wined3d: Add some surface flags.
[wine/gsoc_dplay.git] / dlls / wined3d / device.c
blob64c77f90743a8f475b203a3715b0f0151d3eadb6
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 glBlendColor(col[0], col[1], col[2], col[3]);
298 checkGLcall("glBlendColor");
300 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
301 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
302 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
304 /* TODO: NV_POINT_SPRITE */
305 if (GL_SUPPORT(ARB_POINT_SPRITE)) {
306 if (This->stateBlock->renderState[WINED3DRS_POINTSPRITEENABLE] != FALSE) {
307 /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
308 glDisable(GL_POINT_SMOOTH);
310 /* Centre the texture on the vertex */
311 VTRACE(("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n"));
312 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
314 VTRACE(("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n"));
315 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
316 checkGLcall("glTexEnvf(...)");
317 VTRACE(("glEnable( GL_POINT_SPRITE_ARB )\n"));
318 glEnable( GL_POINT_SPRITE_ARB );
319 checkGLcall("glEnable(...)");
320 } else {
321 VTRACE(("glDisable( GL_POINT_SPRITE_ARB )\n"));
322 glDisable( GL_POINT_SPRITE_ARB );
323 checkGLcall("glEnable(...)");
327 TRACE("-----------------------> Updated the texture at Sampler %ld to have new texture state information\n", Sampler);
330 /**********************************************************
331 * IUnknown parts follows
332 **********************************************************/
334 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
336 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
338 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
339 if (IsEqualGUID(riid, &IID_IUnknown)
340 || IsEqualGUID(riid, &IID_IWineD3DBase)
341 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
342 IUnknown_AddRef(iface);
343 *ppobj = This;
344 return S_OK;
346 *ppobj = NULL;
347 return E_NOINTERFACE;
350 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
351 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
352 ULONG refCount = InterlockedIncrement(&This->ref);
354 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
355 return refCount;
358 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
359 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
360 ULONG refCount = InterlockedDecrement(&This->ref);
362 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
364 if (!refCount) {
365 /* TODO: Clean up all the surfaces and textures! */
366 /* NOTE: You must release the parent if the object was created via a callback
367 ** ***************************/
369 /* Release the update stateblock */
370 if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){
371 if(This->updateStateBlock != This->stateBlock)
372 FIXME("(%p) Something's still holding the Update stateblock\n",This);
374 This->updateStateBlock = NULL;
375 { /* because were not doing proper internal refcounts releasing the primary state block
376 causes recursion with the extra checks in ResourceReleased, to avoid this we have
377 to set this->stateBlock = NULL; first */
378 IWineD3DStateBlock *stateBlock = (IWineD3DStateBlock *)This->stateBlock;
379 This->stateBlock = NULL;
381 /* Release the stateblock */
382 if(IWineD3DStateBlock_Release(stateBlock) > 0){
383 FIXME("(%p) Something's still holding the Update stateblock\n",This);
387 if (This->resources != NULL ) {
388 FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This);
389 dumpResources(This->resources);
393 IWineD3D_Release(This->wineD3D);
394 This->wineD3D = NULL;
395 HeapFree(GetProcessHeap(), 0, This);
396 TRACE("Freed device %p\n", This);
397 This = NULL;
399 return refCount;
402 /**********************************************************
403 * IWineD3DDevice implementation follows
404 **********************************************************/
405 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
406 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
407 *pParent = This->parent;
408 IUnknown_AddRef(This->parent);
409 return WINED3D_OK;
412 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
413 DWORD FVF, WINED3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
414 IUnknown *parent) {
415 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
416 IWineD3DVertexBufferImpl *object;
417 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
418 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, WINED3DRTYPE_VERTEXBUFFER, Size)
420 /*TODO: use VBO's */
421 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
422 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
424 object->fvf = FVF;
426 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
427 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
429 return WINED3D_OK;
432 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
433 WINED3DFORMAT Format, WINED3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
434 HANDLE *sharedHandle, IUnknown *parent) {
435 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
436 IWineD3DIndexBufferImpl *object;
437 TRACE("(%p) Creating index buffer\n", This);
439 /* Allocate the storage for the device */
440 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,WINED3DRTYPE_INDEXBUFFER, Length)
442 /*TODO: use VBO's */
443 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
444 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
447 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
448 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
449 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
451 return WINED3D_OK;
454 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
456 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
457 IWineD3DStateBlockImpl *object;
458 int i, j;
460 D3DCREATEOBJECTINSTANCE(object, StateBlock)
461 object->blockType = Type;
463 /* Special case - Used during initialization to produce a placeholder stateblock
464 so other functions called can update a state block */
465 if (Type == WINED3DSBT_INIT) {
466 /* Don't bother increasing the reference count otherwise a device will never
467 be freed due to circular dependencies */
468 return WINED3D_OK;
471 /* Otherwise, might as well set the whole state block to the appropriate values */
472 if ( This->stateBlock != NULL) {
473 memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
474 } else {
475 memset(object->streamFreq, 1, sizeof(object->streamFreq));
478 /* Reset the ref and type after kludging it */
479 object->wineD3DDevice = This;
480 object->ref = 1;
481 object->blockType = Type;
483 TRACE("Updating changed flags appropriate for type %d\n", Type);
485 if (Type == WINED3DSBT_ALL) {
487 TRACE("ALL => Pretend everything has changed\n");
488 memset(&object->changed, TRUE, sizeof(This->stateBlock->changed));
489 } else if (Type == WINED3DSBT_PIXELSTATE) {
491 TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
492 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
494 object->changed.pixelShader = TRUE;
496 /* Pixel Shader Constants */
497 for (i = 0; i < MAX_PSHADER_CONSTANTS; ++i) {
498 object->changed.pixelShaderConstants[i] = TRUE;
500 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
501 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
503 for (j = 0; j < GL_LIMITS(textures); j++) {
504 for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
505 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
508 for (j = 0 ; j < 16; j++) {
509 for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
511 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
515 } else if (Type == WINED3DSBT_VERTEXSTATE) {
517 TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
518 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
520 object->changed.vertexShader = TRUE;
522 /* Vertex Shader Constants */
523 for (i = 0; i < MAX_VSHADER_CONSTANTS; ++i) {
524 object->changed.vertexShaderConstants[i] = TRUE;
526 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
527 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
529 for (j = 0; j < GL_LIMITS(textures); j++) {
530 for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
531 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
534 for (j = 0 ; j < 16; j++){
535 for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
536 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
540 /* Duplicate light chain */
542 PLIGHTINFOEL *src = NULL;
543 PLIGHTINFOEL *dst = NULL;
544 PLIGHTINFOEL *newEl = NULL;
545 src = This->stateBlock->lights;
546 object->lights = NULL;
549 while (src) {
550 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
551 if (newEl == NULL) return WINED3DERR_OUTOFVIDEOMEMORY;
552 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
553 newEl->prev = dst;
554 newEl->changed = TRUE;
555 newEl->enabledChanged = TRUE;
556 if (dst == NULL) {
557 object->lights = newEl;
558 } else {
559 dst->next = newEl;
561 dst = newEl;
562 src = src->next;
567 } else {
568 FIXME("Unrecognized state block type %d\n", Type);
571 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
572 return WINED3D_OK;
576 /* ************************************
577 MSDN:
578 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
580 Discard
581 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
583 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.
585 ******************************** */
587 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) {
588 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
589 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
590 unsigned int pow2Width, pow2Height;
591 unsigned int Size = 1;
592 TRACE("(%p) Create surface\n",This);
594 /** FIXME: Check ranges on the inputs are valid
595 * MSDN
596 * MultisampleQuality
597 * [in] Quality level. The valid range is between zero and one less than the level
598 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
599 * Passing a larger value returns the error WINED3DERR_INVALIDCALL. The MultisampleQuality
600 * values of paired render targets, depth stencil surfaces, and the MultiSample type
601 * must all match.
602 *******************************/
606 * TODO: Discard MSDN
607 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
609 * If this flag is set, the contents of the depth stencil buffer will be
610 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
611 * with a different depth surface.
613 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
614 ***************************/
616 if(MultisampleQuality < 0) {
617 FIXME("Invalid multisample level %ld\n", MultisampleQuality);
618 return WINED3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
621 if(MultisampleQuality > 0) {
622 FIXME("MultisampleQuality set to %ld, substituting 0\n", MultisampleQuality);
623 MultisampleQuality=0;
626 /** FIXME: Check that the format is supported
627 * by the device.
628 *******************************/
630 /* Non-power2 support */
632 /* Find the nearest pow2 match */
633 pow2Width = pow2Height = 1;
634 while (pow2Width < Width) pow2Width <<= 1;
635 while (pow2Height < Height) pow2Height <<= 1;
637 if (pow2Width > Width || pow2Height > Height) {
638 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
639 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
640 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
641 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
642 This, Width, Height);
643 return WINED3DERR_NOTAVAILABLE;
647 /** Check against the maximum texture sizes supported by the video card **/
648 if (pow2Width > GL_LIMITS(texture_size) || pow2Height > GL_LIMITS(texture_size)) {
649 /* one of three options
650 1: Do the same as we do with nonpow 2 and scale the texture, (any texture ops would require the texture to be scaled which is potentially slow)
651 2: Set the texture to the maxium size (bad idea)
652 3: WARN and return WINED3DERR_NOTAVAILABLE;
654 WARN("(%p) Application requested a surface w %d, h %d, but the graphics card only supports %d\n", This, Width, Height, GL_LIMITS(texture_size));
655 return WINED3DERR_NOTAVAILABLE;
660 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
661 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
662 * space!
663 *********************************/
664 if (WINED3DFMT_UNKNOWN == Format) {
665 Size = 0;
666 } else if (Format == WINED3DFMT_DXT1) {
667 /* DXT1 is half byte per pixel */
668 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4)) >> 1;
670 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
671 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
672 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4));
673 } else {
674 Size = (pow2Width * D3DFmtGetBpp(This, Format)) * pow2Height;
677 /** Create and initialise the surface resource **/
678 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,WINED3DRTYPE_SURFACE, Size)
679 /* "Standalone" surface */
680 IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL);
682 object->currentDesc.Width = Width;
683 object->currentDesc.Height = Height;
684 object->currentDesc.MultiSampleType = MultiSample;
685 object->currentDesc.MultiSampleQuality = MultisampleQuality;
687 /* Setup some glformat defaults */
688 if (WINED3DFMT_UNKNOWN != Format) {
689 object->glDescription.glFormat = D3DFmt2GLFmt(This, object->resource.format);
690 object->glDescription.glFormatInternal = D3DFmt2GLIntFmt(This, object->resource.format);
691 object->glDescription.glType = D3DFmt2GLType(This, object->resource.format);
692 } else {
693 object->glDescription.glFormat = 0;
694 object->glDescription.glFormatInternal = 0;
695 object->glDescription.glType = 0;
698 object->glDescription.textureName = 0;
699 object->glDescription.level = Level;
700 object->glDescription.target = GL_TEXTURE_2D;
702 /* Internal data */
703 object->pow2Width = pow2Width;
704 object->pow2Height = pow2Height;
706 /* Flags */
707 object->Flags = 0; /* We start without flags set */
708 object->Flags |= (pow2Width != Width || pow2Height != Height) ? SFLAG_NONPOW2 : 0;
709 object->Flags |= Discard ? SFLAG_DISCARD : 0;
710 object->Flags |= (WINED3DFMT_D16_LOCKABLE == Format) ? SFLAG_LOCKABLE : 0;
711 object->Flags |= Lockable ? SFLAG_LOCKABLE : 0;
714 if (WINED3DFMT_UNKNOWN != Format) {
715 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
716 object->pow2Size = (pow2Width * object->bytesPerPixel) * pow2Height;
717 } else {
718 object->bytesPerPixel = 0;
719 object->pow2Size = 0;
722 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
724 TRACE("Pool %d %d %d %d",Pool, WINED3DPOOL_DEFAULT, WINED3DPOOL_MANAGED, WINED3DPOOL_SYSTEMMEM);
726 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
727 * this function is too deap to need to care about things like this.
728 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
729 * ****************************************/
730 switch(Pool) {
731 case WINED3DPOOL_SCRATCH:
732 if(Lockable == FALSE)
733 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
734 which are mutually exclusive, setting lockable to true\n");
735 Lockable = TRUE;
736 break;
737 case WINED3DPOOL_SYSTEMMEM:
738 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
739 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
740 case WINED3DPOOL_MANAGED:
741 if(Usage == WINED3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
742 Usage of DYNAMIC which are mutually exclusive, not doing \
743 anything just telling you.\n");
744 break;
745 case WINED3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
746 if(!(Usage & WINED3DUSAGE_DYNAMIC) && !(Usage & WINED3DUSAGE_RENDERTARGET)
747 && !(Usage && WINED3DUSAGE_DEPTHSTENCIL ) && Lockable == TRUE)
748 FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
749 break;
750 default:
751 FIXME("(%p) Unknown pool %d\n", This, Pool);
752 break;
755 if (Usage & WINED3DUSAGE_RENDERTARGET && Pool != WINED3DPOOL_DEFAULT) {
756 FIXME("Trying to create a render target that isn't in the default pool\n");
759 /* mark the texture as dirty so that it get's loaded first time around*/
760 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
761 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
762 This, Width, Height, Format, debug_d3dformat(Format),
763 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
764 return WINED3D_OK;
768 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
769 DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
770 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
771 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
773 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
774 IWineD3DTextureImpl *object;
775 unsigned int i;
776 UINT tmpW;
777 UINT tmpH;
778 HRESULT hr;
779 unsigned int pow2Width = Width;
780 unsigned int pow2Height = Height;
783 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) ....\n", This, Width, Height, Levels, Usage);
785 /* TODO: It should only be possible to create textures for formats
786 that are reported as supported */
787 if (WINED3DFMT_UNKNOWN >= Format) {
788 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
789 return WINED3DERR_INVALIDCALL;
792 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, WINED3DRTYPE_TEXTURE, 0);
793 D3DINITIALIZEBASETEXTURE(object->baseTexture);
794 object->width = Width;
795 object->height = Height;
797 /** Non-power2 support **/
798 /* Find the nearest pow2 match */
799 pow2Width = pow2Height = 1;
800 while (pow2Width < Width) pow2Width <<= 1;
801 while (pow2Height < Height) pow2Height <<= 1;
803 /** FIXME: add support for real non-power-two if it's provided by the video card **/
804 /* Precalculated scaling for 'faked' non power of two texture coords */
805 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
806 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
807 TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
809 /* Calculate levels for mip mapping */
810 if (Levels == 0) {
811 TRACE("calculating levels %d\n", object->baseTexture.levels);
812 object->baseTexture.levels++;
813 tmpW = Width;
814 tmpH = Height;
815 while (tmpW > 1 || tmpH > 1) {
816 tmpW = max(1, tmpW >> 1);
817 tmpH = max(1, tmpH >> 1);
818 object->baseTexture.levels++;
820 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
823 /* Generate all the surfaces */
824 tmpW = Width;
825 tmpH = Height;
826 for (i = 0; i < object->baseTexture.levels; i++)
828 /* use the callback to create the texture surface */
829 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
830 if (hr!= WINED3D_OK) {
831 int j;
832 FIXME("Failed to create surface %p\n", object);
833 /* clean up */
834 for (j = 0 ; j < i ; j++) {
835 IWineD3DSurface_Release(object->surfaces[j]);
837 /* heap free object */
838 HeapFree(GetProcessHeap(), 0, object);
840 *ppTexture = NULL;
841 return hr;
844 IWineD3DSurface_SetContainer(object->surfaces[i], (IWineD3DBase *)object);
845 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
846 /* calculate the next mipmap level */
847 tmpW = max(1, tmpW >> 1);
848 tmpH = max(1, tmpH >> 1);
851 TRACE("(%p) : Created texture %p\n", This, object);
852 return WINED3D_OK;
855 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
856 UINT Width, UINT Height, UINT Depth,
857 UINT Levels, DWORD Usage,
858 WINED3DFORMAT Format, WINED3DPOOL Pool,
859 IWineD3DVolumeTexture **ppVolumeTexture,
860 HANDLE *pSharedHandle, IUnknown *parent,
861 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
863 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
864 IWineD3DVolumeTextureImpl *object;
865 unsigned int i;
866 UINT tmpW;
867 UINT tmpH;
868 UINT tmpD;
870 /* TODO: It should only be possible to create textures for formats
871 that are reported as supported */
872 if (WINED3DFMT_UNKNOWN >= Format) {
873 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
874 return WINED3DERR_INVALIDCALL;
877 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, WINED3DRTYPE_VOLUMETEXTURE, 0);
878 D3DINITIALIZEBASETEXTURE(object->baseTexture);
880 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
881 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
883 object->width = Width;
884 object->height = Height;
885 object->depth = Depth;
887 /* Calculate levels for mip mapping */
888 if (Levels == 0) {
889 object->baseTexture.levels++;
890 tmpW = Width;
891 tmpH = Height;
892 tmpD = Depth;
893 while (tmpW > 1 || tmpH > 1 || tmpD > 1) {
894 tmpW = max(1, tmpW >> 1);
895 tmpH = max(1, tmpH >> 1);
896 tmpD = max(1, tmpD >> 1);
897 object->baseTexture.levels++;
899 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
902 /* Generate all the surfaces */
903 tmpW = Width;
904 tmpH = Height;
905 tmpD = Depth;
907 for (i = 0; i < object->baseTexture.levels; i++)
909 /* Create the volume */
910 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
911 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
913 /* Set it's container to this object */
914 IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)object);
916 /* calcualte the next mipmap level */
917 tmpW = max(1, tmpW >> 1);
918 tmpH = max(1, tmpH >> 1);
919 tmpD = max(1, tmpD >> 1);
922 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
923 TRACE("(%p) : Created volume texture %p\n", This, object);
924 return WINED3D_OK;
927 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
928 UINT Width, UINT Height, UINT Depth,
929 DWORD Usage,
930 WINED3DFORMAT Format, WINED3DPOOL Pool,
931 IWineD3DVolume** ppVolume,
932 HANDLE* pSharedHandle, IUnknown *parent) {
934 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
935 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
937 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, WINED3DRTYPE_VOLUME, ((Width * D3DFmtGetBpp(This, Format)) * Height * Depth))
939 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
940 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
942 object->currentDesc.Width = Width;
943 object->currentDesc.Height = Height;
944 object->currentDesc.Depth = Depth;
945 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
947 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
948 object->lockable = TRUE;
949 object->locked = FALSE;
950 memset(&object->lockedBox, 0, sizeof(WINED3DBOX));
951 object->dirty = TRUE;
953 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
956 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
957 UINT Levels, DWORD Usage,
958 WINED3DFORMAT Format, WINED3DPOOL Pool,
959 IWineD3DCubeTexture **ppCubeTexture,
960 HANDLE *pSharedHandle, IUnknown *parent,
961 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
963 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
964 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
965 unsigned int i, j;
966 UINT tmpW;
967 HRESULT hr;
968 unsigned int pow2EdgeLength = EdgeLength;
970 /* TODO: It should only be possible to create textures for formats
971 that are reported as supported */
972 if (WINED3DFMT_UNKNOWN >= Format) {
973 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
974 return WINED3DERR_INVALIDCALL;
977 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, WINED3DRTYPE_CUBETEXTURE, 0);
978 D3DINITIALIZEBASETEXTURE(object->baseTexture);
980 TRACE("(%p) Create Cube Texture\n", This);
982 /** Non-power2 support **/
984 /* Find the nearest pow2 match */
985 pow2EdgeLength = 1;
986 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
988 object->edgeLength = EdgeLength;
989 /* TODO: support for native non-power 2 */
990 /* Precalculated scaling for 'faked' non power of two texture coords */
991 object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
993 /* Calculate levels for mip mapping */
994 if (Levels == 0) {
995 object->baseTexture.levels++;
996 tmpW = EdgeLength;
997 while (tmpW > 1) {
998 tmpW = max(1, tmpW >> 1);
999 object->baseTexture.levels++;
1001 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1004 /* Generate all the surfaces */
1005 tmpW = EdgeLength;
1006 for (i = 0; i < object->baseTexture.levels; i++) {
1008 /* Create the 6 faces */
1009 for (j = 0; j < 6; j++) {
1011 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
1012 i /* Level */, &object->surfaces[j][i],pSharedHandle);
1014 if(hr!= WINED3D_OK) {
1015 /* clean up */
1016 int k;
1017 int l;
1018 for (l = 0; l < j; l++) {
1019 IWineD3DSurface_Release(object->surfaces[j][i]);
1021 for (k = 0; k < i; k++) {
1022 for (l = 0; l < 6; l++) {
1023 IWineD3DSurface_Release(object->surfaces[l][j]);
1027 FIXME("(%p) Failed to create surface\n",object);
1028 HeapFree(GetProcessHeap(),0,object);
1029 *ppCubeTexture = NULL;
1030 return hr;
1032 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IWineD3DBase *)object);
1033 TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1035 tmpW = max(1, tmpW >> 1);
1038 TRACE("(%p) : Created Cube Texture %p\n", This, object);
1039 *ppCubeTexture = (IWineD3DCubeTexture *) object;
1040 return WINED3D_OK;
1043 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1044 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1045 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1047 if (NULL == ppQuery) {
1048 /* Just a check to see if we support this type of query */
1049 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1050 switch(Type) {
1051 case WINED3DQUERYTYPE_OCCLUSION:
1052 TRACE("(%p) occlusion query\n", This);
1053 if (GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY))
1054 hr = WINED3D_OK;
1055 else
1056 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1057 break;
1058 case WINED3DQUERYTYPE_VCACHE:
1059 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1060 case WINED3DQUERYTYPE_VERTEXSTATS:
1061 case WINED3DQUERYTYPE_EVENT:
1062 case WINED3DQUERYTYPE_TIMESTAMP:
1063 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1064 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1065 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1066 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1067 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1068 case WINED3DQUERYTYPE_PIXELTIMINGS:
1069 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1070 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1071 default:
1072 FIXME("(%p) Unhandled query type %d\n", This, Type);
1074 return hr;
1077 D3DCREATEOBJECTINSTANCE(object, Query)
1078 object->type = Type;
1079 /* allocated the 'extended' data based on the type of query requested */
1080 switch(Type){
1081 case D3DQUERYTYPE_OCCLUSION:
1082 if(GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY)) {
1083 TRACE("(%p) Allocating data for an occlusion query\n", This);
1084 object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1085 break;
1087 case D3DQUERYTYPE_VCACHE:
1088 case D3DQUERYTYPE_RESOURCEMANAGER:
1089 case D3DQUERYTYPE_VERTEXSTATS:
1090 case D3DQUERYTYPE_EVENT:
1091 case D3DQUERYTYPE_TIMESTAMP:
1092 case D3DQUERYTYPE_TIMESTAMPDISJOINT:
1093 case D3DQUERYTYPE_TIMESTAMPFREQ:
1094 case D3DQUERYTYPE_PIPELINETIMINGS:
1095 case D3DQUERYTYPE_INTERFACETIMINGS:
1096 case D3DQUERYTYPE_VERTEXTIMINGS:
1097 case D3DQUERYTYPE_PIXELTIMINGS:
1098 case D3DQUERYTYPE_BANDWIDTHTIMINGS:
1099 case D3DQUERYTYPE_CACHEUTILIZATION:
1100 default:
1101 object->extendedData = 0;
1102 FIXME("(%p) Unhandled query type %d\n",This , Type);
1104 TRACE("(%p) : Created Query %p\n", This, object);
1105 return WINED3D_OK;
1108 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1109 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1110 IUnknown* parent,
1111 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1112 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1113 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1115 HDC hDc;
1116 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1117 int num;
1118 XVisualInfo template;
1119 GLXContext oldContext;
1120 Drawable oldDrawable;
1121 HRESULT hr = WINED3D_OK;
1123 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1125 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1126 * does a device hold a reference to a swap chain giving them a lifetime of the device
1127 * or does the swap chain notify the device of its destruction.
1128 *******************************/
1130 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1132 /* Initialize other useful values */
1133 object->presentParms.BackBufferCount = 1; /* TODO:? support for gl_aux buffers */
1135 /*********************
1136 * Lookup the window Handle and the relating X window handle
1137 ********************/
1139 /* Setup hwnd we are using, plus which display this equates to */
1140 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1141 if (!object->win_handle) {
1142 object->win_handle = This->createParms.hFocusWindow;
1145 object->win_handle = GetAncestor(object->win_handle, GA_ROOT);
1146 if ( !( object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window") ) ) {
1147 ERR("Can't get drawable (window), HWND:%p doesn't have the property __wine_x11_whole_window\n", object->win_handle);
1148 return WINED3DERR_NOTAVAILABLE;
1150 hDc = GetDC(object->win_handle);
1151 object->display = get_display(hDc);
1152 ReleaseDC(object->win_handle, hDc);
1153 TRACE("Using a display of %p %p\n", object->display, hDc);
1155 if (NULL == object->display || NULL == hDc) {
1156 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1157 return WINED3DERR_NOTAVAILABLE;
1160 if (object->win == 0) {
1161 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1162 return WINED3DERR_NOTAVAILABLE;
1165 * Create an opengl context for the display visual
1166 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1167 * use different properties after that point in time. FIXME: How to handle when requested format
1168 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1169 * it chooses is identical to the one already being used!
1170 **********************************/
1172 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1173 ENTER_GL();
1175 /* Create a new context for this swapchain */
1176 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1177 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1178 (or the best possible if none is requested) */
1179 TRACE("Found x visual ID : %ld\n", template.visualid);
1181 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1182 if (NULL == object->visInfo) {
1183 ERR("cannot really get XVisual\n");
1184 LEAVE_GL();
1185 return WINED3DERR_NOTAVAILABLE;
1186 } else {
1187 int n, value;
1188 /* Write out some debug info about the visual/s */
1189 TRACE("Using x visual ID : %ld\n", template.visualid);
1190 TRACE(" visual info: %p\n", object->visInfo);
1191 TRACE(" num items : %d\n", num);
1192 for (n = 0;n < num; n++) {
1193 TRACE("=====item=====: %d\n", n + 1);
1194 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1195 TRACE(" screen : %d\n", object->visInfo[n].screen);
1196 TRACE(" depth : %u\n", object->visInfo[n].depth);
1197 TRACE(" class : %d\n", object->visInfo[n].class);
1198 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1199 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1200 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1201 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1202 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1203 /* log some extra glx info */
1204 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1205 TRACE(" gl_aux_buffers : %d\n", value);
1206 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1207 TRACE(" gl_buffer_size : %d\n", value);
1208 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1209 TRACE(" gl_red_size : %d\n", value);
1210 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1211 TRACE(" gl_green_size : %d\n", value);
1212 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1213 TRACE(" gl_blue_size : %d\n", value);
1214 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1215 TRACE(" gl_alpha_size : %d\n", value);
1216 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1217 TRACE(" gl_depth_size : %d\n", value);
1218 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1219 TRACE(" gl_stencil_size : %d\n", value);
1221 /* Now choose a simila visual ID*/
1223 #ifdef USE_CONTEXT_MANAGER
1225 /** TODO: use a context mamager **/
1226 #endif
1229 IWineD3DSwapChain *implSwapChain;
1230 if (WINED3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1231 /* The first time around we create the context that is shared with all other swapchains and render targets */
1232 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1233 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1234 } else {
1236 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1237 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1238 /* and create a new context with the implicit swapchains context as the shared context */
1239 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1240 IWineD3DSwapChain_Release(implSwapChain);
1244 /* Cleanup */
1245 XFree(object->visInfo);
1246 object->visInfo = NULL;
1248 if (NULL == object->glCtx) {
1249 ERR("cannot create glxContext\n");
1250 LEAVE_GL();
1251 return WINED3DERR_NOTAVAILABLE;
1254 LEAVE_GL();
1255 if (object->glCtx == NULL) {
1256 ERR("Error in context creation !\n");
1257 return WINED3DERR_INVALIDCALL;
1258 } else {
1259 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1260 object->win_handle, object->glCtx, object->win, object->visInfo);
1263 /*********************
1264 * Windowed / Fullscreen
1265 *******************/
1268 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1269 * so we should really check to see if there is a fullscreen swapchain already
1270 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1271 **************************************/
1273 if (!*(pPresentationParameters->Windowed)) {
1275 DEVMODEW devmode;
1276 HDC hdc;
1277 int bpp = 0;
1279 /* Get info on the current display setup */
1280 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1281 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1282 DeleteDC(hdc);
1284 /* Change the display settings */
1285 memset(&devmode, 0, sizeof(DEVMODEW));
1286 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1287 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1288 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1289 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1290 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1291 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1293 /* Make popup window */
1294 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1295 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1296 *(pPresentationParameters->BackBufferWidth),
1297 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1303 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1304 * then the corresponding dimension of the client area of the hDeviceWindow
1305 * (or the focus window, if hDeviceWindow is NULL) is taken.
1306 **********************/
1308 if (*(pPresentationParameters->Windowed) &&
1309 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1310 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1312 RECT Rect;
1313 GetClientRect(object->win_handle, &Rect);
1315 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1316 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1317 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1319 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1320 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1321 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1325 /*********************
1326 * finish off parameter initialization
1327 *******************/
1329 /* Put the correct figures in the presentation parameters */
1330 TRACE("Coppying accross presentaion paraneters\n");
1331 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1332 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1333 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1334 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1335 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1336 object->presentParms.MultiSampleQuality = NULL == pPresentationParameters->MultiSampleQuality ? 0 : *(pPresentationParameters->MultiSampleQuality);
1337 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1338 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1339 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1340 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1341 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1342 object->presentParms.Flags = *(pPresentationParameters->Flags);
1343 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1344 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1347 /*********************
1348 * Create the back, front and stencil buffers
1349 *******************/
1350 TRACE("calling rendertarget CB\n");
1351 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1352 object->presentParms.BackBufferWidth,
1353 object->presentParms.BackBufferHeight,
1354 object->presentParms.BackBufferFormat,
1355 object->presentParms.MultiSampleType,
1356 object->presentParms.MultiSampleQuality,
1357 TRUE /* Lockable */,
1358 &object->frontBuffer,
1359 NULL /* pShared (always null)*/);
1360 if (object->frontBuffer != NULL)
1361 IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
1362 TRACE("calling rendertarget CB\n");
1363 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1364 object->presentParms.BackBufferWidth,
1365 object->presentParms.BackBufferHeight,
1366 object->presentParms.BackBufferFormat,
1367 object->presentParms.MultiSampleType,
1368 object->presentParms.MultiSampleQuality,
1369 TRUE /* Lockable */,
1370 &object->backBuffer,
1371 NULL /* pShared (always null)*/);
1372 if (object->backBuffer != NULL)
1373 IWineD3DSurface_SetContainer(object->backBuffer, (IWineD3DBase *)object);
1375 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1376 if (pPresentationParameters->EnableAutoDepthStencil) {
1377 TRACE("Creating depth stencil buffer\n");
1378 if (This->depthStencilBuffer == NULL ) {
1379 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1380 object->presentParms.BackBufferWidth,
1381 object->presentParms.BackBufferHeight,
1382 object->presentParms.AutoDepthStencilFormat,
1383 object->presentParms.MultiSampleType,
1384 object->presentParms.MultiSampleQuality,
1385 FALSE /* FIXME: Discard */,
1386 &This->depthStencilBuffer,
1387 NULL /* pShared (always null)*/ );
1388 if (This->depthStencilBuffer != NULL)
1389 IWineD3DSurface_SetContainer(This->depthStencilBuffer, 0);
1392 /** TODO: A check on width, height and multisample types
1393 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1394 ****************************/
1395 object->wantsDepthStencilBuffer = TRUE;
1396 } else {
1397 object->wantsDepthStencilBuffer = FALSE;
1400 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1403 /*********************
1404 * init the default renderTarget management
1405 *******************/
1406 object->drawable = object->win;
1407 object->render_ctx = object->glCtx;
1409 if (hr == WINED3D_OK) {
1410 /*********************
1411 * Setup some defaults and clear down the buffers
1412 *******************/
1413 ENTER_GL();
1414 /** save current context and drawable **/
1415 oldContext = glXGetCurrentContext();
1416 oldDrawable = glXGetCurrentDrawable();
1418 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1419 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1420 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1422 checkGLcall("glXMakeCurrent");
1424 TRACE("Setting up the screen\n");
1425 /* Clear the screen */
1426 glClearColor(1.0, 0.0, 0.0, 0.0);
1427 checkGLcall("glClearColor");
1428 glClearIndex(0);
1429 glClearDepth(1);
1430 glClearStencil(0xffff);
1432 checkGLcall("glClear");
1434 glColor3f(1.0, 1.0, 1.0);
1435 checkGLcall("glColor3f");
1437 glEnable(GL_LIGHTING);
1438 checkGLcall("glEnable");
1440 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1441 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1443 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1444 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1446 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1447 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1449 /* switch back to the original context (if there was one)*/
1450 if (This->swapchains != NULL) {
1451 /** TODO: restore the context and drawable **/
1452 glXMakeCurrent(object->display, oldDrawable, oldContext);
1455 LEAVE_GL();
1457 { /* Finally add the swapchain to the end of the devices' swapchain list */
1458 SwapChainList **nextSwapchain;
1459 nextSwapchain = &This->swapchains;
1460 while (*nextSwapchain != NULL) {
1461 nextSwapchain = &((*nextSwapchain)->next);
1463 (*nextSwapchain) = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->swapchains));
1464 (*nextSwapchain)->swapchain = (IWineD3DSwapChain *)object;
1466 TRACE("Set swapchain to %p\n", object);
1467 } else { /* something went wrong so clean up */
1468 IUnknown* bufferParent;
1469 if (object->frontBuffer) {
1471 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1472 IUnknown_Release(bufferParent); /* once for the get parent */
1473 if (IUnknown_Release(bufferParent) > 0) {
1474 FIXME("(%p) Something's still holding the front buffer\n",This);
1477 if (object->backBuffer) {
1478 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1479 IUnknown_Release(bufferParent); /* once for the get parent */
1480 if (IUnknown_Release(bufferParent) > 0) {
1481 FIXME("(%p) Something's still holding the back buffer\n",This);
1484 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1485 /* Clean up the context */
1486 /* check that we are the current context first (we shouldn't be though!) */
1487 if (object->glCtx != 0) {
1488 if(glXGetCurrentContext() == object->glCtx) {
1489 glXMakeCurrent(object->display, None, NULL);
1491 glXDestroyContext(object->display, object->glCtx);
1493 HeapFree(GetProcessHeap(), 0, object);
1497 return hr;
1500 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1501 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1502 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1503 unsigned int numberOfSwapChains = 0;
1504 SwapChainList *swapchain;
1506 swapchain = This->swapchains;
1507 /* itterate through the list to get a count */
1508 while (swapchain != NULL) {
1509 swapchain = swapchain->next;
1510 numberOfSwapChains++;
1513 TRACE("(%p) returning %d\n", This, numberOfSwapChains);
1514 return numberOfSwapChains;
1517 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1518 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1519 SwapChainList *swapchain;
1520 int i = iSwapChain;
1521 HRESULT hr = WINED3DERR_INVALIDCALL;
1522 swapchain = This->swapchains;
1523 TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1526 TRACE("(%p) Finding swapchain %d\n", This, iSwapChain);
1527 while (i > 0 && swapchain != NULL) {
1528 swapchain = swapchain->next;
1529 --i;
1532 if (i > 0) {
1533 FIXME("(%p) Unable to find swapchain %d\n", This, iSwapChain);
1534 *pSwapChain = NULL;
1535 } else if (swapchain != NULL) {
1536 /** TODO: move off to a linkesList implementation **/
1537 *pSwapChain = swapchain->swapchain;
1538 IWineD3DSwapChain_AddRef(*pSwapChain);
1539 hr = WINED3D_OK;
1542 TRACE("(%p) returning %p\n", This, *pSwapChain);
1543 return hr;
1546 /*****
1547 * Vertex Declaration
1548 *****/
1549 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1550 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1551 IWineD3DVertexDeclarationImpl *object = NULL;
1552 HRESULT hr = WINED3D_OK;
1553 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1554 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1555 object->allFVF = 0;
1557 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1559 return hr;
1562 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1563 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pDeclaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1564 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1565 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1566 HRESULT hr = WINED3D_OK;
1567 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1568 object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins;
1570 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1572 /* If a vertex declaration has been passed, save it to the vertex shader, this affects d3d8 only. */
1573 /* Further it needs to be set before calling SetFunction as SetFunction needs the declaration. */
1574 if (pDeclaration != NULL) {
1575 IWineD3DVertexDeclaration *vertexDeclaration;
1576 hr = IWineD3DDevice_CreateVertexDeclaration(iface, pDeclaration, &vertexDeclaration ,NULL);
1577 if (WINED3D_OK == hr) {
1578 TRACE("(%p) : Setting vertex declaration to %p\n", This, vertexDeclaration);
1579 object->vertexDeclaration = vertexDeclaration;
1580 } else {
1581 FIXME("(%p) : Failed to set the declaration, returning WINED3DERR_INVALIDCALL\n", iface);
1582 IWineD3DVertexShader_Release(*ppVertexShader);
1583 return WINED3DERR_INVALIDCALL;
1587 hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1589 if (WINED3D_OK != hr) {
1590 FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface);
1591 IWineD3DVertexShader_Release(*ppVertexShader);
1592 return WINED3DERR_INVALIDCALL;
1595 #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. */
1596 if(Usage == WINED3DUSAGE_SOFTWAREVERTEXPROCESSING) {
1597 /* Foo */
1598 } else {
1599 /* Bar */
1602 #endif
1604 return WINED3D_OK;
1607 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
1608 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1609 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1610 HRESULT hr = WINED3D_OK;
1612 D3DCREATEOBJECTINSTANCE(object, PixelShader)
1613 object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins;
1614 hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
1615 if (WINED3D_OK == hr) {
1616 TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
1617 } else {
1618 WARN("(%p) : Failed to create pixel shader\n", This);
1621 return hr;
1624 HRESULT WINAPI IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice *iface, DWORD Flags, PALETTEENTRY *PalEnt, IWineD3DPalette **Palette, IUnknown *Parent) {
1625 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1626 IWineD3DPaletteImpl *object;
1627 HRESULT hr;
1628 TRACE("(%p)->(%lx, %p, %p, %p)\n", This, Flags, PalEnt, Palette, Parent);
1630 /* Create the new object */
1631 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DPaletteImpl));
1632 if(!object) {
1633 ERR("Out of memory when allocating memory for a IWineD3DPalette implementation\n");
1634 return E_OUTOFMEMORY;
1637 object->lpVtbl = &IWineD3DPalette_Vtbl;
1638 object->ref = 1;
1639 object->Flags = Flags;
1640 object->parent = Parent;
1641 object->wineD3DDevice = This;
1642 object->palNumEntries = IWineD3DPaletteImpl_Size(Flags);
1644 object->hpal = CreatePalette((const LOGPALETTE*)&(object->palVersion));
1646 if(!object->hpal) {
1647 HeapFree( GetProcessHeap(), 0, object);
1648 return E_OUTOFMEMORY;
1651 hr = IWineD3DPalette_SetEntries((IWineD3DPalette *) object, 0, 0, IWineD3DPaletteImpl_Size(Flags), PalEnt);
1652 if(FAILED(hr)) {
1653 IWineD3DPalette_Release((IWineD3DPalette *) object);
1654 return hr;
1657 *Palette = (IWineD3DPalette *) object;
1659 return WINED3D_OK;
1662 HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) {
1663 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1664 IWineD3DSwapChainImpl *swapchain;
1666 TRACE("(%p)->(%p,%p)\n", This, pPresentationParameters, D3DCB_CreateAdditionalSwapChain);
1667 if(This->d3d_initialized) return WINED3DERR_INVALIDCALL;
1669 /* TODO: Test if OpenGL is compiled in and loaded */
1671 /* Setup the implicit swapchain */
1672 TRACE("Creating implicit swapchain\n");
1673 if (D3D_OK != D3DCB_CreateAdditionalSwapChain((IUnknown *) This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain) || swapchain == NULL) {
1674 WARN("Failed to create implicit swapchain\n");
1675 return WINED3DERR_INVALIDCALL;
1678 if(swapchain->backBuffer) {
1679 TRACE("Setting rendertarget to %p\n", swapchain->backBuffer);
1680 This->renderTarget = swapchain->backBuffer;
1682 else {
1683 TRACE("Setting rendertarget to %p\n", swapchain->frontBuffer);
1684 This->renderTarget = swapchain->frontBuffer;
1686 IWineD3DSurface_AddRef(This->renderTarget);
1687 /* Depth Stencil support */
1688 This->stencilBufferTarget = This->depthStencilBuffer;
1689 if (NULL != This->stencilBufferTarget) {
1690 IWineD3DSurface_AddRef(This->stencilBufferTarget);
1693 /* Set up some starting GL setup */
1694 ENTER_GL();
1696 * Initialize openGL extension related variables
1697 * with Default values
1700 ((IWineD3DImpl *) This->wineD3D)->isGLInfoValid = IWineD3DImpl_FillGLCaps( &((IWineD3DImpl *) This->wineD3D)->gl_info, swapchain->display);
1701 /* Setup all the devices defaults */
1702 IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)This->stateBlock);
1703 #if 0
1704 IWineD3DImpl_CheckGraphicsMemory();
1705 #endif
1706 LEAVE_GL();
1708 { /* Set a default viewport */
1709 D3DVIEWPORT9 vp;
1710 vp.X = 0;
1711 vp.Y = 0;
1712 vp.Width = *(pPresentationParameters->BackBufferWidth);
1713 vp.Height = *(pPresentationParameters->BackBufferHeight);
1714 vp.MinZ = 0.0f;
1715 vp.MaxZ = 1.0f;
1716 IWineD3DDevice_SetViewport((IWineD3DDevice *)This, &vp);
1720 /* Initialize the current view state */
1721 This->modelview_valid = 1;
1722 This->proj_valid = 0;
1723 This->view_ident = 1;
1724 This->last_was_rhw = 0;
1725 glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights);
1726 TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This, This);
1728 /* Clear the screen */
1729 IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
1731 This->d3d_initialized = TRUE;
1732 return WINED3D_OK;
1735 HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface) {
1736 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1737 int texstage;
1738 IUnknown* stencilBufferParent;
1739 IUnknown* swapChainParent;
1740 SwapChainList *nextSwapchain;
1741 TRACE("(%p)\n", This);
1743 if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL;
1745 for(texstage = 0; texstage < GL_LIMITS(textures); texstage++) {
1746 IWineD3DDevice_SetTexture(iface, texstage, NULL);
1749 /* NOTE: You must release the parent if the object was created via a callback
1750 ** ***************************/
1751 /* Release all of the swapchains, except the implicit swapchain */
1753 /* NOTE: Don't release swapchain 0 here, it's 'special' */
1754 TRACE("Finding implicit swapchain\n");
1755 nextSwapchain = This->swapchains;
1756 if (nextSwapchain != NULL) {
1757 nextSwapchain = nextSwapchain->next;
1758 } else {
1759 WARN("Expected to find the implicit swapchain\n");
1762 TRACE("Releasing swapchains. nextSwapchain = %p\n", nextSwapchain);
1763 /* release all the other swapchains */
1764 while (nextSwapchain != NULL) {
1765 SwapChainList *prevSwapchain = nextSwapchain;
1766 nextSwapchain = nextSwapchain->next;
1767 TRACE("Releasing swapchain %p\n", prevSwapchain->swapchain);
1768 IWineD3DSwapChain_Release(prevSwapchain->swapchain);
1769 /* NOTE: no need to free the list element, it will be done by the release callback
1770 HeapFree(GetProcessHeap(), 0, prevSwapchain); */
1772 /* Release the buffers (with sanity checks)*/
1773 TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget);
1774 if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
1775 if(This->depthStencilBuffer != This->stencilBufferTarget)
1776 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
1778 This->stencilBufferTarget = NULL;
1780 TRACE("Releasing the render target at %p\n", This->renderTarget);
1781 if(IWineD3DSurface_Release(This->renderTarget) >0){
1782 /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
1784 TRACE("Setting rendertarget to NULL\n");
1785 This->renderTarget = NULL;
1787 IWineD3DSurface_GetParent(This->depthStencilBuffer, &stencilBufferParent);
1788 IUnknown_Release(stencilBufferParent); /* once for the get parent */
1789 if(IUnknown_Release(stencilBufferParent) >0){ /* the second time for when it was created */
1790 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
1792 This->depthStencilBuffer = NULL;
1794 TRACE("Releasing the implicit swapchain\n");
1795 if (This->swapchains != NULL) {
1796 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
1797 IWineD3DSwapChain_GetParent(This->swapchains->swapchain, &swapChainParent);
1798 IUnknown_Release(swapChainParent); /* once for the get parent */
1799 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
1800 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
1803 This->swapchains = NULL;
1805 This->d3d_initialized = FALSE;
1806 return WINED3D_OK;
1809 HRESULT WINAPI IWineD3DDeviceImpl_EnumDisplayModes(IWineD3DDevice *iface, DWORD Flags, UINT Width, UINT Height, WINED3DFORMAT pixelformat, LPVOID context, D3DCB_ENUMDISPLAYMODESCALLBACK callback) {
1810 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1812 DEVMODEW DevModeW;
1813 int i;
1815 TRACE("(%p)->(%lx,%d,%d,%d,%p,%p)\n", This, Flags, Width, Height, pixelformat, context, callback);
1817 for (i = 0; EnumDisplaySettingsExW(NULL, i, &DevModeW, 0); i++) {
1818 /* Ignore some modes if a description was passed */
1819 if ( (Width > 0) && (Width != DevModeW.dmPelsWidth)) continue;
1820 if ( (Height > 0) && (Height != DevModeW.dmPelsHeight)) continue;
1821 if ( (pixelformat != WINED3DFMT_UNKNOWN) && ( D3DFmtGetBpp(NULL, pixelformat) != DevModeW.dmBitsPerPel) ) continue;
1823 TRACE("Enumerating %ldx%ld@%s\n", DevModeW.dmPelsWidth, DevModeW.dmPelsHeight, debug_d3dformat(pixelformat_for_depth(DevModeW.dmBitsPerPel)));
1825 if (callback((IUnknown *) This, (UINT) DevModeW.dmPelsWidth, (UINT) DevModeW.dmPelsHeight, pixelformat_for_depth(DevModeW.dmBitsPerPel), 60.0, context) == DDENUMRET_CANCEL)
1826 return D3D_OK;
1829 return D3D_OK;
1832 HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
1833 FIXME("This call is a d3d7 merge stub. It will be implemented later\n");
1834 return WINED3DERR_INVALIDCALL;
1837 HRESULT WINAPI IWineD3DDeviceImpl_EnumZBufferFormats(IWineD3DDevice *iface, D3DCB_ENUMPIXELFORMATS Callback, void *Context) {
1838 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1839 HRESULT ret;
1840 int i = 0;
1841 WINED3DFORMAT FormatList[] = {
1842 WINED3DFMT_D16,
1843 WINED3DFMT_D32,
1844 WINED3DFMT_D24X4S4,
1845 WINED3DFMT_D24S8,
1846 WINED3DFMT_D24X8,
1847 WINED3DFMT_D15S1,
1848 WINED3DFMT_UNKNOWN /* Terminate the list */
1851 TRACE("(%p)->(%p,%p)\n", This, Callback, Context);
1853 while(FormatList[i] != WINED3DFMT_UNKNOWN) {
1854 TRACE("Enumerating %s\n", debug_d3dformat(FormatList[i]));
1855 ret = Callback((IUnknown *) This, FormatList[i], Context);
1856 if(ret != DDENUMRET_OK) {
1857 TRACE("Enumeration cancelled by Application\n");
1858 return WINED3D_OK;
1860 i++;
1863 TRACE("End of Enumeration\n");
1865 return WINED3D_OK;
1868 HRESULT WINAPI IWineD3DDeviceImpl_EnumTextureFormats(IWineD3DDevice *iface, D3DCB_ENUMPIXELFORMATS Callback, void *Context) {
1869 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1870 HRESULT ret;
1871 int i = 0;
1873 /* From old ddraw:
1874 * WINED3DFMT_A1R5G5B5 needs to be the first 16 bit format, as some dumb apps depend on this
1876 * Do not enumerate RGBA pixel formats: "some games choose the first 16 bit texture format
1877 * with alpha they find enumerated, others the last one. And both want to have the ARGB one."
1878 * But WineD3D doesn't support RGBA formats anyway...
1881 WINED3DFORMAT FormatList[] = {
1882 /* 32 bit */
1883 WINED3DFMT_A8R8G8B8,
1884 WINED3DFMT_X8R8G8B8,
1885 /* 24 bit */
1886 WINED3DFMT_R8G8B8,
1887 /* 16 Bit */
1888 WINED3DFMT_A1R5G5B5,
1889 WINED3DFMT_A4R4G4B4,
1890 WINED3DFMT_R5G6B5,
1891 WINED3DFMT_X1R5G5B5,
1892 /* 8 Bit */
1893 WINED3DFMT_R3G3B2,
1894 WINED3DFMT_P8,
1895 /* FOURCC codes */
1896 WINED3DFMT_DXT1,
1897 WINED3DFMT_DXT3,
1898 WINED3DFMT_DXT5,
1899 /* Terminate the list */
1900 WINED3DFMT_UNKNOWN
1903 TRACE("(%p)->(%p,%p)\n", This, Callback, Context);
1905 while(FormatList[i] != WINED3DFMT_UNKNOWN) {
1906 TRACE("Enumerating %s\n", debug_d3dformat(FormatList[i]));
1907 ret = Callback((IUnknown *) This, FormatList[i], Context);
1908 if(ret != DDENUMRET_OK) {
1909 TRACE("Enumeration cancelled by Application\n");
1910 return WINED3D_OK;
1912 i++;
1915 TRACE("End of Enumeration\n");
1917 return WINED3D_OK;
1920 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
1921 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1922 *ppD3D= This->wineD3D;
1923 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1924 IWineD3D_AddRef(*ppD3D);
1925 return WINED3D_OK;
1928 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1929 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1930 * Into the video ram as possible and seeing how many fit
1931 * you can also get the correct initial value from via X and ATI's driver
1932 *******************/
1933 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1934 static BOOL showfixmes = TRUE;
1935 if (showfixmes) {
1936 FIXME("(%p) : stub, emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1937 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1938 showfixmes = FALSE;
1940 TRACE("(%p) : emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1941 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1942 /* videomemory is simulated videomemory + AGP memory left */
1943 return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1948 /*****
1949 * Get / Set FVF
1950 *****/
1951 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1952 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1953 HRESULT hr = WINED3D_OK;
1955 /* Update the current state block */
1956 This->updateStateBlock->fvf = fvf;
1957 This->updateStateBlock->changed.fvf = TRUE;
1958 This->updateStateBlock->set.fvf = TRUE;
1960 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1962 if (0 != fvf) {
1963 /* clear down the vertex declaration
1964 NOTE: Axis and Allies doesn't work properly otherwise
1965 (may be a stateblock problem though!)
1967 hr = IWineD3DDevice_SetVertexDeclaration(iface, NULL);
1970 return hr;
1974 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1975 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1976 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1977 *pfvf = This->stateBlock->fvf;
1978 return WINED3D_OK;
1981 /*****
1982 * Get / Set Stream Source
1983 *****/
1984 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1985 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1986 IWineD3DVertexBuffer *oldSrc;
1988 /**TODO: instance and index data, see
1989 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1991 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
1992 **************/
1994 /* D3d9 only, but shouldn't hurt d3d8 */
1995 UINT streamFlags;
1997 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1998 if (streamFlags) {
1999 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2000 FIXME("stream index data not supported\n");
2002 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2003 FIXME("stream instance data not supported\n");
2007 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2009 if (StreamNumber >= MAX_STREAMS) {
2010 WARN("Stream out of range %d\n", StreamNumber);
2011 return WINED3DERR_INVALIDCALL;
2014 oldSrc = This->stateBlock->streamSource[StreamNumber];
2015 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
2017 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
2018 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
2019 This->updateStateBlock->streamStride[StreamNumber] = Stride;
2020 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
2021 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
2022 This->updateStateBlock->streamFlags[StreamNumber] = streamFlags;
2024 /* Handle recording of state blocks */
2025 if (This->isRecordingState) {
2026 TRACE("Recording... not performing anything\n");
2027 return WINED3D_OK;
2030 /* Not recording... */
2031 /* Need to do a getParent and pass the reffs up */
2032 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
2033 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
2034 so for now, just count internally */
2035 if (pStreamData != NULL) {
2036 IWineD3DVertexBuffer_AddRef(pStreamData);
2038 if (oldSrc != NULL) {
2039 IWineD3DVertexBuffer_Release(oldSrc);
2042 return WINED3D_OK;
2045 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
2046 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2047 UINT streamFlags;
2049 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
2050 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
2053 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2054 if (streamFlags) {
2055 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2056 FIXME("stream index data not supported\n");
2058 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2059 FIXME("stream instance data not supported\n");
2063 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2065 if (StreamNumber >= MAX_STREAMS) {
2066 WARN("Stream out of range %d\n", StreamNumber);
2067 return WINED3DERR_INVALIDCALL;
2069 *pStream = This->stateBlock->streamSource[StreamNumber];
2070 *pStride = This->stateBlock->streamStride[StreamNumber];
2071 *pOffset = This->stateBlock->streamOffset[StreamNumber];
2073 if (*pStream == NULL) {
2074 FIXME("Attempting to get an empty stream %d, returning WINED3DERR_INVALIDCALL\n", StreamNumber);
2075 return WINED3DERR_INVALIDCALL;
2078 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
2079 return WINED3D_OK;
2082 /*Should be quite easy, just an extension of vertexdata
2083 ref...
2084 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2086 The divider is a bit odd though
2088 VertexOffset = StartVertex / Divider * StreamStride +
2089 VertexIndex / Divider * StreamStride + StreamOffset
2092 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
2093 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2095 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
2096 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (D3DSTREAMSOURCE_INSTANCEDATA | D3DSTREAMSOURCE_INDEXEDDATA );
2098 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
2099 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
2100 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
2102 if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
2103 FIXME("Stream indexing not fully supported\n");
2106 return WINED3D_OK;
2109 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
2110 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2112 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
2113 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
2115 TRACE("(%p) : returning %d\n", This, *Divider);
2117 return WINED3D_OK;
2120 /*****
2121 * Get / Set & Multiply Transform
2122 *****/
2123 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
2124 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2126 /* Most of this routine, comments included copied from ddraw tree initially: */
2127 TRACE("(%p) : Transform State=%d\n", This, d3dts);
2129 /* Handle recording of state blocks */
2130 if (This->isRecordingState) {
2131 TRACE("Recording... not performing anything\n");
2132 This->updateStateBlock->changed.transform[d3dts] = TRUE;
2133 This->updateStateBlock->set.transform[d3dts] = TRUE;
2134 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
2135 return WINED3D_OK;
2139 * If the new matrix is the same as the current one,
2140 * we cut off any further processing. this seems to be a reasonable
2141 * optimization because as was noticed, some apps (warcraft3 for example)
2142 * tend towards setting the same matrix repeatedly for some reason.
2144 * From here on we assume that the new matrix is different, wherever it matters.
2146 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
2147 TRACE("The app is setting the same matrix over again\n");
2148 return WINED3D_OK;
2149 } else {
2150 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
2154 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2155 where ViewMat = Camera space, WorldMat = world space.
2157 In OpenGL, camera and world space is combined into GL_MODELVIEW
2158 matrix. The Projection matrix stay projection matrix.
2161 /* Capture the times we can just ignore the change for now */
2162 if (d3dts == D3DTS_WORLDMATRIX(0)) {
2163 This->modelview_valid = FALSE;
2164 return WINED3D_OK;
2166 } else if (d3dts == D3DTS_PROJECTION) {
2167 This->proj_valid = FALSE;
2168 return WINED3D_OK;
2170 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
2171 /* Indexed Vertex Blending Matrices 256 -> 511 */
2172 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
2173 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
2174 return WINED3D_OK;
2177 /* Now we really are going to have to change a matrix */
2178 ENTER_GL();
2180 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
2181 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
2182 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
2183 unsigned int k;
2185 /* If we are changing the View matrix, reset the light and clipping planes to the new view
2186 * NOTE: We have to reset the positions even if the light/plane is not currently
2187 * enabled, since the call to enable it will not reset the position.
2188 * NOTE2: Apparently texture transforms do NOT need reapplying
2191 PLIGHTINFOEL *lightChain = NULL;
2192 This->modelview_valid = FALSE;
2193 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
2195 glMatrixMode(GL_MODELVIEW);
2196 checkGLcall("glMatrixMode(GL_MODELVIEW)");
2197 glPushMatrix();
2198 glLoadMatrixf((float *)lpmatrix);
2199 checkGLcall("glLoadMatrixf(...)");
2201 /* Reset lights */
2202 lightChain = This->stateBlock->lights;
2203 while (lightChain && lightChain->glIndex != -1) {
2204 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
2205 checkGLcall("glLightfv posn");
2206 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
2207 checkGLcall("glLightfv dirn");
2208 lightChain = lightChain->next;
2211 /* Reset Clipping Planes if clipping is enabled */
2212 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2213 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
2214 checkGLcall("glClipPlane");
2216 glPopMatrix();
2218 } else { /* What was requested!?? */
2219 WARN("invalid matrix specified: %i\n", d3dts);
2222 /* Release lock, all done */
2223 LEAVE_GL();
2224 return WINED3D_OK;
2227 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
2228 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2229 TRACE("(%p) : for Transform State %d\n", This, State);
2230 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
2231 return WINED3D_OK;
2234 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
2235 D3DMATRIX *mat = NULL;
2236 D3DMATRIX temp;
2238 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2239 * below means it will be recorded in a state block change, but it
2240 * works regardless where it is recorded.
2241 * If this is found to be wrong, change to StateBlock.
2243 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2244 TRACE("(%p) : For state %u\n", This, State);
2246 if (State < HIGHEST_TRANSFORMSTATE)
2248 mat = &This->updateStateBlock->transforms[State];
2249 } else {
2250 FIXME("Unhandled transform state!!\n");
2253 /* Copied from ddraw code: */
2254 temp.u.s._11 = (mat->u.s._11 * pMatrix->u.s._11) + (mat->u.s._21 * pMatrix->u.s._12) +
2255 (mat->u.s._31 * pMatrix->u.s._13) + (mat->u.s._41 * pMatrix->u.s._14);
2256 temp.u.s._21 = (mat->u.s._11 * pMatrix->u.s._21) + (mat->u.s._21 * pMatrix->u.s._22) +
2257 (mat->u.s._31 * pMatrix->u.s._23) + (mat->u.s._41 * pMatrix->u.s._24);
2258 temp.u.s._31 = (mat->u.s._11 * pMatrix->u.s._31) + (mat->u.s._21 * pMatrix->u.s._32) +
2259 (mat->u.s._31 * pMatrix->u.s._33) + (mat->u.s._41 * pMatrix->u.s._34);
2260 temp.u.s._41 = (mat->u.s._11 * pMatrix->u.s._41) + (mat->u.s._21 * pMatrix->u.s._42) +
2261 (mat->u.s._31 * pMatrix->u.s._43) + (mat->u.s._41 * pMatrix->u.s._44);
2263 temp.u.s._12 = (mat->u.s._12 * pMatrix->u.s._11) + (mat->u.s._22 * pMatrix->u.s._12) +
2264 (mat->u.s._32 * pMatrix->u.s._13) + (mat->u.s._42 * pMatrix->u.s._14);
2265 temp.u.s._22 = (mat->u.s._12 * pMatrix->u.s._21) + (mat->u.s._22 * pMatrix->u.s._22) +
2266 (mat->u.s._32 * pMatrix->u.s._23) + (mat->u.s._42 * pMatrix->u.s._24);
2267 temp.u.s._32 = (mat->u.s._12 * pMatrix->u.s._31) + (mat->u.s._22 * pMatrix->u.s._32) +
2268 (mat->u.s._32 * pMatrix->u.s._33) + (mat->u.s._42 * pMatrix->u.s._34);
2269 temp.u.s._42 = (mat->u.s._12 * pMatrix->u.s._41) + (mat->u.s._22 * pMatrix->u.s._42) +
2270 (mat->u.s._32 * pMatrix->u.s._43) + (mat->u.s._42 * pMatrix->u.s._44);
2272 temp.u.s._13 = (mat->u.s._13 * pMatrix->u.s._11) + (mat->u.s._23 * pMatrix->u.s._12) +
2273 (mat->u.s._33 * pMatrix->u.s._13) + (mat->u.s._43 * pMatrix->u.s._14);
2274 temp.u.s._23 = (mat->u.s._13 * pMatrix->u.s._21) + (mat->u.s._23 * pMatrix->u.s._22) +
2275 (mat->u.s._33 * pMatrix->u.s._23) + (mat->u.s._43 * pMatrix->u.s._24);
2276 temp.u.s._33 = (mat->u.s._13 * pMatrix->u.s._31) + (mat->u.s._23 * pMatrix->u.s._32) +
2277 (mat->u.s._33 * pMatrix->u.s._33) + (mat->u.s._43 * pMatrix->u.s._34);
2278 temp.u.s._43 = (mat->u.s._13 * pMatrix->u.s._41) + (mat->u.s._23 * pMatrix->u.s._42) +
2279 (mat->u.s._33 * pMatrix->u.s._43) + (mat->u.s._43 * pMatrix->u.s._44);
2281 temp.u.s._14 = (mat->u.s._14 * pMatrix->u.s._11) + (mat->u.s._24 * pMatrix->u.s._12) +
2282 (mat->u.s._34 * pMatrix->u.s._13) + (mat->u.s._44 * pMatrix->u.s._14);
2283 temp.u.s._24 = (mat->u.s._14 * pMatrix->u.s._21) + (mat->u.s._24 * pMatrix->u.s._22) +
2284 (mat->u.s._34 * pMatrix->u.s._23) + (mat->u.s._44 * pMatrix->u.s._24);
2285 temp.u.s._34 = (mat->u.s._14 * pMatrix->u.s._31) + (mat->u.s._24 * pMatrix->u.s._32) +
2286 (mat->u.s._34 * pMatrix->u.s._33) + (mat->u.s._44 * pMatrix->u.s._34);
2287 temp.u.s._44 = (mat->u.s._14 * pMatrix->u.s._41) + (mat->u.s._24 * pMatrix->u.s._42) +
2288 (mat->u.s._34 * pMatrix->u.s._43) + (mat->u.s._44 * pMatrix->u.s._44);
2290 /* Apply change via set transform - will reapply to eg. lights this way */
2291 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2294 /*****
2295 * Get / Set Light
2296 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
2297 *****/
2298 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2299 you can reference any indexes you want as long as that number max are enabled at any
2300 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2301 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2302 but when recording, just build a chain pretty much of commands to be replayed. */
2304 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2305 float rho;
2306 PLIGHTINFOEL *object, *temp;
2308 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2309 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2311 /* If recording state block, just add to end of lights chain */
2312 if (This->isRecordingState) {
2313 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2314 if (NULL == object) {
2315 return WINED3DERR_OUTOFVIDEOMEMORY;
2317 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2318 object->OriginalIndex = Index;
2319 object->glIndex = -1;
2320 object->changed = TRUE;
2322 /* Add to the END of the chain of lights changes to be replayed */
2323 if (This->updateStateBlock->lights == NULL) {
2324 This->updateStateBlock->lights = object;
2325 } else {
2326 temp = This->updateStateBlock->lights;
2327 while (temp->next != NULL) temp=temp->next;
2328 temp->next = object;
2330 TRACE("Recording... not performing anything more\n");
2331 return WINED3D_OK;
2334 /* Ok, not recording any longer so do real work */
2335 object = This->stateBlock->lights;
2336 while (object != NULL && object->OriginalIndex != Index) object = object->next;
2338 /* If we didn't find it in the list of lights, time to add it */
2339 if (object == NULL) {
2340 PLIGHTINFOEL *insertAt,*prevPos;
2342 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2343 if (NULL == object) {
2344 return WINED3DERR_OUTOFVIDEOMEMORY;
2346 object->OriginalIndex = Index;
2347 object->glIndex = -1;
2349 /* Add it to the front of list with the idea that lights will be changed as needed
2350 BUT after any lights currently assigned GL indexes */
2351 insertAt = This->stateBlock->lights;
2352 prevPos = NULL;
2353 while (insertAt != NULL && insertAt->glIndex != -1) {
2354 prevPos = insertAt;
2355 insertAt = insertAt->next;
2358 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2359 This->stateBlock->lights = object;
2360 } else if (insertAt == NULL) { /* End of list */
2361 prevPos->next = object;
2362 object->prev = prevPos;
2363 } else { /* Middle of chain */
2364 if (prevPos == NULL) {
2365 This->stateBlock->lights = object;
2366 } else {
2367 prevPos->next = object;
2369 object->prev = prevPos;
2370 object->next = insertAt;
2371 insertAt->prev = object;
2375 /* Initialize the object */
2376 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,
2377 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2378 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2379 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2380 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2381 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2382 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2384 /* Save away the information */
2385 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2387 switch (pLight->Type) {
2388 case D3DLIGHT_POINT:
2389 /* Position */
2390 object->lightPosn[0] = pLight->Position.x;
2391 object->lightPosn[1] = pLight->Position.y;
2392 object->lightPosn[2] = pLight->Position.z;
2393 object->lightPosn[3] = 1.0f;
2394 object->cutoff = 180.0f;
2395 /* FIXME: Range */
2396 break;
2398 case D3DLIGHT_DIRECTIONAL:
2399 /* Direction */
2400 object->lightPosn[0] = -pLight->Direction.x;
2401 object->lightPosn[1] = -pLight->Direction.y;
2402 object->lightPosn[2] = -pLight->Direction.z;
2403 object->lightPosn[3] = 0.0;
2404 object->exponent = 0.0f;
2405 object->cutoff = 180.0f;
2406 break;
2408 case D3DLIGHT_SPOT:
2409 /* Position */
2410 object->lightPosn[0] = pLight->Position.x;
2411 object->lightPosn[1] = pLight->Position.y;
2412 object->lightPosn[2] = pLight->Position.z;
2413 object->lightPosn[3] = 1.0;
2415 /* Direction */
2416 object->lightDirn[0] = pLight->Direction.x;
2417 object->lightDirn[1] = pLight->Direction.y;
2418 object->lightDirn[2] = pLight->Direction.z;
2419 object->lightDirn[3] = 1.0;
2422 * opengl-ish and d3d-ish spot lights use too different models for the
2423 * light "intensity" as a function of the angle towards the main light direction,
2424 * so we only can approximate very roughly.
2425 * however spot lights are rather rarely used in games (if ever used at all).
2426 * furthermore if still used, probably nobody pays attention to such details.
2428 if (pLight->Falloff == 0) {
2429 rho = 6.28f;
2430 } else {
2431 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2433 if (rho < 0.0001) rho = 0.0001f;
2434 object->exponent = -0.3/log(cos(rho/2));
2435 object->cutoff = pLight->Phi*90/M_PI;
2437 /* FIXME: Range */
2438 break;
2440 default:
2441 FIXME("Unrecognized light type %d\n", pLight->Type);
2444 /* Update the live definitions if the light is currently assigned a glIndex */
2445 if (object->glIndex != -1) {
2446 setup_light(iface, object->glIndex, object);
2448 return WINED3D_OK;
2451 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2452 PLIGHTINFOEL *lightInfo = NULL;
2453 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2454 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2456 /* Locate the light in the live lights */
2457 lightInfo = This->stateBlock->lights;
2458 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2460 if (lightInfo == NULL) {
2461 TRACE("Light information requested but light not defined\n");
2462 return WINED3DERR_INVALIDCALL;
2465 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
2466 return WINED3D_OK;
2469 /*****
2470 * Get / Set Light Enable
2471 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2472 *****/
2473 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2474 PLIGHTINFOEL *lightInfo = NULL;
2475 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2476 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2478 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2479 if (This->isRecordingState) {
2480 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2481 if (NULL == lightInfo) {
2482 return WINED3DERR_OUTOFVIDEOMEMORY;
2484 lightInfo->OriginalIndex = Index;
2485 lightInfo->glIndex = -1;
2486 lightInfo->enabledChanged = TRUE;
2488 /* Add to the END of the chain of lights changes to be replayed */
2489 if (This->updateStateBlock->lights == NULL) {
2490 This->updateStateBlock->lights = lightInfo;
2491 } else {
2492 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2493 while (temp->next != NULL) temp=temp->next;
2494 temp->next = lightInfo;
2496 TRACE("Recording... not performing anything more\n");
2497 return WINED3D_OK;
2500 /* Not recording... So, locate the light in the live lights */
2501 lightInfo = This->stateBlock->lights;
2502 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2504 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2505 if (lightInfo == NULL) {
2506 D3DLIGHT9 lightParms;
2507 /* Warning - untested code :-) Prob safe to change fixme to a trace but
2508 wait until someone confirms it seems to work! */
2509 TRACE("Light enabled requested but light not defined, so defining one!\n");
2510 lightParms.Type = D3DLIGHT_DIRECTIONAL;
2511 lightParms.Diffuse.r = 1.0;
2512 lightParms.Diffuse.g = 1.0;
2513 lightParms.Diffuse.b = 1.0;
2514 lightParms.Diffuse.a = 0.0;
2515 lightParms.Specular.r = 0.0;
2516 lightParms.Specular.g = 0.0;
2517 lightParms.Specular.b = 0.0;
2518 lightParms.Specular.a = 0.0;
2519 lightParms.Ambient.r = 0.0;
2520 lightParms.Ambient.g = 0.0;
2521 lightParms.Ambient.b = 0.0;
2522 lightParms.Ambient.a = 0.0;
2523 lightParms.Position.x = 0.0;
2524 lightParms.Position.y = 0.0;
2525 lightParms.Position.z = 0.0;
2526 lightParms.Direction.x = 0.0;
2527 lightParms.Direction.y = 0.0;
2528 lightParms.Direction.z = 1.0;
2529 lightParms.Range = 0.0;
2530 lightParms.Falloff = 0.0;
2531 lightParms.Attenuation0 = 0.0;
2532 lightParms.Attenuation1 = 0.0;
2533 lightParms.Attenuation2 = 0.0;
2534 lightParms.Theta = 0.0;
2535 lightParms.Phi = 0.0;
2536 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
2538 /* Search for it again! Should be fairly quick as near head of list */
2539 lightInfo = This->stateBlock->lights;
2540 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2541 if (lightInfo == NULL) {
2542 FIXME("Adding default lights has failed dismally\n");
2543 return WINED3DERR_INVALIDCALL;
2547 /* OK, we now have a light... */
2548 if (Enable == FALSE) {
2550 /* If we are disabling it, check it was enabled, and
2551 still only do something if it has assigned a glIndex (which it should have!) */
2552 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2553 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2554 ENTER_GL();
2555 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2556 checkGLcall("glDisable GL_LIGHT0+Index");
2557 LEAVE_GL();
2558 } else {
2559 TRACE("Nothing to do as light was not enabled\n");
2561 lightInfo->lightEnabled = FALSE;
2562 } else {
2564 /* We are enabling it. If it is enabled, it's really simple */
2565 if (lightInfo->lightEnabled) {
2566 /* nop */
2567 TRACE("Nothing to do as light was enabled\n");
2569 /* If it already has a glIndex, it's still simple */
2570 } else if (lightInfo->glIndex != -1) {
2571 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2572 lightInfo->lightEnabled = TRUE;
2573 ENTER_GL();
2574 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2575 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2576 LEAVE_GL();
2578 /* Otherwise got to find space - lights are ordered gl indexes first */
2579 } else {
2580 PLIGHTINFOEL *bsf = NULL;
2581 PLIGHTINFOEL *pos = This->stateBlock->lights;
2582 PLIGHTINFOEL *prev = NULL;
2583 int Index= 0;
2584 int glIndex = -1;
2586 /* Try to minimize changes as much as possible */
2587 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2589 /* Try to remember which index can be replaced if necessary */
2590 if (bsf==NULL && pos->lightEnabled == FALSE) {
2591 /* Found a light we can replace, save as best replacement */
2592 bsf = pos;
2595 /* Step to next space */
2596 prev = pos;
2597 pos = pos->next;
2598 Index ++;
2601 /* If we have too many active lights, fail the call */
2602 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2603 FIXME("Program requests too many concurrent lights\n");
2604 return WINED3DERR_INVALIDCALL;
2606 /* If we have allocated all lights, but not all are enabled,
2607 reuse one which is not enabled */
2608 } else if (Index == This->maxConcurrentLights) {
2609 /* use bsf - Simply swap the new light and the BSF one */
2610 PLIGHTINFOEL *bsfNext = bsf->next;
2611 PLIGHTINFOEL *bsfPrev = bsf->prev;
2613 /* Sort out ends */
2614 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2615 if (bsf->prev != NULL) {
2616 bsf->prev->next = lightInfo;
2617 } else {
2618 This->stateBlock->lights = lightInfo;
2621 /* If not side by side, lots of chains to update */
2622 if (bsf->next != lightInfo) {
2623 lightInfo->prev->next = bsf;
2624 bsf->next->prev = lightInfo;
2625 bsf->next = lightInfo->next;
2626 bsf->prev = lightInfo->prev;
2627 lightInfo->next = bsfNext;
2628 lightInfo->prev = bsfPrev;
2630 } else {
2631 /* Simple swaps */
2632 bsf->prev = lightInfo;
2633 bsf->next = lightInfo->next;
2634 lightInfo->next = bsf;
2635 lightInfo->prev = bsfPrev;
2639 /* Update states */
2640 glIndex = bsf->glIndex;
2641 bsf->glIndex = -1;
2642 lightInfo->glIndex = glIndex;
2643 lightInfo->lightEnabled = TRUE;
2645 /* Finally set up the light in gl itself */
2646 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2647 ENTER_GL();
2648 setup_light(iface, glIndex, lightInfo);
2649 glEnable(GL_LIGHT0 + glIndex);
2650 checkGLcall("glEnable GL_LIGHT0 new setup");
2651 LEAVE_GL();
2653 /* If we reached the end of the allocated lights, with space in the
2654 gl lights, setup a new light */
2655 } else if (pos->glIndex == -1) {
2657 /* We reached the end of the allocated gl lights, so already
2658 know the index of the next one! */
2659 glIndex = Index;
2660 lightInfo->glIndex = glIndex;
2661 lightInfo->lightEnabled = TRUE;
2663 /* In an ideal world, it's already in the right place */
2664 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2665 /* No need to move it */
2666 } else {
2667 /* Remove this light from the list */
2668 lightInfo->prev->next = lightInfo->next;
2669 if (lightInfo->next != NULL) {
2670 lightInfo->next->prev = lightInfo->prev;
2673 /* Add in at appropriate place (inbetween prev and pos) */
2674 lightInfo->prev = prev;
2675 lightInfo->next = pos;
2676 if (prev == NULL) {
2677 This->stateBlock->lights = lightInfo;
2678 } else {
2679 prev->next = lightInfo;
2681 if (pos != NULL) {
2682 pos->prev = lightInfo;
2686 /* Finally set up the light in gl itself */
2687 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2688 ENTER_GL();
2689 setup_light(iface, glIndex, lightInfo);
2690 glEnable(GL_LIGHT0 + glIndex);
2691 checkGLcall("glEnable GL_LIGHT0 new setup");
2692 LEAVE_GL();
2697 return WINED3D_OK;
2700 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2702 PLIGHTINFOEL *lightInfo = NULL;
2703 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2704 TRACE("(%p) : for idx(%ld)\n", This, Index);
2706 /* Locate the light in the live lights */
2707 lightInfo = This->stateBlock->lights;
2708 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2710 if (lightInfo == NULL) {
2711 TRACE("Light enabled state requested but light not defined\n");
2712 return WINED3DERR_INVALIDCALL;
2714 *pEnable = lightInfo->lightEnabled;
2715 return WINED3D_OK;
2718 /*****
2719 * Get / Set Clip Planes
2720 *****/
2721 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2722 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2723 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2725 /* Validate Index */
2726 if (Index >= GL_LIMITS(clipplanes)) {
2727 TRACE("Application has requested clipplane this device doesn't support\n");
2728 return WINED3DERR_INVALIDCALL;
2731 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2732 This->updateStateBlock->set.clipplane[Index] = TRUE;
2733 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2734 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2735 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2736 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2738 /* Handle recording of state blocks */
2739 if (This->isRecordingState) {
2740 TRACE("Recording... not performing anything\n");
2741 return WINED3D_OK;
2744 /* Apply it */
2746 ENTER_GL();
2748 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2749 glMatrixMode(GL_MODELVIEW);
2750 glPushMatrix();
2751 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2753 TRACE("Clipplane [%f,%f,%f,%f]\n",
2754 This->updateStateBlock->clipplane[Index][0],
2755 This->updateStateBlock->clipplane[Index][1],
2756 This->updateStateBlock->clipplane[Index][2],
2757 This->updateStateBlock->clipplane[Index][3]);
2758 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2759 checkGLcall("glClipPlane");
2761 glPopMatrix();
2762 LEAVE_GL();
2764 return WINED3D_OK;
2767 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2768 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2769 TRACE("(%p) : for idx %ld\n", This, Index);
2771 /* Validate Index */
2772 if (Index >= GL_LIMITS(clipplanes)) {
2773 TRACE("Application has requested clipplane this device doesn't support\n");
2774 return WINED3DERR_INVALIDCALL;
2777 pPlane[0] = This->stateBlock->clipplane[Index][0];
2778 pPlane[1] = This->stateBlock->clipplane[Index][1];
2779 pPlane[2] = This->stateBlock->clipplane[Index][2];
2780 pPlane[3] = This->stateBlock->clipplane[Index][3];
2781 return WINED3D_OK;
2784 /*****
2785 * Get / Set Clip Plane Status
2786 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2787 *****/
2788 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2789 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2790 FIXME("(%p) : stub\n", This);
2791 if (NULL == pClipStatus) {
2792 return WINED3DERR_INVALIDCALL;
2794 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2795 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2796 return WINED3D_OK;
2799 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2800 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2801 FIXME("(%p) : stub\n", This);
2802 if (NULL == pClipStatus) {
2803 return WINED3DERR_INVALIDCALL;
2805 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2806 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2807 return WINED3D_OK;
2810 /*****
2811 * Get / Set Material
2812 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2813 *****/
2814 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2815 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2817 This->updateStateBlock->changed.material = TRUE;
2818 This->updateStateBlock->set.material = TRUE;
2819 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2821 /* Handle recording of state blocks */
2822 if (This->isRecordingState) {
2823 TRACE("Recording... not performing anything\n");
2824 return WINED3D_OK;
2827 ENTER_GL();
2828 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2829 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2830 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2831 pMaterial->Ambient.b, pMaterial->Ambient.a);
2832 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2833 pMaterial->Specular.b, pMaterial->Specular.a);
2834 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2835 pMaterial->Emissive.b, pMaterial->Emissive.a);
2836 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2838 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2839 checkGLcall("glMaterialfv(GL_AMBIENT)");
2840 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2841 checkGLcall("glMaterialfv(GL_DIFFUSE)");
2843 /* Only change material color if specular is enabled, otherwise it is set to black */
2844 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2845 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2846 checkGLcall("glMaterialfv(GL_SPECULAR");
2847 } else {
2848 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2849 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2850 checkGLcall("glMaterialfv(GL_SPECULAR");
2852 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2853 checkGLcall("glMaterialfv(GL_EMISSION)");
2854 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2855 checkGLcall("glMaterialf(GL_SHININESS");
2857 LEAVE_GL();
2858 return WINED3D_OK;
2861 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2862 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2863 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2864 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2865 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2866 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2867 pMaterial->Ambient.b, pMaterial->Ambient.a);
2868 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2869 pMaterial->Specular.b, pMaterial->Specular.a);
2870 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2871 pMaterial->Emissive.b, pMaterial->Emissive.a);
2872 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2874 return WINED3D_OK;
2877 /*****
2878 * Get / Set Indices
2879 *****/
2880 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2881 UINT BaseVertexIndex) {
2882 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2883 IWineD3DIndexBuffer *oldIdxs;
2885 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2886 oldIdxs = This->updateStateBlock->pIndexData;
2888 This->updateStateBlock->changed.indices = TRUE;
2889 This->updateStateBlock->set.indices = TRUE;
2890 This->updateStateBlock->pIndexData = pIndexData;
2891 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2893 /* Handle recording of state blocks */
2894 if (This->isRecordingState) {
2895 TRACE("Recording... not performing anything\n");
2896 return WINED3D_OK;
2899 if (NULL != pIndexData) {
2900 IWineD3DIndexBuffer_AddRef(pIndexData);
2902 if (NULL != oldIdxs) {
2903 IWineD3DIndexBuffer_Release(oldIdxs);
2905 return WINED3D_OK;
2908 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2909 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2911 *ppIndexData = This->stateBlock->pIndexData;
2913 /* up ref count on ppindexdata */
2914 if (*ppIndexData) {
2915 IWineD3DIndexBuffer_AddRef(*ppIndexData);
2916 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2917 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
2918 }else{
2919 TRACE("(%p) No index data set\n", This);
2921 TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
2923 return WINED3D_OK;
2926 /*****
2927 * Get / Set Viewports
2928 *****/
2929 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2930 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2932 TRACE("(%p)\n", This);
2933 This->updateStateBlock->changed.viewport = TRUE;
2934 This->updateStateBlock->set.viewport = TRUE;
2935 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2937 /* Handle recording of state blocks */
2938 if (This->isRecordingState) {
2939 TRACE("Recording... not performing anything\n");
2940 return WINED3D_OK;
2942 This->viewport_changed = TRUE;
2944 ENTER_GL();
2946 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2947 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2949 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2950 checkGLcall("glDepthRange");
2951 /* Note: GL requires lower left, DirectX supplies upper left */
2952 /* TODO: replace usage of renderTarget with context management */
2953 glViewport(pViewport->X,
2954 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2955 pViewport->Width, pViewport->Height);
2957 checkGLcall("glViewport");
2959 LEAVE_GL();
2961 return WINED3D_OK;
2965 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2966 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2967 TRACE("(%p)\n", This);
2968 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2969 return WINED3D_OK;
2972 /*****
2973 * Get / Set Render States
2974 * TODO: Verify against dx9 definitions
2975 *****/
2976 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2978 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2979 DWORD OldValue = This->stateBlock->renderState[State];
2981 /* Simple way of referring to either a DWORD or a 4 byte float */
2982 union {
2983 DWORD d;
2984 float f;
2985 } tmpvalue;
2987 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2988 This->updateStateBlock->changed.renderState[State] = TRUE;
2989 This->updateStateBlock->set.renderState[State] = TRUE;
2990 This->updateStateBlock->renderState[State] = Value;
2992 /* Handle recording of state blocks */
2993 if (This->isRecordingState) {
2994 TRACE("Recording... not performing anything\n");
2995 return WINED3D_OK;
2998 ENTER_GL();
3000 switch (State) {
3001 case WINED3DRS_FILLMODE :
3002 switch ((D3DFILLMODE) Value) {
3003 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
3004 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
3005 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
3006 default:
3007 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
3009 checkGLcall("glPolygonMode (fillmode)");
3010 break;
3012 case WINED3DRS_LIGHTING :
3013 if (Value) {
3014 glEnable(GL_LIGHTING);
3015 checkGLcall("glEnable GL_LIGHTING");
3016 } else {
3017 glDisable(GL_LIGHTING);
3018 checkGLcall("glDisable GL_LIGHTING");
3020 break;
3022 case WINED3DRS_ZENABLE :
3023 switch ((D3DZBUFFERTYPE) Value) {
3024 case D3DZB_FALSE:
3025 glDisable(GL_DEPTH_TEST);
3026 checkGLcall("glDisable GL_DEPTH_TEST");
3027 break;
3028 case D3DZB_TRUE:
3029 glEnable(GL_DEPTH_TEST);
3030 checkGLcall("glEnable GL_DEPTH_TEST");
3031 break;
3032 case D3DZB_USEW:
3033 glEnable(GL_DEPTH_TEST);
3034 checkGLcall("glEnable GL_DEPTH_TEST");
3035 FIXME("W buffer is not well handled\n");
3036 break;
3037 default:
3038 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
3040 break;
3042 case WINED3DRS_CULLMODE :
3044 /* If we are culling "back faces with clockwise vertices" then
3045 set front faces to be counter clockwise and enable culling
3046 of back faces */
3047 switch ((D3DCULL) Value) {
3048 case D3DCULL_NONE:
3049 glDisable(GL_CULL_FACE);
3050 checkGLcall("glDisable GL_CULL_FACE");
3051 break;
3052 case D3DCULL_CW:
3053 glEnable(GL_CULL_FACE);
3054 checkGLcall("glEnable GL_CULL_FACE");
3055 if (This->renderUpsideDown) {
3056 glFrontFace(GL_CW);
3057 checkGLcall("glFrontFace GL_CW");
3058 } else {
3059 glFrontFace(GL_CCW);
3060 checkGLcall("glFrontFace GL_CCW");
3062 glCullFace(GL_BACK);
3063 break;
3064 case D3DCULL_CCW:
3065 glEnable(GL_CULL_FACE);
3066 checkGLcall("glEnable GL_CULL_FACE");
3067 if (This->renderUpsideDown) {
3068 glFrontFace(GL_CCW);
3069 checkGLcall("glFrontFace GL_CCW");
3070 } else {
3071 glFrontFace(GL_CW);
3072 checkGLcall("glFrontFace GL_CW");
3074 glCullFace(GL_BACK);
3075 break;
3076 default:
3077 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
3079 break;
3081 case WINED3DRS_SHADEMODE :
3082 switch ((D3DSHADEMODE) Value) {
3083 case D3DSHADE_FLAT:
3084 glShadeModel(GL_FLAT);
3085 checkGLcall("glShadeModel");
3086 break;
3087 case D3DSHADE_GOURAUD:
3088 glShadeModel(GL_SMOOTH);
3089 checkGLcall("glShadeModel");
3090 break;
3091 case D3DSHADE_PHONG:
3092 FIXME("D3DSHADE_PHONG isn't supported?\n");
3094 LEAVE_GL();
3095 return WINED3DERR_INVALIDCALL;
3096 default:
3097 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
3099 break;
3101 case WINED3DRS_DITHERENABLE :
3102 if (Value) {
3103 glEnable(GL_DITHER);
3104 checkGLcall("glEnable GL_DITHER");
3105 } else {
3106 glDisable(GL_DITHER);
3107 checkGLcall("glDisable GL_DITHER");
3109 break;
3111 case WINED3DRS_ZWRITEENABLE :
3112 if (Value) {
3113 glDepthMask(1);
3114 checkGLcall("glDepthMask");
3115 } else {
3116 glDepthMask(0);
3117 checkGLcall("glDepthMask");
3119 break;
3121 case WINED3DRS_ZFUNC :
3123 int glParm = GL_LESS;
3125 switch ((D3DCMPFUNC) Value) {
3126 case D3DCMP_NEVER: glParm=GL_NEVER; break;
3127 case D3DCMP_LESS: glParm=GL_LESS; break;
3128 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
3129 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
3130 case D3DCMP_GREATER: glParm=GL_GREATER; break;
3131 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
3132 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
3133 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
3134 default:
3135 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3137 glDepthFunc(glParm);
3138 checkGLcall("glDepthFunc");
3140 break;
3142 case WINED3DRS_AMBIENT :
3144 float col[4];
3145 D3DCOLORTOGLFLOAT4(Value, col);
3146 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
3147 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
3148 checkGLcall("glLightModel for MODEL_AMBIENT");
3151 break;
3153 case WINED3DRS_ALPHABLENDENABLE :
3154 if (Value) {
3155 glEnable(GL_BLEND);
3156 checkGLcall("glEnable GL_BLEND");
3157 } else {
3158 glDisable(GL_BLEND);
3159 checkGLcall("glDisable GL_BLEND");
3161 break;
3163 case WINED3DRS_SRCBLEND :
3164 case WINED3DRS_DESTBLEND :
3166 int newVal = GL_ZERO;
3167 switch (Value) {
3168 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
3169 case D3DBLEND_ONE : newVal = GL_ONE; break;
3170 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
3171 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
3172 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
3173 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
3174 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
3175 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
3176 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
3177 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
3178 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
3180 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
3181 This->srcBlend = newVal;
3182 This->dstBlend = newVal;
3183 break;
3185 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
3186 This->srcBlend = newVal;
3187 This->dstBlend = newVal;
3188 break;
3189 default:
3190 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
3193 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
3194 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
3195 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
3196 glBlendFunc(This->srcBlend, This->dstBlend);
3198 checkGLcall("glBlendFunc");
3200 break;
3202 case WINED3DRS_ALPHATESTENABLE :
3203 if (Value) {
3204 glEnable(GL_ALPHA_TEST);
3205 checkGLcall("glEnable GL_ALPHA_TEST");
3206 } else {
3207 glDisable(GL_ALPHA_TEST);
3208 checkGLcall("glDisable GL_ALPHA_TEST");
3210 break;
3212 case WINED3DRS_ALPHAFUNC :
3214 int glParm = GL_LESS;
3215 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
3217 switch ((D3DCMPFUNC) Value) {
3218 case D3DCMP_NEVER: glParm = GL_NEVER; break;
3219 case D3DCMP_LESS: glParm = GL_LESS; break;
3220 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
3221 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
3222 case D3DCMP_GREATER: glParm = GL_GREATER; break;
3223 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
3224 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
3225 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
3226 default:
3227 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3229 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
3230 glAlphaFunc(glParm, ref);
3231 This->alphafunc = glParm;
3232 checkGLcall("glAlphaFunc");
3234 break;
3236 case WINED3DRS_ALPHAREF :
3238 int glParm = This->alphafunc;
3239 float ref = 1.0f;
3241 ref = ((float) Value) / 255.0f;
3242 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
3243 glAlphaFunc(glParm, ref);
3244 checkGLcall("glAlphaFunc");
3246 break;
3248 case WINED3DRS_CLIPPLANEENABLE :
3249 case WINED3DRS_CLIPPING :
3251 /* Ensure we only do the changed clip planes */
3252 DWORD enable = 0xFFFFFFFF;
3253 DWORD disable = 0x00000000;
3255 /* If enabling / disabling all */
3256 if (State == WINED3DRS_CLIPPING) {
3257 if (Value) {
3258 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3259 disable = 0x00;
3260 } else {
3261 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3262 enable = 0x00;
3264 } else {
3265 enable = Value & ~OldValue;
3266 disable = ~Value & OldValue;
3269 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
3270 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
3271 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
3272 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
3273 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
3274 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
3276 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
3277 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
3278 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
3279 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
3280 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
3281 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
3283 /** update clipping status */
3284 if (enable) {
3285 This->stateBlock->clip_status.ClipUnion = 0;
3286 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
3287 } else {
3288 This->stateBlock->clip_status.ClipUnion = 0;
3289 This->stateBlock->clip_status.ClipIntersection = 0;
3292 break;
3294 case WINED3DRS_BLENDOP :
3296 int glParm = GL_FUNC_ADD;
3298 switch ((D3DBLENDOP) Value) {
3299 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
3300 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
3301 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3302 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
3303 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
3304 default:
3305 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
3307 TRACE("glBlendEquation(%x)\n", glParm);
3308 glBlendEquation(glParm);
3309 checkGLcall("glBlendEquation");
3311 break;
3313 case WINED3DRS_TEXTUREFACTOR :
3315 unsigned int i;
3317 /* Note the texture color applies to all textures whereas
3318 GL_TEXTURE_ENV_COLOR applies to active only */
3319 float col[4];
3320 D3DCOLORTOGLFLOAT4(Value, col);
3321 /* Set the default alpha blend color */
3322 glBlendColor(col[0], col[1], col[2], col[3]);
3323 checkGLcall("glBlendColor");
3325 /* And now the default texture color as well */
3326 for (i = 0; i < GL_LIMITS(textures); i++) {
3328 /* Note the D3DRS value applies to all textures, but GL has one
3329 per texture, so apply it now ready to be used! */
3330 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3331 GLACTIVETEXTURE(i);
3332 } else if (i>0) {
3333 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3336 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3337 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3340 break;
3342 case WINED3DRS_SPECULARENABLE :
3344 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3345 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3346 specular color. This is wrong:
3347 Separate specular color means the specular colour is maintained separately, whereas
3348 single color means it is merged in. However in both cases they are being used to
3349 some extent.
3350 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3351 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3352 running 1.4 yet!
3354 if (Value) {
3355 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3356 checkGLcall("glMaterialfv");
3357 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3358 glEnable(GL_COLOR_SUM_EXT);
3359 } else {
3360 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3362 checkGLcall("glEnable(GL_COLOR_SUM)");
3363 } else {
3364 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3366 /* for the case of enabled lighting: */
3367 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3368 checkGLcall("glMaterialfv");
3370 /* for the case of disabled lighting: */
3371 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3372 glDisable(GL_COLOR_SUM_EXT);
3373 } else {
3374 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3376 checkGLcall("glDisable(GL_COLOR_SUM)");
3379 break;
3381 case WINED3DRS_STENCILENABLE :
3382 if (Value) {
3383 glEnable(GL_STENCIL_TEST);
3384 checkGLcall("glEnable GL_STENCIL_TEST");
3385 } else {
3386 glDisable(GL_STENCIL_TEST);
3387 checkGLcall("glDisable GL_STENCIL_TEST");
3389 break;
3391 case WINED3DRS_STENCILFUNC :
3393 GLint func;
3394 GLint ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3395 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3397 func = GL_ALWAYS;
3398 switch ((D3DCMPFUNC)Value) {
3399 case D3DCMP_NEVER: func = GL_NEVER; break;
3400 case D3DCMP_LESS: func = GL_LESS; break;
3401 case D3DCMP_EQUAL: func = GL_EQUAL; break;
3402 case D3DCMP_LESSEQUAL: func = GL_LEQUAL; break;
3403 case D3DCMP_GREATER: func = GL_GREATER; break;
3404 case D3DCMP_NOTEQUAL: func = GL_NOTEQUAL; break;
3405 case D3DCMP_GREATEREQUAL: func = GL_GEQUAL; break;
3406 case D3DCMP_ALWAYS: func = GL_ALWAYS; break;
3407 default:
3408 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3410 This->stencilfunc = func;
3411 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3412 #if 0 /* Don't use OpenGL 2.0 calls for now */
3413 if(GL_EXTCALL(glStencilFuncSeparate)) {
3414 GL_EXTCALL(glStencilFuncSeparate(GL_FRONT, func, ref, mask));
3415 checkGLcall("glStencilFuncSeparate(GL_FRONT,...)");
3417 else
3418 #endif
3419 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3420 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3421 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3422 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
3423 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
3424 glStencilFunc(func, ref, mask);
3425 checkGLcall("glStencilFunc(...)");
3427 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3428 GL_EXTCALL(glStencilFuncSeparateATI(GL_FRONT, func, ref, mask));
3429 checkGLcall("glStencilFuncSeparateATI(GL_FRONT,...)");
3430 } else {
3431 TRACE("Separate stencil function not supported on this version of opengl");
3432 glStencilFunc(func, ref, mask);
3433 checkGLcall("glStencilFunc(...)");
3435 } else {
3436 glStencilFunc(func, ref, mask);
3437 checkGLcall("glStencilFunc(...)");
3439 break;
3441 case WINED3DRS_STENCILREF :
3443 int glParm = This->stencilfunc;
3444 int ref = 0;
3445 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3447 ref = Value;
3448 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3449 glStencilFunc(glParm, ref, mask);
3450 checkGLcall("glStencilFunc");
3452 break;
3454 case WINED3DRS_STENCILMASK :
3456 int glParm = This->stencilfunc;
3457 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3458 GLuint mask = Value;
3460 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3461 glStencilFunc(glParm, ref, mask);
3462 checkGLcall("glStencilFunc");
3464 break;
3466 case WINED3DRS_STENCILFAIL :
3467 case WINED3DRS_STENCILZFAIL :
3468 case WINED3DRS_STENCILPASS :
3470 GLint stencilFail;
3471 GLint depthFail;
3472 GLint stencilPass;
3474 GLint action = StencilOp(Value);
3476 glGetIntegerv(GL_STENCIL_FAIL, &stencilFail);
3477 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &depthFail);
3478 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &stencilPass);
3480 if(WINED3DRS_STENCILFAIL == State) {
3481 stencilFail = action;
3483 else if(WINED3DRS_STENCILZFAIL == State) {
3484 depthFail = action;
3486 else if(WINED3DRS_STENCILPASS == State) {
3487 stencilPass = action;
3490 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3491 #if 0 /* Don't use OpenGL 2.0 calls for now */
3492 if(GL_EXTCALL(glStencilOpSeparate)) {
3493 GL_EXTCALL(glStencilOpSeparate(GL_FRONT, stencilFail, depthFail, stencilPass));
3494 checkGLcall("glStencilOpSeparate(GL_FRONT,...)");
3496 else
3497 #endif
3498 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3499 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3500 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3501 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
3502 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
3503 glStencilOp(stencilFail, depthFail, stencilPass);
3504 checkGLcall("glStencilOp(...)");
3506 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3507 GL_EXTCALL(glStencilOpSeparateATI(GL_FRONT, stencilFail, depthFail, stencilPass));
3508 checkGLcall("glStencilOpSeparateATI(GL_FRONT,...)");
3509 } else {
3510 TRACE("Separate stencil operation not supported on this version of opengl");
3511 glStencilOp(stencilFail, depthFail, stencilPass);
3512 checkGLcall("glStencilOp(...)");
3514 } else {
3515 glStencilOp(stencilFail, depthFail, stencilPass);
3516 checkGLcall("glStencilOp(...)");
3518 break;
3520 case WINED3DRS_STENCILWRITEMASK :
3522 glStencilMask(Value);
3523 TRACE("glStencilMask(%lu)\n", Value);
3524 checkGLcall("glStencilMask");
3526 break;
3528 case WINED3DRS_FOGENABLE :
3530 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
3531 glEnable(GL_FOG);
3532 checkGLcall("glEnable GL_FOG");
3533 } else {
3534 glDisable(GL_FOG);
3535 checkGLcall("glDisable GL_FOG");
3538 break;
3540 case WINED3DRS_RANGEFOGENABLE :
3542 if (Value) {
3543 TRACE("Enabled RANGEFOG");
3544 } else {
3545 TRACE("Disabled RANGEFOG");
3548 break;
3550 case WINED3DRS_FOGCOLOR :
3552 float col[4];
3553 D3DCOLORTOGLFLOAT4(Value, col);
3554 /* Set the default alpha blend color */
3555 glFogfv(GL_FOG_COLOR, &col[0]);
3556 checkGLcall("glFog GL_FOG_COLOR");
3558 break;
3560 case WINED3DRS_FOGTABLEMODE :
3562 glHint(GL_FOG_HINT, GL_NICEST);
3563 switch (Value) {
3564 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3565 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3566 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3567 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3568 default:
3569 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3571 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3572 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3575 break;
3577 case WINED3DRS_FOGVERTEXMODE :
3579 glHint(GL_FOG_HINT, GL_FASTEST);
3580 switch (Value) {
3581 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3582 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3583 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3584 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3585 default:
3586 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3588 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3589 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
3592 break;
3594 case WINED3DRS_FOGSTART :
3596 tmpvalue.d = Value;
3597 glFogfv(GL_FOG_START, &tmpvalue.f);
3598 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3599 TRACE("Fog Start == %f\n", tmpvalue.f);
3601 break;
3603 case WINED3DRS_FOGEND :
3605 tmpvalue.d = Value;
3606 glFogfv(GL_FOG_END, &tmpvalue.f);
3607 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3608 TRACE("Fog End == %f\n", tmpvalue.f);
3610 break;
3612 case WINED3DRS_FOGDENSITY :
3614 tmpvalue.d = Value;
3615 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3616 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3618 break;
3620 case WINED3DRS_VERTEXBLEND :
3622 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3623 TRACE("Vertex Blending state to %ld\n", Value);
3625 break;
3627 case WINED3DRS_TWEENFACTOR :
3629 tmpvalue.d = Value;
3630 This->updateStateBlock->tween_factor = tmpvalue.f;
3631 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3633 break;
3635 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
3637 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3639 break;
3641 case WINED3DRS_COLORVERTEX :
3642 case WINED3DRS_DIFFUSEMATERIALSOURCE :
3643 case WINED3DRS_SPECULARMATERIALSOURCE :
3644 case WINED3DRS_AMBIENTMATERIALSOURCE :
3645 case WINED3DRS_EMISSIVEMATERIALSOURCE :
3647 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3649 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3650 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3651 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3652 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3653 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3654 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3656 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3657 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3658 Parm = GL_AMBIENT_AND_DIFFUSE;
3659 } else {
3660 Parm = GL_DIFFUSE;
3662 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3663 Parm = GL_AMBIENT;
3664 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3665 Parm = GL_EMISSION;
3666 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3667 Parm = GL_SPECULAR;
3668 } else {
3669 Parm = -1;
3672 if (Parm == -1) {
3673 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3674 } else {
3675 This->tracking_color = NEEDS_TRACKING;
3676 This->tracking_parm = Parm;
3679 } else {
3680 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3683 break;
3685 case WINED3DRS_LINEPATTERN :
3687 union {
3688 DWORD d;
3689 D3DLINEPATTERN lp;
3690 } tmppattern;
3691 tmppattern.d = Value;
3693 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3695 if (tmppattern.lp.wRepeatFactor) {
3696 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3697 checkGLcall("glLineStipple(repeat, linepattern)");
3698 glEnable(GL_LINE_STIPPLE);
3699 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3700 } else {
3701 glDisable(GL_LINE_STIPPLE);
3702 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3705 break;
3707 case WINED3DRS_ZBIAS : /* D3D8 only */
3709 if (Value) {
3710 tmpvalue.d = Value;
3711 TRACE("ZBias value %f\n", tmpvalue.f);
3712 glPolygonOffset(0, -tmpvalue.f);
3713 checkGLcall("glPolygonOffset(0, -Value)");
3714 glEnable(GL_POLYGON_OFFSET_FILL);
3715 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3716 glEnable(GL_POLYGON_OFFSET_LINE);
3717 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3718 glEnable(GL_POLYGON_OFFSET_POINT);
3719 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3720 } else {
3721 glDisable(GL_POLYGON_OFFSET_FILL);
3722 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3723 glDisable(GL_POLYGON_OFFSET_LINE);
3724 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3725 glDisable(GL_POLYGON_OFFSET_POINT);
3726 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3729 break;
3731 case WINED3DRS_NORMALIZENORMALS :
3732 if (Value) {
3733 glEnable(GL_NORMALIZE);
3734 checkGLcall("glEnable(GL_NORMALIZE);");
3735 } else {
3736 glDisable(GL_NORMALIZE);
3737 checkGLcall("glDisable(GL_NORMALIZE);");
3739 break;
3741 case WINED3DRS_POINTSIZE :
3742 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
3743 tmpvalue.d = Value;
3744 TRACE("Set point size to %f\n", tmpvalue.f);
3745 glPointSize(tmpvalue.f);
3746 checkGLcall("glPointSize(...);");
3747 break;
3749 case WINED3DRS_POINTSIZE_MIN :
3750 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3751 tmpvalue.d = Value;
3752 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3753 checkGLcall("glPointParameterfEXT(...);");
3754 } else {
3755 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3757 break;
3759 case WINED3DRS_POINTSIZE_MAX :
3760 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3761 tmpvalue.d = Value;
3762 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3763 checkGLcall("glPointParameterfEXT(...);");
3764 } else {
3765 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3767 break;
3769 case WINED3DRS_POINTSCALE_A :
3770 case WINED3DRS_POINTSCALE_B :
3771 case WINED3DRS_POINTSCALE_C :
3772 case WINED3DRS_POINTSCALEENABLE :
3775 * POINTSCALEENABLE controls how point size value is treated. If set to
3776 * true, the point size is scaled with respect to height of viewport.
3777 * When set to false point size is in pixels.
3779 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
3782 /* Default values */
3783 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3786 * Minimum valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
3787 * This means that OpenGL will clamp really small point sizes to 1.0f.
3788 * To correct for this we need to multiply by the scale factor when sizes
3789 * are less than 1.0f. scale_factor = 1.0f / point_size.
3791 GLfloat pointSize = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSIZE]);
3792 if(pointSize > 0.0f) {
3793 GLfloat scaleFactor;
3795 if(pointSize < 1.0f) {
3796 scaleFactor = pointSize * pointSize;
3797 } else {
3798 scaleFactor = 1.0f;
3801 if(This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3802 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]) /
3803 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3804 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]) /
3805 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3806 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) /
3807 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3811 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
3812 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
3813 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
3815 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3816 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3817 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
3818 } else {
3819 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
3821 break;
3823 case WINED3DRS_COLORWRITEENABLE :
3825 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3826 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3827 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3828 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3829 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3830 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3831 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3832 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3833 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3834 checkGLcall("glColorMask(...)");
3836 break;
3838 case WINED3DRS_LOCALVIEWER :
3840 GLint state = (Value) ? 1 : 0;
3841 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3842 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3844 break;
3846 case WINED3DRS_LASTPIXEL :
3848 if (Value) {
3849 TRACE("Last Pixel Drawing Enabled\n");
3850 } else {
3851 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3854 break;
3856 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3858 if (Value) {
3859 TRACE("Software Processing Enabled\n");
3860 } else {
3861 TRACE("Software Processing Disabled\n");
3864 break;
3866 /** not supported */
3867 case WINED3DRS_ZVISIBLE :
3869 LEAVE_GL();
3870 return WINED3DERR_INVALIDCALL;
3872 case WINED3DRS_POINTSPRITEENABLE :
3874 /* TODO: NV_POINT_SPRITE */
3875 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
3876 TRACE("Point sprites not supported\n");
3877 break;
3881 * Point sprites are always enabled. Value controls texture coordinate
3882 * replacement mode. Must be set true for point sprites to use
3883 * textures.
3885 glEnable(GL_POINT_SPRITE_ARB);
3886 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
3888 if (Value) {
3889 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
3890 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, TRUE)");
3891 } else {
3892 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, FALSE);
3893 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, FALSE)");
3895 break;
3897 case WINED3DRS_EDGEANTIALIAS :
3899 if(Value) {
3900 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3901 glEnable(GL_BLEND);
3902 checkGLcall("glEnable(GL_BLEND)");
3903 glEnable(GL_LINE_SMOOTH);
3904 checkGLcall("glEnable(GL_LINE_SMOOTH)");
3905 } else {
3906 glDisable(GL_BLEND);
3907 checkGLcall("glDisable(GL_BLEND)");
3908 glDisable(GL_LINE_SMOOTH);
3909 checkGLcall("glDisable(GL_LINE_SMOOTH)");
3911 break;
3913 case WINED3DRS_WRAP0 :
3914 case WINED3DRS_WRAP1 :
3915 case WINED3DRS_WRAP2 :
3916 case WINED3DRS_WRAP3 :
3917 case WINED3DRS_WRAP4 :
3918 case WINED3DRS_WRAP5 :
3919 case WINED3DRS_WRAP6 :
3920 case WINED3DRS_WRAP7 :
3921 case WINED3DRS_WRAP8 :
3922 case WINED3DRS_WRAP9 :
3923 case WINED3DRS_WRAP10 :
3924 case WINED3DRS_WRAP11 :
3925 case WINED3DRS_WRAP12 :
3926 case WINED3DRS_WRAP13 :
3927 case WINED3DRS_WRAP14 :
3928 case WINED3DRS_WRAP15 :
3930 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
3931 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
3932 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
3933 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
3934 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
3936 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
3938 TRACE("(%p)->(%s,%ld) Texture wraping not yet supported\n",This, debug_d3drenderstate(State), Value);
3939 break;
3940 case WINED3DRS_MULTISAMPLEANTIALIAS :
3942 if (!GL_SUPPORT(ARB_MULTISAMPLE)) {
3943 TRACE("Multisample antialiasing not supported\n");
3944 break;
3947 if(Value) {
3948 glEnable(GL_MULTISAMPLE_ARB);
3949 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
3950 } else {
3951 glDisable(GL_MULTISAMPLE_ARB);
3952 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
3954 break;
3956 case WINED3DRS_SCISSORTESTENABLE :
3958 if(Value) {
3959 glEnable(GL_SCISSOR_TEST);
3960 checkGLcall("glEnable(GL_SCISSOR_TEST)");
3961 } else {
3962 glDisable(GL_SCISSOR_TEST);
3963 checkGLcall("glDisable(GL_SCISSOR_TEST)");
3965 break;
3967 case WINED3DRS_SLOPESCALEDEPTHBIAS :
3969 if(Value) {
3970 tmpvalue.d = Value;
3971 glEnable(GL_POLYGON_OFFSET_FILL);
3972 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
3973 glPolygonOffset(tmpvalue.f, *((float*)&This->stateBlock->renderState[WINED3DRS_DEPTHBIAS]));
3974 checkGLcall("glPolygonOffset(...)");
3975 } else {
3976 glDisable(GL_POLYGON_OFFSET_FILL);
3977 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
3979 break;
3981 case WINED3DRS_ANTIALIASEDLINEENABLE :
3983 if(Value) {
3984 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3985 glEnable(GL_BLEND);
3986 checkGLcall("glEnable(GL_BLEND)");
3987 glEnable(GL_LINE_SMOOTH);
3988 checkGLcall("glEnable(GL_LINE_SMOOTH)");
3989 } else {
3990 glDisable(GL_BLEND);
3991 checkGLcall("glDisable(GL_BLEND)");
3992 glDisable(GL_LINE_SMOOTH);
3993 checkGLcall("glDisable(GL_LINE_SMOOTH)");
3995 break;
3997 case WINED3DRS_TWOSIDEDSTENCILMODE :
3999 if(Value) {
4000 TRACE("Two-sided stencil mode enabled\n");
4001 } else {
4002 TRACE("Two-sided stencil mode disabled\n");
4004 break;
4006 case WINED3DRS_CCW_STENCILFAIL :
4007 case WINED3DRS_CCW_STENCILZFAIL :
4008 case WINED3DRS_CCW_STENCILPASS :
4010 GLint stencilFail;
4011 GLint depthFail;
4012 GLint stencilPass;
4014 GLint action = StencilOp(Value);
4016 glGetIntegerv(GL_STENCIL_BACK_FAIL, &stencilFail);
4017 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &depthFail);
4018 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS, &stencilPass);
4020 if(WINED3DRS_CCW_STENCILFAIL == State) {
4021 stencilFail = action;
4023 else if(WINED3DRS_CCW_STENCILZFAIL == State) {
4024 depthFail = action;
4026 else if(WINED3DRS_CCW_STENCILPASS == State) {
4027 stencilPass = action;
4030 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
4031 #if 0 /* Don't use OpenGL 2.0 calls for now */
4032 if(GL_EXTCALL(glStencilOpSeparate)) {
4033 GL_EXTCALL(glStencilOpSeparate(GL_BACK, stencilFail, depthFail, stencilPass));
4034 checkGLcall("glStencilOpSeparate(GL_BACK,...)");
4036 else
4037 #endif
4038 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
4039 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
4040 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
4041 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
4042 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
4043 glStencilOp(stencilFail, depthFail, stencilPass);
4044 checkGLcall("glStencilOp(...)");
4046 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
4047 GL_EXTCALL(glStencilOpSeparateATI(GL_BACK, stencilFail, depthFail, stencilPass));
4048 checkGLcall("glStencilOpSeparateATI(GL_BACK,...)");
4049 } else {
4050 TRACE("Separate stencil operation not supported on this version of opengl");
4051 glStencilOp(stencilFail, depthFail, stencilPass);
4052 checkGLcall("glStencilOp(...)");
4054 } else {
4055 glStencilOp(stencilFail, depthFail, stencilPass);
4056 checkGLcall("glStencilOp(...)");
4058 break;
4060 case WINED3DRS_CCW_STENCILFUNC :
4062 GLint func;
4063 GLint ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
4064 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
4066 func = GL_ALWAYS;
4067 switch ((D3DCMPFUNC)Value) {
4068 case D3DCMP_NEVER: func = GL_NEVER; break;
4069 case D3DCMP_LESS: func = GL_LESS; break;
4070 case D3DCMP_EQUAL: func = GL_EQUAL; break;
4071 case D3DCMP_LESSEQUAL: func = GL_LEQUAL; break;
4072 case D3DCMP_GREATER: func = GL_GREATER; break;
4073 case D3DCMP_NOTEQUAL: func = GL_NOTEQUAL; break;
4074 case D3DCMP_GREATEREQUAL: func = GL_GEQUAL; break;
4075 case D3DCMP_ALWAYS: func = GL_ALWAYS; break;
4076 default:
4077 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
4079 This->stencilfunc = func;
4080 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
4081 #if 0 /* Don't use OpenGL 2.0 calls for now */
4082 if(GL_EXTCALL(glStencilFuncSeparate)) {
4083 GL_EXTCALL(glStencilFuncSeparate(GL_BACK, func, ref, mask));
4084 checkGLcall("glStencilFuncSeparate(GL_BACK,...)");
4086 else
4087 #endif
4088 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
4089 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
4090 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
4091 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
4092 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
4093 glStencilFunc(func, ref, mask);
4094 checkGLcall("glStencilFunc(...)");
4096 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
4097 GL_EXTCALL(glStencilFuncSeparateATI(GL_BACK, func, ref, mask));
4098 checkGLcall("glStencilFuncSeparateATI(GL_BACK,...)");
4099 } else {
4100 TRACE("Separate stencil function not supported on this version of opengl");
4101 glStencilFunc(func, ref, mask);
4102 checkGLcall("glStencilFunc(...)");
4104 } else {
4105 glStencilFunc(func, ref, mask);
4106 checkGLcall("glStencilFunc(...)");
4108 break;
4110 case WINED3DRS_DEPTHBIAS :
4112 if(Value) {
4113 tmpvalue.d = Value;
4114 glEnable(GL_POLYGON_OFFSET_FILL);
4115 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4116 glPolygonOffset(*((float*)&This->stateBlock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS]), tmpvalue.f);
4117 checkGLcall("glPolygonOffset(...)");
4118 } else {
4119 glDisable(GL_POLYGON_OFFSET_FILL);
4120 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4122 break;
4124 case WINED3DRS_SEPARATEALPHABLENDENABLE :
4125 case WINED3DRS_SRCBLENDALPHA :
4126 case WINED3DRS_DESTBLENDALPHA :
4127 case WINED3DRS_BLENDOPALPHA :
4128 case WINED3DRS_MULTISAMPLEMASK :
4129 case WINED3DRS_PATCHEDGESTYLE :
4130 case WINED3DRS_PATCHSEGMENTS :
4131 case WINED3DRS_DEBUGMONITORTOKEN :
4132 case WINED3DRS_POSITIONORDER :
4133 case WINED3DRS_NORMALORDER :
4134 case WINED3DRS_MINTESSELLATIONLEVEL :
4135 case WINED3DRS_MAXTESSELLATIONLEVEL :
4136 case WINED3DRS_ADAPTIVETESS_X :
4137 case WINED3DRS_ADAPTIVETESS_Y :
4138 case WINED3DRS_ADAPTIVETESS_Z :
4139 case WINED3DRS_ADAPTIVETESS_W :
4140 case WINED3DRS_ENABLEADAPTIVETESSELLATION :
4141 case WINED3DRS_COLORWRITEENABLE1 :
4142 case WINED3DRS_COLORWRITEENABLE2 :
4143 case WINED3DRS_COLORWRITEENABLE3 :
4144 case WINED3DRS_BLENDFACTOR :
4145 case WINED3DRS_SRGBWRITEENABLE :
4146 FIXME("(%p)->(%s,%ld) not handled yet\n", This, debug_d3drenderstate(State), Value);
4147 break;
4148 default:
4149 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
4152 LEAVE_GL();
4154 return WINED3D_OK;
4157 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
4158 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4159 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
4160 *pValue = This->stateBlock->renderState[State];
4161 return WINED3D_OK;
4164 /*****
4165 * Get / Set Sampler States
4166 * TODO: Verify against dx9 definitions
4167 *****/
4169 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
4170 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4172 * SetSampler is designed to allow for more than the standard up to 8 textures
4173 * and Geforce has stopped supporting more than 6 standard textures in openGL.
4174 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
4176 * http://developer.nvidia.com/object/General_FAQ.html#t6
4178 * There are two new settings for GForce
4179 * the sampler one:
4180 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
4181 * and the texture one:
4182 * GL_MAX_TEXTURE_COORDS_ARB.
4183 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
4184 ******************/
4185 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
4186 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
4188 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
4189 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE, Sampler, Type);
4190 return WINED3DERR_INVALIDCALL;
4192 TRACE("Setting sampler %ld %d to %ld\n", Sampler, Type, Value);
4193 This->updateStateBlock->samplerState[Sampler][Type] = Value;
4194 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
4195 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
4197 /* Handle recording of state blocks */
4198 if (This->isRecordingState) {
4199 TRACE("Recording... not performing anything\n");
4200 return WINED3D_OK;
4203 return WINED3D_OK;
4206 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
4207 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4208 /** TODO: check that sampler is in range **/
4209 *Value = This->updateStateBlock->samplerState[Sampler][Type];
4210 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
4212 return WINED3D_OK;
4215 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
4216 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4217 ENTER_GL();
4219 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4220 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4221 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
4222 LEAVE_GL();
4224 return WINED3D_OK;
4227 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
4228 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4229 GLint scissorBox[4];
4231 ENTER_GL();
4232 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4233 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
4234 pRect->left = scissorBox[1];
4235 pRect->top = scissorBox[2];
4236 pRect->right = scissorBox[1] + scissorBox[3];
4237 pRect->bottom = scissorBox[2] + scissorBox[4];
4238 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4239 LEAVE_GL();
4240 return WINED3D_OK;
4243 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
4244 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4245 IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
4247 TRACE("(%p) : pDecl=%p\n", This, pDecl);
4249 This->updateStateBlock->vertexDecl = pDecl;
4250 This->updateStateBlock->changed.vertexDecl = TRUE;
4251 This->updateStateBlock->set.vertexDecl = TRUE;
4253 if (This->isRecordingState) {
4254 TRACE("Recording... not performing anything\n");
4257 if (NULL != pDecl) {
4258 IWineD3DVertexDeclaration_AddRef(pDecl);
4260 if (NULL != oldDecl) {
4261 IWineD3DVertexDeclaration_Release(oldDecl);
4263 return WINED3D_OK;
4266 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
4267 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4269 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
4271 *ppDecl = This->stateBlock->vertexDecl;
4272 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
4273 return WINED3D_OK;
4276 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
4277 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4278 IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
4280 This->updateStateBlock->vertexShader = pShader;
4281 This->updateStateBlock->changed.vertexShader = TRUE;
4282 This->updateStateBlock->set.vertexShader = TRUE;
4284 if (This->isRecordingState) {
4285 TRACE("Recording... not performing anything\n");
4288 if (NULL != pShader) {
4289 IWineD3DVertexShader_AddRef(pShader);
4291 if (NULL != oldShader) {
4292 IWineD3DVertexShader_Release(oldShader);
4295 if (pShader != NULL && ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration != NULL) {
4296 TRACE("(%p) : setting vertexDeclaration(%p)\n", This, ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration);
4297 IWineD3DDevice_SetVertexDeclaration(iface, ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration);
4300 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4302 * TODO: merge HAL shaders context switching from prototype
4304 return WINED3D_OK;
4307 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
4308 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4310 if (NULL == ppShader) {
4311 return WINED3DERR_INVALIDCALL;
4313 *ppShader = This->stateBlock->vertexShader;
4314 if( NULL != *ppShader)
4315 IWineD3DVertexShader_AddRef(*ppShader);
4317 TRACE("(%p) : returning %p\n", This, *ppShader);
4318 return WINED3D_OK;
4321 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4322 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4324 int i;
4325 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4327 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4328 iface, dstData, srcData, type, start, count, registersize);
4330 if (type != WINESHADERCNST_NONE) {
4331 if (srcData == NULL || cnt < 0) {
4332 return WINED3DERR_INVALIDCALL;
4335 CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
4338 for (i = start; i < cnt + start; ++i) {
4339 This->updateStateBlock->changed.vertexShaderConstants[i] = TRUE;
4340 This->updateStateBlock->set.vertexShaderConstants[i] = TRUE;
4341 This->updateStateBlock->vertexShaderConstantT[i] = type;
4344 return WINED3D_OK;
4347 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4348 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4350 int i;
4351 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4353 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4354 iface, dstData, srcData, type, start, count, registersize);
4356 /* Verify that the requested shader constant was populated with the correct type */
4357 for (i = start; i < cnt + start; ++i) {
4358 if (This->updateStateBlock->vertexShaderConstantT[i] != type) {
4359 TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning WINED3DERR_INVALIDCALL\n",
4360 This, type, This->updateStateBlock->vertexShaderConstantT[i]);
4361 return WINED3DERR_INVALIDCALL;
4365 if (dstData == NULL || cnt < 0) {
4366 return WINED3DERR_INVALIDCALL;
4369 CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
4371 return WINED3D_OK;
4374 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
4375 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4377 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4378 This->updateStateBlock->vertexShaderConstantB,
4379 pConstantData,
4380 WINESHADERCNST_BOOL,
4381 StartRegister,
4382 BoolCount,
4383 sizeof(*pConstantData));
4386 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
4387 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4389 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4390 pConstantData,
4391 This->updateStateBlock->vertexShaderConstantB,
4392 WINESHADERCNST_BOOL,
4393 StartRegister,
4394 BoolCount,
4395 sizeof(*pConstantData));
4398 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
4399 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4401 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4402 This->updateStateBlock->vertexShaderConstantI,
4403 pConstantData,
4404 WINESHADERCNST_INTEGER,
4405 StartRegister,
4406 Vector4iCount,
4407 4 * sizeof(*pConstantData));
4410 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
4411 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4413 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4414 pConstantData,
4415 This->updateStateBlock->vertexShaderConstantI,
4416 WINESHADERCNST_INTEGER,
4417 StartRegister,
4418 Vector4iCount,
4419 4 * sizeof(*pConstantData));
4423 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
4424 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4426 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4427 This->updateStateBlock->vertexShaderConstantF,
4428 pConstantData,
4429 WINESHADERCNST_FLOAT,
4430 StartRegister,
4431 Vector4fCount,
4432 4 * sizeof(*pConstantData));
4435 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
4436 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4438 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4439 pConstantData,
4440 This->updateStateBlock->vertexShaderConstantF,
4441 WINESHADERCNST_FLOAT,
4442 StartRegister,
4443 Vector4fCount,
4444 4 * sizeof(*pConstantData));
4447 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
4448 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4449 NULL,
4450 NULL,
4451 WINESHADERCNST_NONE,
4452 StartRegister,
4453 VectorNCount,
4457 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
4458 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4459 IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader;
4460 This->updateStateBlock->pixelShader = pShader;
4461 This->updateStateBlock->changed.pixelShader = TRUE;
4462 This->updateStateBlock->set.pixelShader = TRUE;
4464 /* Handle recording of state blocks */
4465 if (This->isRecordingState) {
4466 TRACE("Recording... not performing anything\n");
4469 if (NULL != pShader) {
4470 IWineD3DPixelShader_AddRef(pShader);
4472 if (NULL != oldShader) {
4473 IWineD3DPixelShader_Release(oldShader);
4476 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4478 * TODO: merge HAL shaders context switching from prototype
4480 return WINED3D_OK;
4483 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
4484 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4486 if (NULL == ppShader) {
4487 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
4488 return WINED3DERR_INVALIDCALL;
4491 *ppShader = This->stateBlock->pixelShader;
4492 if (NULL != *ppShader) {
4493 IWineD3DPixelShader_AddRef(*ppShader);
4495 TRACE("(%p) : returning %p\n", This, *ppShader);
4496 return WINED3D_OK;
4499 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4500 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4502 int i;
4503 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4505 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4506 iface, dstData, srcData, type, start, count, registersize);
4508 if (type != WINESHADERCNST_NONE) {
4509 if (srcData == NULL || cnt < 0) {
4510 return WINED3DERR_INVALIDCALL;
4513 CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
4516 for (i = start; i < cnt + start; ++i) {
4517 This->updateStateBlock->changed.pixelShaderConstants[i] = TRUE;
4518 This->updateStateBlock->set.pixelShaderConstants[i] = TRUE;
4519 This->updateStateBlock->pixelShaderConstantT[i] = type;
4522 return WINED3D_OK;
4525 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4526 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4528 int i;
4529 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4531 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4532 iface, dstData, srcData, type, start, count, registersize);
4534 /* Verify that the requested shader constant was populated with the correct type */
4535 for (i = start; i < cnt + start; ++i) {
4536 if (This->updateStateBlock->pixelShaderConstantT[i] != type) {
4537 TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning WINED3DERR_INVALIDCALL\n",
4538 This, type, This->updateStateBlock->pixelShaderConstantT[i]);
4539 return WINED3DERR_INVALIDCALL;
4543 if (dstData == NULL || cnt < 0) {
4544 return WINED3DERR_INVALIDCALL;
4547 CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
4549 return WINED3D_OK;
4552 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
4553 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4555 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4556 This->updateStateBlock->pixelShaderConstantB,
4557 pConstantData,
4558 WINESHADERCNST_BOOL,
4559 StartRegister,
4560 BoolCount,
4561 sizeof(*pConstantData));
4564 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
4565 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4567 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4568 pConstantData,
4569 This->updateStateBlock->pixelShaderConstantB,
4570 WINESHADERCNST_BOOL,
4571 StartRegister,
4572 BoolCount,
4573 sizeof(*pConstantData));
4576 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
4577 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4579 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4580 This->updateStateBlock->pixelShaderConstantI,
4581 pConstantData,
4582 WINESHADERCNST_INTEGER,
4583 StartRegister,
4584 Vector4iCount,
4585 4 * sizeof(*pConstantData));
4588 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
4589 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4591 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4592 pConstantData,
4593 This->updateStateBlock->pixelShaderConstantI,
4594 WINESHADERCNST_INTEGER,
4595 StartRegister,
4596 Vector4iCount,
4597 4 * sizeof(*pConstantData));
4600 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
4601 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4603 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4604 This->updateStateBlock->pixelShaderConstantF,
4605 pConstantData,
4606 WINESHADERCNST_FLOAT,
4607 StartRegister,
4608 Vector4fCount,
4609 4 * sizeof(*pConstantData));
4612 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
4613 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4615 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4616 pConstantData,
4617 This->updateStateBlock->pixelShaderConstantF,
4618 WINESHADERCNST_FLOAT,
4619 StartRegister,
4620 Vector4fCount,
4621 4 * sizeof(*pConstantData));
4624 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
4625 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4626 NULL,
4627 NULL,
4628 WINESHADERCNST_NONE,
4629 StartRegister,
4630 VectorNCount,
4634 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
4635 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4636 FIXME("(%p) : stub\n", This);
4637 return WINED3D_OK;
4640 /*****
4641 * Apply / Get / Set Texture Stage States
4642 * TODO: Verify against dx9 definitions
4643 *****/
4645 /* 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 */
4646 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
4647 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4648 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
4649 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4651 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4653 /* Check that the stage is within limits */
4654 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4655 TRACE("Attempt to access invalid texture rejected\n");
4656 return;
4659 ENTER_GL();
4661 switch (Type) {
4662 case WINED3DTSS_ALPHAOP :
4663 case WINED3DTSS_COLOROP :
4664 /* nothing to do as moved to drawprim for now */
4665 break;
4666 case WINED3DTSS_ADDRESSW :
4667 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
4668 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
4669 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
4671 } else {
4672 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
4673 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
4674 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
4675 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
4677 #endif
4678 case WINED3DTSS_TEXCOORDINDEX :
4680 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
4682 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
4683 one flag, you can still specify an index value, which the system uses to
4684 determine the texture wrapping mode.
4685 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
4686 means use the vertex position (camera-space) as the input texture coordinates
4687 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
4688 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
4689 to the TEXCOORDINDEX value */
4692 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
4694 switch (Value & 0xFFFF0000) {
4695 case D3DTSS_TCI_PASSTHRU:
4696 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
4697 glDisable(GL_TEXTURE_GEN_S);
4698 glDisable(GL_TEXTURE_GEN_T);
4699 glDisable(GL_TEXTURE_GEN_R);
4700 glDisable(GL_TEXTURE_GEN_Q);
4701 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
4702 break;
4704 case D3DTSS_TCI_CAMERASPACEPOSITION:
4705 /* CameraSpacePosition means use the vertex position, transformed to camera space,
4706 as the input texture coordinates for this stage's texture transformation. This
4707 equates roughly to EYE_LINEAR */
4709 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4710 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4711 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4712 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4713 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4715 glMatrixMode(GL_MODELVIEW);
4716 glPushMatrix();
4717 glLoadIdentity();
4718 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4719 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4720 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4721 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4722 glPopMatrix();
4724 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
4725 glEnable(GL_TEXTURE_GEN_S);
4726 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4727 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4728 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4729 glEnable(GL_TEXTURE_GEN_T);
4730 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4731 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4732 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4733 glEnable(GL_TEXTURE_GEN_R);
4734 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4735 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4736 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4738 break;
4740 case D3DTSS_TCI_CAMERASPACENORMAL:
4742 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4743 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4744 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4745 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4746 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4747 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
4749 glMatrixMode(GL_MODELVIEW);
4750 glPushMatrix();
4751 glLoadIdentity();
4752 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4753 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4754 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4755 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4756 glPopMatrix();
4758 glEnable(GL_TEXTURE_GEN_S);
4759 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4760 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4761 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4762 glEnable(GL_TEXTURE_GEN_T);
4763 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4764 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4765 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4766 glEnable(GL_TEXTURE_GEN_R);
4767 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4768 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4769 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4772 break;
4774 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
4776 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4777 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4778 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4779 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4780 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4781 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
4783 glMatrixMode(GL_MODELVIEW);
4784 glPushMatrix();
4785 glLoadIdentity();
4786 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4787 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4788 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4789 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4790 glPopMatrix();
4792 glEnable(GL_TEXTURE_GEN_S);
4793 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4794 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4795 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4796 glEnable(GL_TEXTURE_GEN_T);
4797 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4798 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4799 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4800 glEnable(GL_TEXTURE_GEN_R);
4801 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4802 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4803 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4806 break;
4808 /* Unhandled types: */
4809 default:
4810 /* Todo: */
4811 /* ? disable GL_TEXTURE_GEN_n ? */
4812 glDisable(GL_TEXTURE_GEN_S);
4813 glDisable(GL_TEXTURE_GEN_T);
4814 glDisable(GL_TEXTURE_GEN_R);
4815 glDisable(GL_TEXTURE_GEN_Q);
4816 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
4817 break;
4820 break;
4822 /* Unhandled */
4823 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
4824 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);
4825 break;
4827 case WINED3DTSS_BUMPENVMAT00 :
4828 case WINED3DTSS_BUMPENVMAT01 :
4829 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
4830 break;
4831 case WINED3DTSS_BUMPENVMAT10 :
4832 case WINED3DTSS_BUMPENVMAT11 :
4833 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
4834 break;
4836 case WINED3DTSS_BUMPENVLSCALE :
4837 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4838 break;
4840 case WINED3DTSS_BUMPENVLOFFSET :
4841 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4842 break;
4844 case WINED3DTSS_RESULTARG :
4845 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4846 break;
4848 default:
4849 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
4850 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4853 LEAVE_GL();
4855 return;
4858 /*****
4859 * Get / Set Texture Stage States
4860 * TODO: Verify against dx9 definitions
4861 *****/
4862 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
4863 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4865 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4867 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4869 /* Reject invalid texture units */
4870 if (Stage >= GL_LIMITS(textures)) {
4871 TRACE("Attempt to access invalid texture rejected\n");
4872 return WINED3DERR_INVALIDCALL;
4875 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
4876 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
4877 This->updateStateBlock->textureState[Stage][Type] = Value;
4879 return WINED3D_OK;
4882 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4883 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4884 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4885 *pValue = This->updateStateBlock->textureState[Stage][Type];
4886 return WINED3D_OK;
4889 /*****
4890 * Get / Set Texture
4891 *****/
4892 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4894 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4895 IWineD3DBaseTexture *oldTexture;
4897 oldTexture = This->updateStateBlock->textures[Stage];
4898 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
4900 #if 0 /* TODO: check so vertex textures */
4901 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
4902 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
4903 return WINED3D_OK;
4905 #endif
4907 /* Reject invalid texture units */
4908 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4909 WARN("Attempt to access invalid texture rejected\n");
4910 return WINED3DERR_INVALIDCALL;
4913 if(pTexture != NULL) {
4914 /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH; The same is
4915 * the case for WINED3DPOOL_SYSTEMMEM textures unless WINED3DDEVCAPS_TEXTURESYSTEMMORY is set.
4916 * We don't check the caps as GetDeviceCaps is inefficient and we don't set the cap anyway.
4918 if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH || ((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SYSTEMMEM) {
4919 WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
4920 return WINED3DERR_INVALIDCALL;
4924 oldTexture = This->updateStateBlock->textures[Stage];
4925 TRACE("GL_LIMITS %d\n",GL_LIMITS(textures));
4926 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
4928 This->updateStateBlock->set.textures[Stage] = TRUE;
4929 This->updateStateBlock->changed.textures[Stage] = TRUE;
4930 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
4931 This->updateStateBlock->textures[Stage] = pTexture;
4933 /* Handle recording of state blocks */
4934 if (This->isRecordingState) {
4935 TRACE("Recording... not performing anything\n");
4936 return WINED3D_OK;
4939 /** NOTE: MSDN says that setTexture increases the reference count,
4940 * and the the application nust set the texture back to null (or have a leaky application),
4941 * This means we should pass the refcount up to the parent
4942 *******************************/
4943 if (NULL != This->updateStateBlock->textures[Stage]) {
4944 IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
4947 if (NULL != oldTexture) {
4948 IWineD3DBaseTexture_Release(oldTexture);
4951 return WINED3D_OK;
4954 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4955 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4956 TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
4958 /* Reject invalid texture units */
4959 if (Stage >= GL_LIMITS(textures)) {
4960 TRACE("Attempt to access invalid texture rejected\n");
4961 return WINED3DERR_INVALIDCALL;
4963 *ppTexture=This->updateStateBlock->textures[Stage];
4964 if (*ppTexture)
4965 IWineD3DBaseTexture_AddRef(*ppTexture);
4966 else
4967 return WINED3DERR_INVALIDCALL;
4968 return WINED3D_OK;
4971 /*****
4972 * Get Back Buffer
4973 *****/
4974 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
4975 IWineD3DSurface **ppBackBuffer) {
4976 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4977 IWineD3DSwapChain *swapChain;
4978 HRESULT hr;
4980 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4982 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4983 if (hr == WINED3D_OK) {
4984 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4985 IWineD3DSwapChain_Release(swapChain);
4986 } else {
4987 *ppBackBuffer = NULL;
4989 return hr;
4992 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4993 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4994 WARN("(%p) : stub, calling idirect3d for now\n", This);
4995 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4998 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
4999 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5000 IWineD3DSwapChain *swapChain;
5001 HRESULT hr;
5003 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5004 if (hr == WINED3D_OK) {
5005 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
5006 IWineD3DSwapChain_Release(swapChain);
5007 } else {
5008 FIXME("(%p) Error getting display mode\n", This);
5010 return hr;
5013 HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
5014 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5015 TRACE("(%p)->(%p)\n", This, hWnd);
5017 This->ddraw_window = hWnd;
5018 return WINED3D_OK;
5021 HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
5022 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5023 TRACE("(%p)->(%p)\n", This, hWnd);
5025 *hWnd = This->ddraw_window;
5026 return WINED3D_OK;
5029 /*****
5030 * Stateblock related functions
5031 *****/
5033 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
5034 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5035 IWineD3DStateBlockImpl *object;
5036 TRACE("(%p)", This);
5038 if (This->isRecordingState) {
5039 return WINED3DERR_INVALIDCALL;
5042 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
5043 if (NULL == object ) {
5044 FIXME("(%p)Error allocating memory for stateblock\n", This);
5045 return E_OUTOFMEMORY;
5047 TRACE("(%p) creted object %p\n", This, object);
5048 object->wineD3DDevice= This;
5049 /** FIXME: object->parent = parent; **/
5050 object->parent = NULL;
5051 object->blockType = WINED3DSBT_ALL;
5052 object->ref = 1;
5053 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
5055 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
5056 This->updateStateBlock = object;
5057 This->isRecordingState = TRUE;
5059 TRACE("(%p) recording stateblock %p\n",This , object);
5060 return WINED3D_OK;
5063 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
5064 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5066 if (!This->isRecordingState) {
5067 FIXME("(%p) not recording! returning error\n", This);
5068 *ppStateBlock = NULL;
5069 return WINED3DERR_INVALIDCALL;
5072 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
5073 This->isRecordingState = FALSE;
5074 This->updateStateBlock = This->stateBlock;
5075 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
5076 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
5077 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
5078 return WINED3D_OK;
5081 /*****
5082 * Scene related functions
5083 *****/
5084 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
5085 /* At the moment we have no need for any functionality at the beginning
5086 of a scene */
5087 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5088 TRACE("(%p) : stub\n", This);
5089 return WINED3D_OK;
5092 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
5093 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5094 TRACE("(%p)\n", This);
5095 ENTER_GL();
5096 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
5097 glFlush();
5098 checkGLcall("glFlush");
5100 TRACE("End Scene\n");
5101 if(This->renderTarget != NULL) {
5103 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
5104 IUnknown *targetContainer = NULL;
5105 if (WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
5106 || WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
5107 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
5108 /** always dirtify for now. we must find a better way to see that surface have been modified
5109 (Modifications should will only occur via draw-primitive, but we do need better locking
5110 switching to render-to-texture should remove the overhead though.
5112 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
5113 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
5114 IWineD3DSurface_PreLoad(This->renderTarget);
5115 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
5116 IUnknown_Release(targetContainer);
5119 This->sceneEnded = TRUE;
5120 LEAVE_GL();
5121 return WINED3D_OK;
5124 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
5125 CONST RECT* pSourceRect, CONST RECT* pDestRect,
5126 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
5127 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5128 IWineD3DSwapChain *swapChain = NULL;
5129 int i;
5130 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
5132 TRACE("(%p) Presenting the frame\n", This);
5134 for(i = 0 ; i < swapchains ; i ++) {
5136 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
5137 TRACE("presentinng chain %d, %p\n", i, swapChain);
5138 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
5139 IWineD3DSwapChain_Release(swapChain);
5142 return WINED3D_OK;
5145 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
5146 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
5147 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5149 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
5150 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
5151 when the depth-buffer format does not contain stencil buffer information, this method fails. */
5152 GLbitfield glMask = 0;
5153 GLboolean old_ztest;
5154 GLfloat old_z_clear_value;
5155 GLint old_stencil_clear_value;
5156 GLfloat old_color_clear_value[4];
5157 unsigned int i;
5158 CONST D3DRECT* curRect;
5160 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
5161 Count, pRects, Flags, Z, Stencil);
5163 ENTER_GL();
5165 glEnable(GL_SCISSOR_TEST);
5166 checkGLcall("glEnable GL_SCISSOR_TEST");
5168 if (Count > 0 && pRects) {
5169 curRect = pRects;
5170 } else {
5171 curRect = NULL;
5174 /* Only set the values up once, as they are not changing */
5175 if (Flags & D3DCLEAR_STENCIL) {
5176 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
5177 glClearStencil(Stencil);
5178 checkGLcall("glClearStencil");
5179 glMask = glMask | GL_STENCIL_BUFFER_BIT;
5180 glStencilMask(0xFFFFFFFF);
5183 if (Flags & D3DCLEAR_ZBUFFER) {
5184 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
5185 glDepthMask(GL_TRUE);
5186 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
5187 glClearDepth(Z);
5188 checkGLcall("glClearDepth");
5189 glMask = glMask | GL_DEPTH_BUFFER_BIT;
5192 if (Flags & D3DCLEAR_TARGET) {
5193 TRACE("Clearing screen with glClear to color %lx\n", Color);
5194 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
5195 glClearColor(D3DCOLOR_R(Color),
5196 D3DCOLOR_G(Color),
5197 D3DCOLOR_B(Color),
5198 D3DCOLOR_A(Color));
5199 checkGLcall("glClearColor");
5201 /* Clear ALL colors! */
5202 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5203 glMask = glMask | GL_COLOR_BUFFER_BIT;
5206 /* Now process each rect in turn */
5207 for (i = 0; i < Count || i == 0; i++) {
5209 if (curRect) {
5210 /* Note gl uses lower left, width/height */
5211 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
5212 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
5213 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
5214 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
5215 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
5216 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
5217 checkGLcall("glScissor");
5218 } else {
5219 glScissor(This->stateBlock->viewport.X,
5220 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
5221 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
5222 This->stateBlock->viewport.Width,
5223 This->stateBlock->viewport.Height);
5224 checkGLcall("glScissor");
5227 /* Clear the selected rectangle (or full screen) */
5228 glClear(glMask);
5229 checkGLcall("glClear");
5231 /* Step to the next rectangle */
5232 if (curRect) curRect = curRect + sizeof(D3DRECT);
5235 /* Restore the old values (why..?) */
5236 if (Flags & D3DCLEAR_STENCIL) {
5237 glClearStencil(old_stencil_clear_value);
5238 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
5240 if (Flags & D3DCLEAR_ZBUFFER) {
5241 glDepthMask(old_ztest);
5242 glClearDepth(old_z_clear_value);
5244 if (Flags & D3DCLEAR_TARGET) {
5245 glClearColor(old_color_clear_value[0],
5246 old_color_clear_value[1],
5247 old_color_clear_value[2],
5248 old_color_clear_value[3]);
5249 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
5250 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
5251 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
5252 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
5255 glDisable(GL_SCISSOR_TEST);
5256 checkGLcall("glDisable");
5257 LEAVE_GL();
5259 return WINED3D_OK;
5262 /*****
5263 * Drawing functions
5264 *****/
5265 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
5266 UINT PrimitiveCount) {
5268 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5269 This->stateBlock->streamIsUP = FALSE;
5271 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
5272 debug_d3dprimitivetype(PrimitiveType),
5273 StartVertex, PrimitiveCount);
5274 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
5275 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
5278 return WINED3D_OK;
5281 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
5282 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
5283 D3DPRIMITIVETYPE PrimitiveType,
5284 INT baseVIndex, UINT minIndex,
5285 UINT NumVertices, UINT startIndex, UINT primCount) {
5287 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5288 UINT idxStride = 2;
5289 IWineD3DIndexBuffer *pIB;
5290 WINED3DINDEXBUFFER_DESC IdxBufDsc;
5292 pIB = This->stateBlock->pIndexData;
5293 This->stateBlock->streamIsUP = FALSE;
5295 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
5296 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5297 minIndex, NumVertices, startIndex, baseVIndex, primCount);
5299 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
5300 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
5301 idxStride = 2;
5302 } else {
5303 idxStride = 4;
5306 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
5307 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
5309 return WINED3D_OK;
5312 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
5313 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
5314 UINT VertexStreamZeroStride) {
5315 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5317 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
5318 debug_d3dprimitivetype(PrimitiveType),
5319 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
5321 /* release the stream source */
5322 if (This->stateBlock->streamSource[0] != NULL) {
5323 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5326 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5327 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5328 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5329 This->stateBlock->streamIsUP = TRUE;
5331 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
5332 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
5333 /* stream zero settings set to null at end, as per the msdn
5334 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
5336 This->stateBlock->streamStride[0] = 0;
5337 This->stateBlock->streamSource[0] = NULL;
5339 /*stream zero settings set to null at end, as per the msdn */
5340 return WINED3D_OK;
5343 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
5344 UINT MinVertexIndex, UINT NumVertices,
5345 UINT PrimitiveCount, CONST void* pIndexData,
5346 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
5347 UINT VertexStreamZeroStride) {
5348 int idxStride;
5349 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5351 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
5352 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5353 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
5354 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
5356 if (IndexDataFormat == WINED3DFMT_INDEX16) {
5357 idxStride = 2;
5358 } else {
5359 idxStride = 4;
5362 /* release the stream and index data */
5363 if (This->stateBlock->streamSource[0] != NULL) {
5364 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5366 if (This->stateBlock->pIndexData) {
5367 IWineD3DIndexBuffer_Release(This->stateBlock->pIndexData);
5370 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5371 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5372 This->stateBlock->streamIsUP = TRUE;
5373 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5375 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
5376 /* stream zero settings set to null at end as per the msdn
5377 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
5380 /* stream zero settings set to null at end as per the msdn */
5381 This->stateBlock->streamSource[0] = NULL;
5382 This->stateBlock->streamStride[0] = 0;
5384 return WINED3D_OK;
5387 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
5388 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
5389 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5390 HRESULT hr = WINED3D_OK;
5391 WINED3DRESOURCETYPE sourceType;
5392 WINED3DRESOURCETYPE destinationType;
5393 int i ,levels;
5395 /* TODO: think about moving the code into IWineD3DBaseTexture */
5397 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
5399 /* verify that the source and destination textures aren't NULL */
5400 if (NULL == pSourceTexture || NULL == pDestinationTexture) {
5401 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
5402 This, pSourceTexture, pDestinationTexture);
5403 hr = WINED3DERR_INVALIDCALL;
5406 if (pSourceTexture == pDestinationTexture) {
5407 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
5408 This, pSourceTexture, pDestinationTexture);
5409 hr = WINED3DERR_INVALIDCALL;
5411 /* Verify that the source and destination textures are the same type */
5412 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
5413 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
5415 if (sourceType != destinationType) {
5416 WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
5417 This);
5418 hr = WINED3DERR_INVALIDCALL;
5421 /* check that both textures have the identical numbers of levels */
5422 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
5423 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
5424 hr = WINED3DERR_INVALIDCALL;
5427 if (WINED3D_OK == hr) {
5429 /* Make sure that the destination texture is loaded */
5430 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
5432 /* Update every surface level of the texture */
5433 levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
5435 switch (sourceType) {
5436 case WINED3DRTYPE_TEXTURE:
5438 IWineD3DSurface *srcSurface;
5439 IWineD3DSurface *destSurface;
5441 for (i = 0 ; i < levels ; ++i) {
5442 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture, i, &srcSurface);
5443 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
5444 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5445 IWineD3DSurface_Release(srcSurface);
5446 IWineD3DSurface_Release(destSurface);
5447 if (WINED3D_OK != hr) {
5448 WARN("(%p) : Call to update surface failed\n", This);
5449 return hr;
5453 break;
5454 case WINED3DRTYPE_CUBETEXTURE:
5456 IWineD3DSurface *srcSurface;
5457 IWineD3DSurface *destSurface;
5458 WINED3DCUBEMAP_FACES faceType;
5460 for (i = 0 ; i < levels ; ++i) {
5461 /* Update each cube face */
5462 for (faceType = D3DCUBEMAP_FACE_POSITIVE_X; faceType <= D3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
5463 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture, faceType, i, &srcSurface);
5464 if (WINED3D_OK != hr) {
5465 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5466 } else {
5467 TRACE("Got srcSurface %p\n", srcSurface);
5469 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
5470 if (WINED3D_OK != hr) {
5471 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5472 } else {
5473 TRACE("Got desrSurface %p\n", destSurface);
5475 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5476 IWineD3DSurface_Release(srcSurface);
5477 IWineD3DSurface_Release(destSurface);
5478 if (WINED3D_OK != hr) {
5479 WARN("(%p) : Call to update surface failed\n", This);
5480 return hr;
5485 break;
5486 #if 0 /* TODO: Add support for volume textures */
5487 case WINED3DRTYPE_VOLUMETEXTURE:
5489 IWineD3DVolume srcVolume = NULL;
5490 IWineD3DSurface destVolume = NULL;
5492 for (i = 0 ; i < levels ; ++i) {
5493 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture, i, &srcVolume);
5494 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
5495 hr = IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
5496 IWineD3DVolume_Release(srcSurface);
5497 IWineD3DVolume_Release(destSurface);
5498 if (WINED3D_OK != hr) {
5499 WARN("(%p) : Call to update volume failed\n", This);
5500 return hr;
5504 break;
5505 #endif
5506 default:
5507 FIXME("(%p) : Unsupported source and destination type\n", This);
5508 hr = WINED3DERR_INVALIDCALL;
5512 return hr;
5515 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
5516 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
5517 CONST RECT* pDestRect, WINED3DTEXTUREFILTERTYPE Filter) {
5518 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5520 TRACE("(%p) : stub\n", This);
5521 return WINED3D_OK;
5523 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
5524 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5525 /** TODO: remove remove casts to IWineD3DSurfaceImpl *
5526 * NOTE It may be best to move the code into surface to occomplish this
5527 ****************************************/
5529 WINED3DSURFACE_DESC surfaceDesc;
5530 unsigned int surfaceWidth, surfaceHeight;
5531 glDescriptor *targetGlDescription = NULL;
5532 glDescriptor *surfaceGlDescription = NULL;
5533 IWineD3DSwapChainImpl *container = NULL;
5535 IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
5536 IWineD3DSurface_GetGlDesc(pSurface, &surfaceGlDescription);
5537 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5539 surfaceDesc.Width = &surfaceWidth;
5540 surfaceDesc.Height = &surfaceHeight;
5541 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5542 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
5544 /* Ok, I may need to setup some kind of active swapchain reference on the device */
5545 IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
5546 ENTER_GL();
5547 /* TODO: opengl Context switching for swapchains etc... */
5548 if (NULL != container || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
5549 if (NULL != container && (pRenderTarget == container->backBuffer)) {
5550 glReadBuffer(GL_BACK);
5551 vcheckGLcall("glReadBuffer(GL_BACK)");
5552 } else if ((NULL != container && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
5553 glReadBuffer(GL_FRONT);
5554 vcheckGLcall("glReadBuffer(GL_FRONT)");
5555 } else if (pRenderTarget == This->depthStencilBuffer) {
5556 FIXME("Reading of depthstencil not yet supported\n");
5559 glReadPixels(surfaceGlDescription->target,
5560 surfaceGlDescription->level,
5561 surfaceWidth,
5562 surfaceHeight,
5563 surfaceGlDescription->glFormat,
5564 surfaceGlDescription->glType,
5565 (void *)IWineD3DSurface_GetData(pSurface));
5566 vcheckGLcall("glReadPixels(...)");
5567 if(NULL != container ){
5568 IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
5570 } else {
5571 IWineD3DBaseTexture *container;
5572 GLenum textureDimensions = GL_TEXTURE_2D;
5574 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
5575 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
5576 IWineD3DBaseTexture_Release(container);
5578 /* TODO: 2D -> Cube surface coppies etc.. */
5579 if (surfaceGlDescription->target != textureDimensions) {
5580 FIXME("(%p) : Texture dimension mismatch\n", This);
5582 glEnable(textureDimensions);
5583 vcheckGLcall("glEnable(GL_TEXTURE_...)");
5584 /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
5585 glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
5586 vcheckGLcall("glBindTexture");
5587 glGetTexImage(surfaceGlDescription->target,
5588 surfaceGlDescription->level,
5589 surfaceGlDescription->glFormat,
5590 surfaceGlDescription->glType,
5591 (void *)IWineD3DSurface_GetData(pSurface));
5592 glDisable(textureDimensions);
5593 vcheckGLcall("glDisable(GL_TEXTURE_...)");
5596 LEAVE_GL();
5597 return WINED3D_OK;
5600 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
5601 IWineD3DSwapChain *swapChain;
5602 HRESULT hr;
5603 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5604 if(hr == WINED3D_OK) {
5605 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
5606 IWineD3DSwapChain_Release(swapChain);
5608 return hr;
5611 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5612 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5613 /* return a sensible default */
5614 *pNumPasses = 1;
5615 /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
5616 FIXME("(%p) : stub\n", This);
5617 return WINED3D_OK;
5620 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5621 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5622 int j;
5623 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5624 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5625 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5626 return WINED3DERR_INVALIDCALL;
5628 for (j = 0; j < 256; ++j) {
5629 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
5630 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5631 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
5632 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5634 TRACE("(%p) : returning\n", This);
5635 return WINED3D_OK;
5638 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5639 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5640 int j;
5641 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5642 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5643 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5644 return WINED3DERR_INVALIDCALL;
5646 for (j = 0; j < 256; ++j) {
5647 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
5648 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5649 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
5650 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5652 TRACE("(%p) : returning\n", This);
5653 return WINED3D_OK;
5656 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5657 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5658 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5659 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5660 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5661 return WINED3DERR_INVALIDCALL;
5663 /*TODO: stateblocks */
5664 This->currentPalette = PaletteNumber;
5665 TRACE("(%p) : returning\n", This);
5666 return WINED3D_OK;
5669 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
5670 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5671 if (PaletteNumber == NULL) {
5672 WARN("(%p) : returning Invalid Call\n", This);
5673 return WINED3DERR_INVALIDCALL;
5675 /*TODO: stateblocks */
5676 *PaletteNumber = This->currentPalette;
5677 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
5678 return WINED3D_OK;
5681 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
5682 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5683 static BOOL showFixmes = TRUE;
5684 if (showFixmes) {
5685 FIXME("(%p) : stub\n", This);
5686 showFixmes = FALSE;
5689 This->softwareVertexProcessing = bSoftware;
5690 return WINED3D_OK;
5694 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
5695 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5696 static BOOL showFixmes = TRUE;
5697 if (showFixmes) {
5698 FIXME("(%p) : stub\n", This);
5699 showFixmes = FALSE;
5701 return This->softwareVertexProcessing;
5705 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
5706 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5707 IWineD3DSwapChain *swapChain;
5708 HRESULT hr;
5710 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
5712 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5713 if(hr == WINED3D_OK){
5714 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
5715 IWineD3DSwapChain_Release(swapChain);
5716 }else{
5717 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
5719 return hr;
5723 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
5724 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5725 static BOOL showfixmes = TRUE;
5726 if(nSegments != 0.0f) {
5727 if( showfixmes) {
5728 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
5729 showfixmes = FALSE;
5732 return WINED3D_OK;
5735 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
5736 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5737 static BOOL showfixmes = TRUE;
5738 if( showfixmes) {
5739 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
5740 showfixmes = FALSE;
5742 return 0.0f;
5745 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
5746 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5747 /** TODO: remove casts to IWineD3DSurfaceImpl
5748 * NOTE: move code to surface to accomplish this
5749 ****************************************/
5750 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
5751 int srcWidth, srcHeight;
5752 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
5753 WINED3DFORMAT destFormat, srcFormat;
5754 UINT destSize;
5755 int destLeft, destTop;
5756 WINED3DPOOL srcPool, destPool;
5757 int offset = 0;
5758 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
5759 glDescriptor *glDescription = NULL;
5760 GLenum textureDimensions = GL_TEXTURE_2D;
5761 IWineD3DBaseTexture *baseTexture;
5763 WINED3DSURFACE_DESC winedesc;
5765 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
5766 memset(&winedesc, 0, sizeof(winedesc));
5767 winedesc.Width = &srcSurfaceWidth;
5768 winedesc.Height = &srcSurfaceHeight;
5769 winedesc.Pool = &srcPool;
5770 winedesc.Format = &srcFormat;
5772 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5774 winedesc.Width = &destSurfaceWidth;
5775 winedesc.Height = &destSurfaceHeight;
5776 winedesc.Pool = &destPool;
5777 winedesc.Format = &destFormat;
5778 winedesc.Size = &destSize;
5780 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5782 if(srcPool != WINED3DPOOL_SYSTEMMEM || destPool != WINED3DPOOL_DEFAULT){
5783 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
5784 return WINED3DERR_INVALIDCALL;
5787 if (destFormat == WINED3DFMT_UNKNOWN) {
5788 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5789 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5791 /* Get the update surface description */
5792 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5795 /* Make sure the surface is loaded and up to date */
5796 IWineD3DSurface_PreLoad(pDestinationSurface);
5798 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
5800 ENTER_GL();
5802 /* this needs to be done in lines if the sourceRect != the sourceWidth */
5803 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
5804 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
5805 destLeft = pDestPoint ? pDestPoint->x : 0;
5806 destTop = pDestPoint ? pDestPoint->y : 0;
5809 /* This function doesn't support compressed textures
5810 the pitch is just bytesPerPixel * width */
5811 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
5812 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
5813 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
5814 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
5816 /* TODO DXT formats */
5818 if(pSourceRect != NULL && pSourceRect->top != 0){
5819 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
5821 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
5822 ,This
5823 ,glDescription->level
5824 ,destLeft
5825 ,destTop
5826 ,srcWidth
5827 ,srcHeight
5828 ,glDescription->glFormat
5829 ,glDescription->glType
5830 ,IWineD3DSurface_GetData(pSourceSurface)
5833 /* Sanity check */
5834 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
5836 /* need to lock the surface to get the data */
5837 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5840 /* TODO: Cube and volume support */
5841 if(rowoffset != 0){
5842 /* not a whole row so we have to do it a line at a time */
5843 int j;
5845 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
5846 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5848 for(j = destTop ; j < (srcHeight + destTop) ; j++){
5850 glTexSubImage2D(glDescription->target
5851 ,glDescription->level
5852 ,destLeft
5854 ,srcWidth
5856 ,glDescription->glFormat
5857 ,glDescription->glType
5858 ,data /* could be quicker using */
5860 data += rowoffset;
5863 } else { /* Full width, so just write out the whole texture */
5865 if (WINED3DFMT_DXT1 == destFormat ||
5866 WINED3DFMT_DXT2 == destFormat ||
5867 WINED3DFMT_DXT3 == destFormat ||
5868 WINED3DFMT_DXT4 == destFormat ||
5869 WINED3DFMT_DXT5 == destFormat) {
5870 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
5871 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
5872 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
5873 FIXME("Updating part of a compressed texture is not supported at the moment\n");
5874 } if (destFormat != srcFormat) {
5875 FIXME("Updating mixed format compressed texture is not curretly support\n");
5876 } else {
5877 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
5878 glDescription->level,
5879 glDescription->glFormatInternal,
5880 srcWidth,
5881 srcHeight,
5883 destSize,
5884 IWineD3DSurface_GetData(pSourceSurface));
5886 } else {
5887 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
5891 } else {
5892 if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
5894 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
5895 to repack the data from pow2Width/Height to expected Width,Height, this makes the
5896 data returned by GetData non-power2 width/height with hardware non-power2
5897 pow2Width/height are set to surface width height, repacking isn't needed so it
5898 doesn't matter which function gets called. */
5899 glTexSubImage2D(glDescription->target
5900 ,glDescription->level
5901 ,destLeft
5902 ,destTop
5903 ,srcWidth
5904 ,srcHeight
5905 ,glDescription->glFormat
5906 ,glDescription->glType
5907 ,IWineD3DSurface_GetData(pSourceSurface)
5909 } else {
5911 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
5912 glTexSubImage2D(glDescription->target
5913 ,glDescription->level
5914 ,destLeft
5915 ,destTop
5916 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
5917 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
5918 ,glDescription->glFormat
5919 ,glDescription->glType
5920 ,IWineD3DSurface_GetData(pSourceSurface)
5926 checkGLcall("glTexSubImage2D");
5928 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
5929 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
5930 * surface bigger than it needs to be hmm.. */
5931 if (WINED3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
5932 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
5933 IWineD3DBaseTexture_Release(baseTexture);
5936 glDisable(textureDimensions); /* This needs to be managed better.... */
5937 LEAVE_GL();
5939 return WINED3D_OK;
5942 /* Used by DirectX 8 */
5943 HRESULT WINAPI IWineD3DDeviceImpl_CopyRects(IWineD3DDevice *iface,
5944 IWineD3DSurface* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
5945 IWineD3DSurface* pDestinationSurface, CONST POINT* pDestPointsArray) {
5947 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5948 HRESULT hr = WINED3D_OK;
5949 WINED3DFORMAT srcFormat, destFormat;
5950 UINT srcWidth, destWidth;
5951 UINT srcHeight, destHeight;
5952 UINT srcSize;
5953 WINED3DSURFACE_DESC winedesc;
5955 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
5956 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
5959 /* Check that the source texture is in WINED3DPOOL_SYSTEMMEM and the destination texture is in WINED3DPOOL_DEFAULT */
5960 memset(&winedesc, 0, sizeof(winedesc));
5962 winedesc.Format = &srcFormat;
5963 winedesc.Width = &srcWidth;
5964 winedesc.Height = &srcHeight;
5965 winedesc.Size = &srcSize;
5966 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5968 winedesc.Format = &destFormat;
5969 winedesc.Width = &destWidth;
5970 winedesc.Height = &destHeight;
5971 winedesc.Size = NULL;
5972 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5974 /* Check that the source and destination formats match */
5975 if (srcFormat != destFormat && WINED3DFMT_UNKNOWN != destFormat) {
5976 WARN("(%p) source %p format must match the dest %p format, returning WINED3DERR_INVALIDCALL\n", This, pSourceSurface, pDestinationSurface);
5977 return WINED3DERR_INVALIDCALL;
5978 } else if (WINED3DFMT_UNKNOWN == destFormat) {
5979 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5980 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5981 destFormat = srcFormat;
5984 /* Quick if complete copy ... */
5985 if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
5987 if (srcWidth == destWidth && srcHeight == destHeight) {
5988 WINED3DLOCKED_RECT lrSrc;
5989 WINED3DLOCKED_RECT lrDst;
5990 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, NULL, WINED3DLOCK_READONLY);
5991 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, NULL, 0L);
5992 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", srcWidth, srcHeight);
5994 memcpy(lrDst.pBits, lrSrc.pBits, srcSize);
5996 IWineD3DSurface_UnlockRect(pSourceSurface);
5997 IWineD3DSurface_UnlockRect(pDestinationSurface);
5998 TRACE("Unlocked src and dst\n");
6000 } else {
6002 FIXME("Wanted to copy all surfaces but size not compatible, returning WINED3DERR_INVALIDCALL\n");
6003 hr = WINED3DERR_INVALIDCALL;
6006 } else {
6008 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
6010 int bytesPerPixel = ((IWineD3DSurfaceImpl *) pSourceSurface)->bytesPerPixel;
6011 unsigned int i;
6013 /* Copy rect by rect */
6014 for (i = 0; i < cRects; ++i) {
6015 CONST RECT* r = &pSourceRectsArray[i];
6016 CONST POINT* p = &pDestPointsArray[i];
6017 int copyperline;
6018 int j;
6019 WINED3DLOCKED_RECT lrSrc;
6020 WINED3DLOCKED_RECT lrDst;
6021 RECT dest_rect;
6023 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
6024 if (srcFormat == WINED3DFMT_DXT1) {
6025 copyperline = ((r->right - r->left) * bytesPerPixel) / 2; /* DXT1 is half byte per pixel */
6026 } else {
6027 copyperline = ((r->right - r->left) * bytesPerPixel);
6030 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, r, WINED3DLOCK_READONLY);
6031 dest_rect.left = p->x;
6032 dest_rect.top = p->y;
6033 dest_rect.right = p->x + (r->right - r->left);
6034 dest_rect.bottom= p->y + (r->bottom - r->top);
6035 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, &dest_rect, 0L);
6036 TRACE("Locked src and dst\n");
6038 /* Find where to start */
6039 for (j = 0; j < (r->bottom - r->top - 1); ++j) {
6040 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
6042 IWineD3DSurface_UnlockRect(pSourceSurface);
6043 IWineD3DSurface_UnlockRect(pDestinationSurface);
6044 TRACE("Unlocked src and dst\n");
6046 } else {
6047 FIXME("Wanted to copy partial surfaces not implemented, returning WINED3DERR_INVALIDCALL\n");
6048 hr = WINED3DERR_INVALIDCALL;
6052 return hr;
6055 /* Implementation details at http://developer.nvidia.com/attach/6494
6057 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
6058 hmm.. no longer supported use
6059 OpenGL evaluators or tessellate surfaces within your application.
6062 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
6063 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
6064 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6065 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
6066 FIXME("(%p) : Stub\n", This);
6067 return WINED3D_OK;
6071 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
6072 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
6073 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6074 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
6075 FIXME("(%p) : Stub\n", This);
6076 return WINED3D_OK;
6079 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
6080 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6081 TRACE("(%p) Handle(%d)\n", This, Handle);
6082 FIXME("(%p) : Stub\n", This);
6083 return WINED3D_OK;
6086 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
6087 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
6088 fill a surface with a block of color! */
6089 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6090 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
6091 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
6092 IWineD3DSwapChainImpl *container = NULL;
6093 BOOL isRenderTarget = FALSE;
6094 unsigned int width, height;
6095 unsigned int top, left;
6096 unsigned int u, v;
6097 DWORD *data;
6098 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
6100 if (surface->resource.pool != WINED3DPOOL_DEFAULT) {
6101 FIXME("call to colorfill with non WINED3DPOOL_DEFAULT surface\n");
6102 return WINED3DERR_INVALIDCALL;
6105 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
6106 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
6107 if (WINED3DUSAGE_RENDERTARGET & surface->resource.usage) {
6108 /* TODO: make sure we set everything back to the way it was, and context management!
6109 glGetIntegerv(GL_READ_BUFFER, &prev_read);
6110 vcheckGLcall("glIntegerv");
6111 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
6112 vcheckGLcall("glIntegerv");
6114 TRACE("Color fill to render targets may cause some graphics issues\n");
6115 if (pSurface == container->frontBuffer) {
6116 glDrawBuffer(GL_FRONT);
6117 } else {
6118 glDrawBuffer(GL_BACK);
6120 } else {
6121 if (WINED3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
6122 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld\n", surface, surface->resource.usage);
6123 } else {
6124 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
6126 if (container != NULL) {
6127 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
6129 /* we can use GL_STENCIL_INDEX etc...*/
6130 return WINED3D_OK;
6132 if (container != NULL) {
6133 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
6135 isRenderTarget = TRUE;
6137 /* TODO: drawing to GL_FRONT and GL_BACK */
6138 /* TODO: see if things can be speeded up by using the correct
6139 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
6140 if (pRect == NULL) {
6141 top = 0;
6142 left = 0;
6143 width = surface->currentDesc.Width;
6144 height = surface->currentDesc.Height;
6145 } else {
6146 left = pRect->x1;
6147 top = pRect->y1;
6148 width = pRect->x2 - left;
6149 height = pRect->y2 - top;
6152 data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
6153 /* Create a 'line' of color color, in the correct format for the surface */
6154 for (u = 0 ; u < width ; u ++) {
6155 data[u] = color;
6158 ENTER_GL();
6159 if (isRenderTarget == FALSE) {
6160 glDescriptor *glDesc;
6161 IWineD3DSurface_PreLoad(pSurface);
6163 /* draw a block of the coloured line on the sufrace */
6164 IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
6165 for (v = 0 ; v< height;v++) {
6166 glTexSubImage2D(glDesc->target
6167 ,glDesc->level /* level */
6168 ,left
6169 ,top + v
6170 ,width
6171 ,1 /* height */
6172 ,GL_RGBA
6173 ,GL_UNSIGNED_BYTE
6174 ,data
6177 checkGLcall("glTexSubImage2D");
6178 /* clean up */
6179 glDisable(glDesc->target);
6180 } else {
6181 /** FIXME: Using GLClear may be faster **/
6182 glRasterPos2i(left, top);
6183 glPixelZoom((float)width ,(float)height);
6184 glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
6185 checkGLcall("glDrawPixels");
6187 HeapFree(GetProcessHeap(), 0, data);
6188 LEAVE_GL();
6189 return WINED3D_OK;
6193 /* rendertarget and deptth stencil functions */
6194 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
6195 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6197 /* FIXME: Implelent RenderTargetIndex >0 */
6198 if(RenderTargetIndex > 0)
6199 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
6201 *ppRenderTarget = This->renderTarget;
6202 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
6203 /* Note inc ref on returned surface */
6204 if(*ppRenderTarget != NULL)
6205 IWineD3DSurface_AddRef(*ppRenderTarget);
6206 return WINED3D_OK;
6209 HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
6210 FIXME("This call is a d3d7 merge stub. It will be implemented later\n");
6211 return WINED3DERR_INVALIDCALL;
6214 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
6215 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6216 *ppZStencilSurface = This->depthStencilBuffer;
6217 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
6219 if(*ppZStencilSurface != NULL) {
6220 /* Note inc ref on returned surface */
6221 IWineD3DSurface_AddRef(*ppZStencilSurface);
6223 return WINED3D_OK;
6226 /* internal static helper functions */
6227 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
6228 IWineD3DSurface *RenderSurface);
6230 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
6231 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6232 HRESULT hr = WINED3D_OK;
6233 WINED3DVIEWPORT viewport;
6235 TRACE("(%p) Swapping rendertarget\n",This);
6236 if (RenderTargetIndex > 0) {
6237 FIXME("(%p) Render targets other than the first are not supported\n",This);
6238 RenderTargetIndex = 0;
6241 /* MSDN says that null disables the render target
6242 but a device must always be associated with a render target
6243 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
6245 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
6246 for more details
6248 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
6249 FIXME("Trying to set render target 0 to NULL\n");
6250 return WINED3DERR_INVALIDCALL;
6252 /* TODO: replace Impl* usage with interface usage */
6253 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
6254 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);
6255 return WINED3DERR_INVALIDCALL;
6257 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
6258 * builds, but I think wine counts as a 'debug' build for now.
6259 ******************************/
6260 /* If we are trying to set what we already have, don't bother */
6261 if (pRenderTarget == This->renderTarget) {
6262 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6263 } else {
6264 /* Otherwise, set the render target up */
6266 if (FALSE == This->sceneEnded) {
6267 IWineD3DDevice_EndScene(iface);
6269 TRACE("clearing renderer\n");
6270 /* IWineD3DDeviceImpl_CleanRender(iface); */
6271 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6272 depending on the renter target implementation being used.
6273 A shared context implementation will share all buffers between all rendertargets (including swapchains),
6274 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6275 stencil buffer and incure an extra memory overhead */
6276 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
6279 if (SUCCEEDED(hr)) {
6280 /* Finally, reset the viewport as the MSDN states. */
6281 /* TODO: Replace impl usage */
6282 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
6283 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
6284 viewport.X = 0;
6285 viewport.Y = 0;
6286 viewport.MaxZ = 1.0f;
6287 viewport.MinZ = 0.0f;
6288 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
6289 } else {
6290 FIXME("Unknown error setting the render target\n");
6292 This->sceneEnded = FALSE;
6293 return hr;
6296 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
6297 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6298 HRESULT hr = WINED3D_OK;
6299 IWineD3DSurface *tmp;
6301 TRACE("(%p) Swapping z-buffer\n",This);
6303 if (pNewZStencil == This->stencilBufferTarget) {
6304 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6305 } else {
6306 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6307 * depending on the renter target implementation being used.
6308 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
6309 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6310 * stencil buffer and incure an extra memory overhead
6311 ******************************************************/
6314 tmp = This->stencilBufferTarget;
6315 This->stencilBufferTarget = pNewZStencil;
6316 /* should we be calling the parent or the wined3d surface? */
6317 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
6318 if (NULL != tmp) IWineD3DSurface_Release(tmp);
6319 hr = WINED3D_OK;
6320 /** TODO: glEnable/glDisable on depth/stencil depending on
6321 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
6322 **********************************************************/
6325 return hr;
6329 #ifdef GL_VERSION_1_3
6330 /* Internal functions not in DirectX */
6331 /** TODO: move this off to the opengl context manager
6332 *(the swapchain doesn't need to know anything about offscreen rendering!)
6333 ****************************************************/
6335 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
6337 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6339 TRACE("(%p), %p\n", This, swapchain);
6341 if (swapchain->win != swapchain->drawable) {
6342 /* Set everything back the way it ws */
6343 swapchain->render_ctx = swapchain->glCtx;
6344 swapchain->drawable = swapchain->win;
6346 return WINED3D_OK;
6349 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
6350 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
6351 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6352 int i;
6353 unsigned int width;
6354 unsigned int height;
6355 WINED3DFORMAT format;
6356 WINED3DSURFACE_DESC surfaceDesc;
6357 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
6358 surfaceDesc.Width = &width;
6359 surfaceDesc.Height = &height;
6360 surfaceDesc.Format = &format;
6361 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
6362 *context = NULL;
6363 /* I need a get width/height function (and should do something with the format) */
6364 for (i = 0; i < CONTEXT_CACHE; ++i) {
6365 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
6366 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
6367 the pSurface can be set to 0 allowing it to be reused from cache **/
6368 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
6369 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
6370 *context = &This->contextCache[i];
6371 break;
6373 if (This->contextCache[i].Width == 0) {
6374 This->contextCache[i].pSurface = pSurface;
6375 This->contextCache[i].Width = width;
6376 This->contextCache[i].Height = height;
6377 *context = &This->contextCache[i];
6378 break;
6381 if (i == CONTEXT_CACHE) {
6382 int minUsage = 0x7FFFFFFF; /* MAX_INT */
6383 glContext *dropContext = 0;
6384 for (i = 0; i < CONTEXT_CACHE; i++) {
6385 if (This->contextCache[i].usedcount < minUsage) {
6386 dropContext = &This->contextCache[i];
6387 minUsage = This->contextCache[i].usedcount;
6390 /* clean up the context (this doesn't work for ATI at the moment */
6391 #if 0
6392 glXDestroyContext(swapchain->display, dropContext->context);
6393 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
6394 #endif
6395 FIXME("Leak\n");
6396 dropContext->Width = 0;
6397 dropContext->pSurface = pSurface;
6398 *context = dropContext;
6399 } else {
6400 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
6401 for (i = 0; i < CONTEXT_CACHE; i++) {
6402 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
6406 if (*context != NULL)
6407 return WINED3D_OK;
6408 else
6409 return E_OUTOFMEMORY;
6411 #endif
6413 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
6414 * the functionality needs splitting up so that we don't do more than we should do.
6415 * this only seems to impact performance a little.
6416 ******************************/
6417 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
6418 IWineD3DSurface *RenderSurface) {
6419 HRESULT ret = WINED3DERR_INVALIDCALL;
6422 * Currently only active for GLX >= 1.3
6423 * for others versions we'll have to use GLXPixmaps
6425 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
6426 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
6427 * so only check OpenGL version
6428 * ..........................
6429 * I don't believe that it is a problem with NVidia headers,
6430 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
6431 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
6432 * ATI Note:
6433 * Your application will report GLX version 1.2 on glXQueryVersion.
6434 * However, it is safe to call the GLX 1.3 functions as described below.
6436 #if defined(GL_VERSION_1_3)
6438 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6439 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
6440 IWineD3DSurface *tmp;
6441 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
6442 GLXFBConfig* cfgs = NULL;
6443 int nCfgs = 0;
6444 int attribs[256];
6445 int nAttribs = 0;
6446 IWineD3DSwapChain *currentSwapchain;
6447 IWineD3DSwapChainImpl *swapchain;
6448 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
6449 * but switch them off if the StencilSurface is set to NULL
6450 ** *********************************************************/
6451 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
6452 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
6454 /**TODO:
6455 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
6456 it StencilSurface != NULL && zBufferTarget == NULL switch it on
6459 #define PUSH1(att) attribs[nAttribs++] = (att);
6460 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
6462 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
6464 /** TODO: remove the reff to Impl (context manager should fix this!) **/
6465 IWineD3DSwapChainImpl *impSwapChain;
6466 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
6467 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
6468 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
6471 ENTER_GL();
6473 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
6474 PUSH2(GLX_X_RENDERABLE, TRUE);
6475 PUSH2(GLX_DOUBLEBUFFER, TRUE);
6476 TRACE("calling makeglcfg\n");
6477 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
6478 PUSH1(None);
6480 TRACE("calling chooseFGConfig\n");
6481 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
6482 attribs, &nCfgs);
6484 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
6485 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
6486 why we failed and only show this message once! */
6487 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"); /**/
6488 nAttribs = 0;
6489 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
6490 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
6491 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
6492 PUSH2(GLX_DOUBLEBUFFER, FALSE);
6493 TRACE("calling makeglcfg\n");
6494 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
6495 PUSH1(None);
6496 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
6497 attribs, &nCfgs);
6500 if (NULL != cfgs) {
6501 #ifdef EXTRA_TRACES
6502 int i;
6503 for (i = 0; i < nCfgs; ++i) {
6504 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
6505 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
6506 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
6509 if (NULL != This->renderTarget) {
6510 glFlush();
6511 vcheckGLcall("glFlush");
6512 /** This is only useful if the old render target was a swapchain,
6513 * we need to supercede this with a function that displays
6514 * the current buffer on the screen. This is easy to do in glx1.3 but
6515 * we need to do copy-write pixels in glx 1.2.
6516 ************************************************/
6517 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
6519 printf("Hit Enter to get next frame ...\n");
6520 getchar();
6522 #endif
6525 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&currentSwapchain) != WINED3D_OK) {
6526 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
6527 IWineD3DDevice_GetSwapChain(iface, 0, &currentSwapchain);
6531 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
6532 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
6533 **********************************************************************/
6534 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == WINED3D_OK) {
6535 /* We also need to make sure that the lights &co are also in the context of the swapchains */
6536 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
6537 TRACE("making swapchain active\n");
6538 if (RenderSurface != This->renderTarget) {
6539 if (RenderSurface == swapchain->backBuffer) {
6540 } else {
6541 /* This could be flagged so that some operations work directly with the front buffer */
6542 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
6544 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
6545 == False) {
6546 TRACE("Error in setting current context: context %p drawable %ld !\n",
6547 impSwapChain->glCtx, impSwapChain->win);
6550 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
6552 checkGLcall("glXMakeContextCurrent");
6554 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
6556 else if (pbuffer_support == TRUE && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
6558 /** ********************************************************************
6559 * This is a quickly hacked out implementation of offscreen textures.
6560 * It will work in most cases but there may be problems if the client
6561 * modifies the texture directly, or expects the contents of the rendertarget
6562 * to be persistent.
6564 * There are some real speed vs compatibility issues here:
6565 * we should really use a new context for every texture, but that eats ram.
6566 * we should also be restoring the texture to the pbuffer but that eats CPU
6567 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
6568 * but if this means reusing the display backbuffer then we need to make sure that
6569 * states are correctly preserved.
6570 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
6571 * and gain a good performance increase at the cost of compatibility.
6572 * I would suggest that, when this is the case, a user configurable flag be made
6573 * available, allowing the user to choose the best emulated experience for them.
6574 *********************************************************************/
6576 XVisualInfo *visinfo;
6577 glContext *newContext;
6579 /* Here were using a shared context model */
6580 if (WINED3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
6581 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6584 /* If the context doesn't exist then create a new one */
6585 /* TODO: This should really be part of findGlContext */
6586 if (NULL == newContext->context) {
6588 TRACE("making new buffer\n");
6589 nAttribs = 0;
6590 PUSH2(GLX_PBUFFER_WIDTH, newContext->Width);
6591 PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
6592 PUSH1(None);
6594 newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
6596 /** ****************************************
6597 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
6598 *they note:
6599 * In future releases, we may provide the calls glXCreateNewContext,
6600 * glXQueryDrawable and glXMakeContextCurrent.
6601 * so until then we have to use glXGetVisualFromFBConfig &co..
6602 ********************************************/
6605 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
6606 if (!visinfo) {
6607 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
6608 } else {
6609 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
6610 XFree(visinfo);
6613 if (NULL == newContext || NULL == newContext->context) {
6614 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6615 } else {
6616 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
6617 if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
6618 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
6621 /* Clean up the old context */
6622 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
6623 /* Set the current context of the swapchain to the new context */
6624 impSwapChain->drawable = newContext->drawable;
6625 impSwapChain->render_ctx = newContext->context;
6629 #if 1 /* Apply the stateblock to the new context
6630 FIXME: This is a bit of a hack, each context should know it's own state,
6631 the directX current directX state should then be applied to the context */
6633 BOOL oldRecording;
6634 IWineD3DStateBlockImpl *oldUpdateStateBlock;
6635 oldUpdateStateBlock = This->updateStateBlock;
6636 oldRecording= This->isRecordingState;
6637 This->isRecordingState = FALSE;
6638 This->updateStateBlock = This->stateBlock;
6639 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
6641 This->isRecordingState = oldRecording;
6642 This->updateStateBlock = oldUpdateStateBlock;
6644 #endif
6647 /* clean up the current rendertargets swapchain (if it belonged to one) */
6648 if (currentSwapchain != NULL) {
6649 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
6652 /* Were done with the opengl context management, setup the rendertargets */
6654 tmp = This->renderTarget;
6655 This->renderTarget = RenderSurface;
6656 IWineD3DSurface_AddRef(This->renderTarget);
6657 IWineD3DSurface_Release(tmp);
6662 DWORD value;
6663 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
6664 /* Check that the container is not a swapchain member */
6666 IWineD3DSwapChain *tmpSwapChain;
6667 if (WINED3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
6668 This->renderUpsideDown = TRUE;
6669 }else{
6670 This->renderUpsideDown = FALSE;
6671 IWineD3DSwapChain_Release(tmpSwapChain);
6673 /* Force updating the cull mode */
6674 TRACE("setting render state\n");
6675 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
6676 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
6678 /* Force updating projection matrix */
6679 This->last_was_rhw = FALSE;
6680 This->proj_valid = FALSE;
6683 ret = WINED3D_OK;
6685 if (cfgs != NULL) {
6686 XFree(cfgs);
6687 } else {
6688 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
6689 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
6692 #undef PUSH1
6693 #undef PUSH2
6694 if ( NULL != impSwapChain) {
6695 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
6697 LEAVE_GL();
6699 #endif
6700 return ret;
6703 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
6704 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
6705 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6706 /* TODO: the use of Impl is deprecated. */
6707 /* some basic validation checks */
6708 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
6710 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
6712 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
6713 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
6714 return WINED3DERR_INVALIDCALL;
6716 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
6717 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
6718 return WINED3DERR_INVALIDCALL;
6720 /* TODO: make the cursor 'real' */
6722 This->xHotSpot = XHotSpot;
6723 This->yHotSpot = YHotSpot;
6725 return WINED3D_OK;
6728 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
6729 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6730 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
6732 This->xScreenSpace = XScreenSpace;
6733 This->yScreenSpace = YScreenSpace;
6735 return;
6739 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
6740 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6741 TRACE("(%p) : visible(%d)\n", This, bShow);
6743 This->bCursorVisible = bShow;
6745 return WINED3D_OK;
6748 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
6749 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6750 TRACE("(%p) : state (%lu)\n", This, This->state);
6751 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
6752 switch (This->state) {
6753 case WINED3D_OK:
6754 return WINED3D_OK;
6755 case WINED3DERR_DEVICELOST:
6757 ResourceList *resourceList = This->resources;
6758 while (NULL != resourceList) {
6759 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
6760 return WINED3DERR_DEVICENOTRESET;
6761 resourceList = resourceList->next;
6763 return WINED3DERR_DEVICELOST;
6765 case WINED3DERR_DRIVERINTERNALERROR:
6766 return WINED3DERR_DRIVERINTERNALERROR;
6769 /* Unknown state */
6770 return WINED3DERR_DRIVERINTERNALERROR;
6774 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
6775 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6776 /** FIXME: Resource tracking needs to be done,
6777 * The closes we can do to this is set the priorities of all managed textures low
6778 * and then reset them.
6779 ***********************************************************/
6780 FIXME("(%p) : stub\n", This);
6781 return WINED3D_OK;
6784 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
6785 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6786 /** FIXME: Resource trascking needs to be done.
6787 * in effect this pulls all non only default
6788 * textures out of video memory and deletes all glTextures (glDeleteTextures)
6789 * and should clear down the context and set it up according to pPresentationParameters
6790 ***********************************************************/
6791 FIXME("(%p) : stub\n", This);
6792 return WINED3D_OK;
6795 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
6796 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6797 /** FIXME: always true at the moment **/
6798 if(bEnableDialogs == FALSE) {
6799 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
6801 return WINED3D_OK;
6805 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
6806 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6807 TRACE("(%p) : pParameters %p\n", This, pParameters);
6809 *pParameters = This->createParms;
6810 return WINED3D_OK;
6813 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
6814 IWineD3DSwapChain *swapchain;
6815 HRESULT hrc = WINED3D_OK;
6817 TRACE("Relaying to swapchain\n");
6819 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
6820 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
6821 IWineD3DSwapChain_Release(swapchain);
6823 return;
6826 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
6827 IWineD3DSwapChain *swapchain;
6828 HRESULT hrc = WINED3D_OK;
6830 TRACE("Relaying to swapchain\n");
6832 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
6833 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
6834 IWineD3DSwapChain_Release(swapchain);
6836 return;
6840 /** ********************************************************
6841 * Notification functions
6842 ** ********************************************************/
6843 /** This function must be called in the release of a resource when ref == 0,
6844 * the contents of resource must still be correct,
6845 * any handels to other resource held by the caller must be closed
6846 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
6847 *****************************************************/
6848 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6849 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6850 ResourceList* resourceList;
6852 TRACE("(%p) : resource %p\n", This, resource);
6853 #if 0
6854 EnterCriticalSection(&resourceStoreCriticalSection);
6855 #endif
6856 /* add a new texture to the frot of the linked list */
6857 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
6858 resourceList->resource = resource;
6860 /* Get the old head */
6861 resourceList->next = This->resources;
6863 This->resources = resourceList;
6864 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
6866 #if 0
6867 LeaveCriticalSection(&resourceStoreCriticalSection);
6868 #endif
6869 return;
6872 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6873 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6874 ResourceList* resourceList = NULL;
6875 ResourceList* previousResourceList = NULL;
6877 TRACE("(%p) : resource %p\n", This, resource);
6879 #if 0
6880 EnterCriticalSection(&resourceStoreCriticalSection);
6881 #endif
6882 resourceList = This->resources;
6884 while (resourceList != NULL) {
6885 if(resourceList->resource == resource) break;
6886 previousResourceList = resourceList;
6887 resourceList = resourceList->next;
6890 if (resourceList == NULL) {
6891 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
6892 #if 0
6893 LeaveCriticalSection(&resourceStoreCriticalSection);
6894 #endif
6895 return;
6896 } else {
6897 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
6899 /* make sure we don't leave a hole in the list */
6900 if (previousResourceList != NULL) {
6901 previousResourceList->next = resourceList->next;
6902 } else {
6903 This->resources = resourceList->next;
6906 #if 0
6907 LeaveCriticalSection(&resourceStoreCriticalSection);
6908 #endif
6909 return;
6913 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
6914 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6915 int counter;
6917 TRACE("(%p) : resource %p\n", This, resource);
6918 switch(IWineD3DResource_GetType(resource)){
6919 case WINED3DRTYPE_SURFACE:
6920 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
6921 break;
6922 case WINED3DRTYPE_TEXTURE:
6923 case WINED3DRTYPE_CUBETEXTURE:
6924 case WINED3DRTYPE_VOLUMETEXTURE:
6925 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
6926 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6927 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6928 This->stateBlock->textures[counter] = NULL;
6930 if (This->updateStateBlock != This->stateBlock ){
6931 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6932 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6933 This->updateStateBlock->textures[counter] = NULL;
6937 break;
6938 case WINED3DRTYPE_VOLUME:
6939 /* TODO: nothing really? */
6940 break;
6941 case WINED3DRTYPE_VERTEXBUFFER:
6942 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
6944 int streamNumber;
6945 TRACE("Cleaning up stream pointers\n");
6947 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
6948 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
6949 FINDOUT: should changes.streamSource[StreamNumber] be set ?
6951 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6952 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
6953 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
6954 This->updateStateBlock->streamSource[streamNumber] = 0;
6955 /* Set changed flag? */
6958 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) */
6959 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
6960 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
6961 This->stateBlock->streamSource[streamNumber] = 0;
6964 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
6965 else { /* This shouldn't happen */
6966 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
6968 #endif
6972 break;
6973 case WINED3DRTYPE_INDEXBUFFER:
6974 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
6975 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6976 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6977 This->updateStateBlock->pIndexData = NULL;
6980 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
6981 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6982 This->stateBlock->pIndexData = NULL;
6986 break;
6987 default:
6988 FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
6989 break;
6993 /* Remove the resoruce from the resourceStore */
6994 IWineD3DDeviceImpl_RemoveResource(iface, resource);
6996 TRACE("Resource released\n");
7001 /** This function is to be called by the swapchain when it is released and it's ref = 0
7002 *****************************************************/
7003 void WINAPI IWineD3DDeviceImpl_SwapChainReleased(IWineD3DDevice *iface, IWineD3DSwapChain *swapChain){
7004 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7005 SwapChainList **nextSwapchain;
7006 nextSwapchain = &This->swapchains;
7008 /* Check to see if the swapchian is being used as the render target */
7009 if (This->renderTarget != NULL) {
7010 IWineD3DSurface *swapchainBackBuffer;
7012 IWineD3DSwapChain_GetBackBuffer(swapChain, 0 ,( D3DBACKBUFFER_TYPE) 0, &swapchainBackBuffer);
7013 if (This->renderTarget == swapchainBackBuffer) {
7014 /* Don't know what to do, so warn and carry on as usual (which in this case leaves the renderterget in limbo) */
7015 FIXME("Atempting to release a swapchain that is currently beuing used as a render target, behaviour is undefined\n");
7019 /* Go through the swapchain list and try to find the swapchain being released */
7020 while(*nextSwapchain != NULL && (*nextSwapchain)->swapchain != swapChain) {
7021 nextSwapchain = &(*nextSwapchain)->next;
7024 /* Check to see if we found the swapchain */
7025 if (NULL != *nextSwapchain) {
7026 /* We found the swapchain so remove it from the list */
7027 TRACE("(%p) releasing swapchain(%p)\n", iface, swapChain);
7028 HeapFree(GetProcessHeap(), 0 , *nextSwapchain);
7029 *nextSwapchain = (*nextSwapchain)->next;
7030 } else {
7031 /* We didn't find the swapchain on the list, this can only heppen because of a programming error in wined3d */
7032 FIXME("(%p) Attempting to release a swapchain (%p) that hasn't been stored\n", iface, swapChain);
7035 TRACE("swapchain (%p) released\n", swapChain);
7036 return;
7039 /**********************************************************
7040 * IWineD3DDevice VTbl follows
7041 **********************************************************/
7043 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
7045 /*** IUnknown methods ***/
7046 IWineD3DDeviceImpl_QueryInterface,
7047 IWineD3DDeviceImpl_AddRef,
7048 IWineD3DDeviceImpl_Release,
7049 /*** IWineD3DDevice methods ***/
7050 IWineD3DDeviceImpl_GetParent,
7051 /*** Creation methods**/
7052 IWineD3DDeviceImpl_CreateVertexBuffer,
7053 IWineD3DDeviceImpl_CreateIndexBuffer,
7054 IWineD3DDeviceImpl_CreateStateBlock,
7055 IWineD3DDeviceImpl_CreateSurface,
7056 IWineD3DDeviceImpl_CreateTexture,
7057 IWineD3DDeviceImpl_CreateVolumeTexture,
7058 IWineD3DDeviceImpl_CreateVolume,
7059 IWineD3DDeviceImpl_CreateCubeTexture,
7060 IWineD3DDeviceImpl_CreateQuery,
7061 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
7062 IWineD3DDeviceImpl_CreateVertexDeclaration,
7063 IWineD3DDeviceImpl_CreateVertexShader,
7064 IWineD3DDeviceImpl_CreatePixelShader,
7065 IWineD3DDeviceImpl_CreatePalette,
7066 /*** Odd functions **/
7067 IWineD3DDeviceImpl_Init3D,
7068 IWineD3DDeviceImpl_Uninit3D,
7069 IWineD3DDeviceImpl_EnumDisplayModes,
7070 IWineD3DDeviceImpl_EvictManagedResources,
7071 IWineD3DDeviceImpl_GetAvailableTextureMem,
7072 IWineD3DDeviceImpl_GetBackBuffer,
7073 IWineD3DDeviceImpl_GetCreationParameters,
7074 IWineD3DDeviceImpl_GetDeviceCaps,
7075 IWineD3DDeviceImpl_GetDirect3D,
7076 IWineD3DDeviceImpl_GetDisplayMode,
7077 IWineD3DDeviceImpl_SetDisplayMode,
7078 IWineD3DDeviceImpl_GetHWND,
7079 IWineD3DDeviceImpl_SetHWND,
7080 IWineD3DDeviceImpl_GetNumberOfSwapChains,
7081 IWineD3DDeviceImpl_GetRasterStatus,
7082 IWineD3DDeviceImpl_GetSwapChain,
7083 IWineD3DDeviceImpl_Reset,
7084 IWineD3DDeviceImpl_SetDialogBoxMode,
7085 IWineD3DDeviceImpl_SetCursorProperties,
7086 IWineD3DDeviceImpl_SetCursorPosition,
7087 IWineD3DDeviceImpl_ShowCursor,
7088 IWineD3DDeviceImpl_TestCooperativeLevel,
7089 IWineD3DDeviceImpl_EnumZBufferFormats,
7090 IWineD3DDeviceImpl_EnumTextureFormats,
7091 /*** Getters and setters **/
7092 IWineD3DDeviceImpl_SetClipPlane,
7093 IWineD3DDeviceImpl_GetClipPlane,
7094 IWineD3DDeviceImpl_SetClipStatus,
7095 IWineD3DDeviceImpl_GetClipStatus,
7096 IWineD3DDeviceImpl_SetCurrentTexturePalette,
7097 IWineD3DDeviceImpl_GetCurrentTexturePalette,
7098 IWineD3DDeviceImpl_SetDepthStencilSurface,
7099 IWineD3DDeviceImpl_GetDepthStencilSurface,
7100 IWineD3DDeviceImpl_SetFVF,
7101 IWineD3DDeviceImpl_GetFVF,
7102 IWineD3DDeviceImpl_SetGammaRamp,
7103 IWineD3DDeviceImpl_GetGammaRamp,
7104 IWineD3DDeviceImpl_SetIndices,
7105 IWineD3DDeviceImpl_GetIndices,
7106 IWineD3DDeviceImpl_SetLight,
7107 IWineD3DDeviceImpl_GetLight,
7108 IWineD3DDeviceImpl_SetLightEnable,
7109 IWineD3DDeviceImpl_GetLightEnable,
7110 IWineD3DDeviceImpl_SetMaterial,
7111 IWineD3DDeviceImpl_GetMaterial,
7112 IWineD3DDeviceImpl_SetNPatchMode,
7113 IWineD3DDeviceImpl_GetNPatchMode,
7114 IWineD3DDeviceImpl_SetPaletteEntries,
7115 IWineD3DDeviceImpl_GetPaletteEntries,
7116 IWineD3DDeviceImpl_SetPixelShader,
7117 IWineD3DDeviceImpl_GetPixelShader,
7118 IWineD3DDeviceImpl_SetPixelShaderConstant,
7119 IWineD3DDeviceImpl_GetPixelShaderConstant,
7120 IWineD3DDeviceImpl_SetPixelShaderConstantB,
7121 IWineD3DDeviceImpl_GetPixelShaderConstantB,
7122 IWineD3DDeviceImpl_SetPixelShaderConstantI,
7123 IWineD3DDeviceImpl_GetPixelShaderConstantI,
7124 IWineD3DDeviceImpl_SetPixelShaderConstantF,
7125 IWineD3DDeviceImpl_GetPixelShaderConstantF,
7126 IWineD3DDeviceImpl_SetPixelShaderConstantN,
7127 IWineD3DDeviceImpl_SetRenderState,
7128 IWineD3DDeviceImpl_GetRenderState,
7129 IWineD3DDeviceImpl_SetRenderTarget,
7130 IWineD3DDeviceImpl_GetRenderTarget,
7131 IWineD3DDeviceImpl_SetFrontBackBuffers,
7132 IWineD3DDeviceImpl_SetSamplerState,
7133 IWineD3DDeviceImpl_GetSamplerState,
7134 IWineD3DDeviceImpl_SetScissorRect,
7135 IWineD3DDeviceImpl_GetScissorRect,
7136 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
7137 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
7138 IWineD3DDeviceImpl_SetStreamSource,
7139 IWineD3DDeviceImpl_GetStreamSource,
7140 IWineD3DDeviceImpl_SetStreamSourceFreq,
7141 IWineD3DDeviceImpl_GetStreamSourceFreq,
7142 IWineD3DDeviceImpl_SetTexture,
7143 IWineD3DDeviceImpl_GetTexture,
7144 IWineD3DDeviceImpl_SetTextureStageState,
7145 IWineD3DDeviceImpl_GetTextureStageState,
7146 IWineD3DDeviceImpl_SetTransform,
7147 IWineD3DDeviceImpl_GetTransform,
7148 IWineD3DDeviceImpl_SetVertexDeclaration,
7149 IWineD3DDeviceImpl_GetVertexDeclaration,
7150 IWineD3DDeviceImpl_SetVertexShader,
7151 IWineD3DDeviceImpl_GetVertexShader,
7152 IWineD3DDeviceImpl_SetVertexShaderConstant,
7153 IWineD3DDeviceImpl_GetVertexShaderConstant,
7154 IWineD3DDeviceImpl_SetVertexShaderConstantB,
7155 IWineD3DDeviceImpl_GetVertexShaderConstantB,
7156 IWineD3DDeviceImpl_SetVertexShaderConstantI,
7157 IWineD3DDeviceImpl_GetVertexShaderConstantI,
7158 IWineD3DDeviceImpl_SetVertexShaderConstantF,
7159 IWineD3DDeviceImpl_GetVertexShaderConstantF,
7160 IWineD3DDeviceImpl_SetVertexShaderConstantN,
7161 IWineD3DDeviceImpl_SetViewport,
7162 IWineD3DDeviceImpl_GetViewport,
7163 IWineD3DDeviceImpl_MultiplyTransform,
7164 IWineD3DDeviceImpl_ValidateDevice,
7165 IWineD3DDeviceImpl_ProcessVertices,
7166 /*** State block ***/
7167 IWineD3DDeviceImpl_BeginStateBlock,
7168 IWineD3DDeviceImpl_EndStateBlock,
7169 /*** Scene management ***/
7170 IWineD3DDeviceImpl_BeginScene,
7171 IWineD3DDeviceImpl_EndScene,
7172 IWineD3DDeviceImpl_Present,
7173 IWineD3DDeviceImpl_Clear,
7174 /*** Drawing ***/
7175 IWineD3DDeviceImpl_DrawPrimitive,
7176 IWineD3DDeviceImpl_DrawIndexedPrimitive,
7177 IWineD3DDeviceImpl_DrawPrimitiveUP,
7178 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
7179 IWineD3DDeviceImpl_DrawRectPatch,
7180 IWineD3DDeviceImpl_DrawTriPatch,
7181 IWineD3DDeviceImpl_DeletePatch,
7182 IWineD3DDeviceImpl_ColorFill,
7183 IWineD3DDeviceImpl_UpdateTexture,
7184 IWineD3DDeviceImpl_UpdateSurface,
7185 IWineD3DDeviceImpl_CopyRects,
7186 IWineD3DDeviceImpl_StretchRect,
7187 IWineD3DDeviceImpl_GetRenderTargetData,
7188 IWineD3DDeviceImpl_GetFrontBufferData,
7189 /*** Internal use IWineD3DDevice methods ***/
7190 IWineD3DDeviceImpl_SetupTextureStates,
7191 /*** object tracking ***/
7192 IWineD3DDeviceImpl_SwapChainReleased,
7193 IWineD3DDeviceImpl_ResourceReleased
7197 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
7198 WINED3DRS_ALPHABLENDENABLE ,
7199 WINED3DRS_ALPHAFUNC ,
7200 WINED3DRS_ALPHAREF ,
7201 WINED3DRS_ALPHATESTENABLE ,
7202 WINED3DRS_BLENDOP ,
7203 WINED3DRS_COLORWRITEENABLE ,
7204 WINED3DRS_DESTBLEND ,
7205 WINED3DRS_DITHERENABLE ,
7206 WINED3DRS_FILLMODE ,
7207 WINED3DRS_FOGDENSITY ,
7208 WINED3DRS_FOGEND ,
7209 WINED3DRS_FOGSTART ,
7210 WINED3DRS_LASTPIXEL ,
7211 WINED3DRS_SHADEMODE ,
7212 WINED3DRS_SRCBLEND ,
7213 WINED3DRS_STENCILENABLE ,
7214 WINED3DRS_STENCILFAIL ,
7215 WINED3DRS_STENCILFUNC ,
7216 WINED3DRS_STENCILMASK ,
7217 WINED3DRS_STENCILPASS ,
7218 WINED3DRS_STENCILREF ,
7219 WINED3DRS_STENCILWRITEMASK ,
7220 WINED3DRS_STENCILZFAIL ,
7221 WINED3DRS_TEXTUREFACTOR ,
7222 WINED3DRS_WRAP0 ,
7223 WINED3DRS_WRAP1 ,
7224 WINED3DRS_WRAP2 ,
7225 WINED3DRS_WRAP3 ,
7226 WINED3DRS_WRAP4 ,
7227 WINED3DRS_WRAP5 ,
7228 WINED3DRS_WRAP6 ,
7229 WINED3DRS_WRAP7 ,
7230 WINED3DRS_ZENABLE ,
7231 WINED3DRS_ZFUNC ,
7232 WINED3DRS_ZWRITEENABLE
7235 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
7236 WINED3DTSS_ADDRESSW ,
7237 WINED3DTSS_ALPHAARG0 ,
7238 WINED3DTSS_ALPHAARG1 ,
7239 WINED3DTSS_ALPHAARG2 ,
7240 WINED3DTSS_ALPHAOP ,
7241 WINED3DTSS_BUMPENVLOFFSET ,
7242 WINED3DTSS_BUMPENVLSCALE ,
7243 WINED3DTSS_BUMPENVMAT00 ,
7244 WINED3DTSS_BUMPENVMAT01 ,
7245 WINED3DTSS_BUMPENVMAT10 ,
7246 WINED3DTSS_BUMPENVMAT11 ,
7247 WINED3DTSS_COLORARG0 ,
7248 WINED3DTSS_COLORARG1 ,
7249 WINED3DTSS_COLORARG2 ,
7250 WINED3DTSS_COLOROP ,
7251 WINED3DTSS_RESULTARG ,
7252 WINED3DTSS_TEXCOORDINDEX ,
7253 WINED3DTSS_TEXTURETRANSFORMFLAGS
7256 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
7257 WINED3DSAMP_ADDRESSU ,
7258 WINED3DSAMP_ADDRESSV ,
7259 WINED3DSAMP_ADDRESSW ,
7260 WINED3DSAMP_BORDERCOLOR ,
7261 WINED3DSAMP_MAGFILTER ,
7262 WINED3DSAMP_MINFILTER ,
7263 WINED3DSAMP_MIPFILTER ,
7264 WINED3DSAMP_MIPMAPLODBIAS ,
7265 WINED3DSAMP_MAXMIPLEVEL ,
7266 WINED3DSAMP_MAXANISOTROPY ,
7267 WINED3DSAMP_SRGBTEXTURE ,
7268 WINED3DSAMP_ELEMENTINDEX
7271 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
7272 WINED3DRS_AMBIENT ,
7273 WINED3DRS_AMBIENTMATERIALSOURCE ,
7274 WINED3DRS_CLIPPING ,
7275 WINED3DRS_CLIPPLANEENABLE ,
7276 WINED3DRS_COLORVERTEX ,
7277 WINED3DRS_DIFFUSEMATERIALSOURCE ,
7278 WINED3DRS_EMISSIVEMATERIALSOURCE ,
7279 WINED3DRS_FOGDENSITY ,
7280 WINED3DRS_FOGEND ,
7281 WINED3DRS_FOGSTART ,
7282 WINED3DRS_FOGTABLEMODE ,
7283 WINED3DRS_FOGVERTEXMODE ,
7284 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
7285 WINED3DRS_LIGHTING ,
7286 WINED3DRS_LOCALVIEWER ,
7287 WINED3DRS_MULTISAMPLEANTIALIAS ,
7288 WINED3DRS_MULTISAMPLEMASK ,
7289 WINED3DRS_NORMALIZENORMALS ,
7290 WINED3DRS_PATCHEDGESTYLE ,
7291 WINED3DRS_POINTSCALE_A ,
7292 WINED3DRS_POINTSCALE_B ,
7293 WINED3DRS_POINTSCALE_C ,
7294 WINED3DRS_POINTSCALEENABLE ,
7295 WINED3DRS_POINTSIZE ,
7296 WINED3DRS_POINTSIZE_MAX ,
7297 WINED3DRS_POINTSIZE_MIN ,
7298 WINED3DRS_POINTSPRITEENABLE ,
7299 WINED3DRS_RANGEFOGENABLE ,
7300 WINED3DRS_SPECULARMATERIALSOURCE ,
7301 WINED3DRS_TWEENFACTOR ,
7302 WINED3DRS_VERTEXBLEND
7305 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
7306 WINED3DTSS_TEXCOORDINDEX ,
7307 WINED3DTSS_TEXTURETRANSFORMFLAGS
7310 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
7311 WINED3DSAMP_DMAPOFFSET