wined3d: Implement IWineD3DDevice::SetFrontBackBuffers.
[wine/multimedia.git] / dlls / wined3d / device.c
blob943e38f7fa9289604881ac31d9509417e9c76531
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);
765 /* Store the DirectDraw primary surface. This is the first rendertarget surface created */
766 if( (Usage & WINED3DUSAGE_RENDERTARGET) && (!This->ddraw_primary) )
767 This->ddraw_primary = (IWineD3DSurface *) object;
769 /* Look at the implementation and set the correct Vtable */
770 switch(Impl) {
771 case SURFACE_OPENGL:
772 /* Nothing to do, it's set already */
773 break;
775 case SURFACE_GDI:
776 object->lpVtbl = &IWineGDISurface_Vtbl;
777 break;
779 default:
780 /* To be sure to catch this */
781 ERR("Unknown requested surface implementation %d!\n", Impl);
782 IWineD3DSurface_Release((IWineD3DSurface *) object);
783 return WINED3DERR_INVALIDCALL;
786 /* Call the private setup routine */
787 return IWineD3DSurface_PrivateSetup( (IWineD3DSurface *) object );
791 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
792 DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
793 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
794 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
796 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
797 IWineD3DTextureImpl *object;
798 unsigned int i;
799 UINT tmpW;
800 UINT tmpH;
801 HRESULT hr;
802 unsigned int pow2Width = Width;
803 unsigned int pow2Height = Height;
806 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) ....\n", This, Width, Height, Levels, Usage);
808 /* TODO: It should only be possible to create textures for formats
809 that are reported as supported */
810 if (WINED3DFMT_UNKNOWN >= Format) {
811 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
812 return WINED3DERR_INVALIDCALL;
815 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, WINED3DRTYPE_TEXTURE, 0);
816 D3DINITIALIZEBASETEXTURE(object->baseTexture);
817 object->width = Width;
818 object->height = Height;
820 /** Non-power2 support **/
821 /* Find the nearest pow2 match */
822 pow2Width = pow2Height = 1;
823 while (pow2Width < Width) pow2Width <<= 1;
824 while (pow2Height < Height) pow2Height <<= 1;
826 /** FIXME: add support for real non-power-two if it's provided by the video card **/
827 /* Precalculated scaling for 'faked' non power of two texture coords */
828 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
829 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
830 TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
832 /* Calculate levels for mip mapping */
833 if (Levels == 0) {
834 TRACE("calculating levels %d\n", object->baseTexture.levels);
835 object->baseTexture.levels++;
836 tmpW = Width;
837 tmpH = Height;
838 while (tmpW > 1 || tmpH > 1) {
839 tmpW = max(1, tmpW >> 1);
840 tmpH = max(1, tmpH >> 1);
841 object->baseTexture.levels++;
843 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
846 /* Generate all the surfaces */
847 tmpW = Width;
848 tmpH = Height;
849 for (i = 0; i < object->baseTexture.levels; i++)
851 /* use the callback to create the texture surface */
852 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
853 if (hr!= WINED3D_OK) {
854 int j;
855 FIXME("Failed to create surface %p\n", object);
856 /* clean up */
857 for (j = 0 ; j < i ; j++) {
858 IWineD3DSurface_Release(object->surfaces[j]);
860 /* heap free object */
861 HeapFree(GetProcessHeap(), 0, object);
863 *ppTexture = NULL;
864 return hr;
867 IWineD3DSurface_SetContainer(object->surfaces[i], (IWineD3DBase *)object);
868 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
869 /* calculate the next mipmap level */
870 tmpW = max(1, tmpW >> 1);
871 tmpH = max(1, tmpH >> 1);
874 TRACE("(%p) : Created texture %p\n", This, object);
875 return WINED3D_OK;
878 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
879 UINT Width, UINT Height, UINT Depth,
880 UINT Levels, DWORD Usage,
881 WINED3DFORMAT Format, WINED3DPOOL Pool,
882 IWineD3DVolumeTexture **ppVolumeTexture,
883 HANDLE *pSharedHandle, IUnknown *parent,
884 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
886 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
887 IWineD3DVolumeTextureImpl *object;
888 unsigned int i;
889 UINT tmpW;
890 UINT tmpH;
891 UINT tmpD;
893 /* TODO: It should only be possible to create textures for formats
894 that are reported as supported */
895 if (WINED3DFMT_UNKNOWN >= Format) {
896 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
897 return WINED3DERR_INVALIDCALL;
900 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, WINED3DRTYPE_VOLUMETEXTURE, 0);
901 D3DINITIALIZEBASETEXTURE(object->baseTexture);
903 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
904 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
906 object->width = Width;
907 object->height = Height;
908 object->depth = Depth;
910 /* Calculate levels for mip mapping */
911 if (Levels == 0) {
912 object->baseTexture.levels++;
913 tmpW = Width;
914 tmpH = Height;
915 tmpD = Depth;
916 while (tmpW > 1 || tmpH > 1 || tmpD > 1) {
917 tmpW = max(1, tmpW >> 1);
918 tmpH = max(1, tmpH >> 1);
919 tmpD = max(1, tmpD >> 1);
920 object->baseTexture.levels++;
922 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
925 /* Generate all the surfaces */
926 tmpW = Width;
927 tmpH = Height;
928 tmpD = Depth;
930 for (i = 0; i < object->baseTexture.levels; i++)
932 /* Create the volume */
933 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
934 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
936 /* Set it's container to this object */
937 IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)object);
939 /* calcualte the next mipmap level */
940 tmpW = max(1, tmpW >> 1);
941 tmpH = max(1, tmpH >> 1);
942 tmpD = max(1, tmpD >> 1);
945 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
946 TRACE("(%p) : Created volume texture %p\n", This, object);
947 return WINED3D_OK;
950 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
951 UINT Width, UINT Height, UINT Depth,
952 DWORD Usage,
953 WINED3DFORMAT Format, WINED3DPOOL Pool,
954 IWineD3DVolume** ppVolume,
955 HANDLE* pSharedHandle, IUnknown *parent) {
957 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
958 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
960 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, WINED3DRTYPE_VOLUME, ((Width * D3DFmtGetBpp(This, Format)) * Height * Depth))
962 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
963 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
965 object->currentDesc.Width = Width;
966 object->currentDesc.Height = Height;
967 object->currentDesc.Depth = Depth;
968 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
970 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
971 object->lockable = TRUE;
972 object->locked = FALSE;
973 memset(&object->lockedBox, 0, sizeof(WINED3DBOX));
974 object->dirty = TRUE;
976 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
979 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
980 UINT Levels, DWORD Usage,
981 WINED3DFORMAT Format, WINED3DPOOL Pool,
982 IWineD3DCubeTexture **ppCubeTexture,
983 HANDLE *pSharedHandle, IUnknown *parent,
984 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
986 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
987 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
988 unsigned int i, j;
989 UINT tmpW;
990 HRESULT hr;
991 unsigned int pow2EdgeLength = EdgeLength;
993 /* TODO: It should only be possible to create textures for formats
994 that are reported as supported */
995 if (WINED3DFMT_UNKNOWN >= Format) {
996 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
997 return WINED3DERR_INVALIDCALL;
1000 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, WINED3DRTYPE_CUBETEXTURE, 0);
1001 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1003 TRACE("(%p) Create Cube Texture\n", This);
1005 /** Non-power2 support **/
1007 /* Find the nearest pow2 match */
1008 pow2EdgeLength = 1;
1009 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
1011 object->edgeLength = EdgeLength;
1012 /* TODO: support for native non-power 2 */
1013 /* Precalculated scaling for 'faked' non power of two texture coords */
1014 object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
1016 /* Calculate levels for mip mapping */
1017 if (Levels == 0) {
1018 object->baseTexture.levels++;
1019 tmpW = EdgeLength;
1020 while (tmpW > 1) {
1021 tmpW = max(1, tmpW >> 1);
1022 object->baseTexture.levels++;
1024 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1027 /* Generate all the surfaces */
1028 tmpW = EdgeLength;
1029 for (i = 0; i < object->baseTexture.levels; i++) {
1031 /* Create the 6 faces */
1032 for (j = 0; j < 6; j++) {
1034 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
1035 i /* Level */, &object->surfaces[j][i],pSharedHandle);
1037 if(hr!= WINED3D_OK) {
1038 /* clean up */
1039 int k;
1040 int l;
1041 for (l = 0; l < j; l++) {
1042 IWineD3DSurface_Release(object->surfaces[j][i]);
1044 for (k = 0; k < i; k++) {
1045 for (l = 0; l < 6; l++) {
1046 IWineD3DSurface_Release(object->surfaces[l][j]);
1050 FIXME("(%p) Failed to create surface\n",object);
1051 HeapFree(GetProcessHeap(),0,object);
1052 *ppCubeTexture = NULL;
1053 return hr;
1055 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IWineD3DBase *)object);
1056 TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1058 tmpW = max(1, tmpW >> 1);
1061 TRACE("(%p) : Created Cube Texture %p\n", This, object);
1062 *ppCubeTexture = (IWineD3DCubeTexture *) object;
1063 return WINED3D_OK;
1066 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1067 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1068 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1070 if (NULL == ppQuery) {
1071 /* Just a check to see if we support this type of query */
1072 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1073 switch(Type) {
1074 case WINED3DQUERYTYPE_OCCLUSION:
1075 TRACE("(%p) occlusion query\n", This);
1076 if (GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY))
1077 hr = WINED3D_OK;
1078 else
1079 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1080 break;
1081 case WINED3DQUERYTYPE_VCACHE:
1082 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1083 case WINED3DQUERYTYPE_VERTEXSTATS:
1084 case WINED3DQUERYTYPE_EVENT:
1085 case WINED3DQUERYTYPE_TIMESTAMP:
1086 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1087 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1088 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1089 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1090 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1091 case WINED3DQUERYTYPE_PIXELTIMINGS:
1092 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1093 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1094 default:
1095 FIXME("(%p) Unhandled query type %d\n", This, Type);
1097 return hr;
1100 D3DCREATEOBJECTINSTANCE(object, Query)
1101 object->type = Type;
1102 /* allocated the 'extended' data based on the type of query requested */
1103 switch(Type){
1104 case D3DQUERYTYPE_OCCLUSION:
1105 if(GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY)) {
1106 TRACE("(%p) Allocating data for an occlusion query\n", This);
1107 object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1108 break;
1110 case D3DQUERYTYPE_VCACHE:
1111 case D3DQUERYTYPE_RESOURCEMANAGER:
1112 case D3DQUERYTYPE_VERTEXSTATS:
1113 case D3DQUERYTYPE_EVENT:
1114 case D3DQUERYTYPE_TIMESTAMP:
1115 case D3DQUERYTYPE_TIMESTAMPDISJOINT:
1116 case D3DQUERYTYPE_TIMESTAMPFREQ:
1117 case D3DQUERYTYPE_PIPELINETIMINGS:
1118 case D3DQUERYTYPE_INTERFACETIMINGS:
1119 case D3DQUERYTYPE_VERTEXTIMINGS:
1120 case D3DQUERYTYPE_PIXELTIMINGS:
1121 case D3DQUERYTYPE_BANDWIDTHTIMINGS:
1122 case D3DQUERYTYPE_CACHEUTILIZATION:
1123 default:
1124 object->extendedData = 0;
1125 FIXME("(%p) Unhandled query type %d\n",This , Type);
1127 TRACE("(%p) : Created Query %p\n", This, object);
1128 return WINED3D_OK;
1131 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1132 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1133 IUnknown* parent,
1134 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1135 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1136 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1138 HDC hDc;
1139 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1140 int num;
1141 XVisualInfo template;
1142 GLXContext oldContext;
1143 Drawable oldDrawable;
1144 HRESULT hr = WINED3D_OK;
1146 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1148 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1149 * does a device hold a reference to a swap chain giving them a lifetime of the device
1150 * or does the swap chain notify the device of its destruction.
1151 *******************************/
1153 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1155 /*********************
1156 * Lookup the window Handle and the relating X window handle
1157 ********************/
1159 /* Setup hwnd we are using, plus which display this equates to */
1160 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1161 if (!object->win_handle) {
1162 object->win_handle = This->createParms.hFocusWindow;
1165 object->win_handle = GetAncestor(object->win_handle, GA_ROOT);
1166 if ( !( object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window") ) ) {
1167 ERR("Can't get drawable (window), HWND:%p doesn't have the property __wine_x11_whole_window\n", object->win_handle);
1168 return WINED3DERR_NOTAVAILABLE;
1170 hDc = GetDC(object->win_handle);
1171 object->display = get_display(hDc);
1172 ReleaseDC(object->win_handle, hDc);
1173 TRACE("Using a display of %p %p\n", object->display, hDc);
1175 if (NULL == object->display || NULL == hDc) {
1176 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1177 return WINED3DERR_NOTAVAILABLE;
1180 if (object->win == 0) {
1181 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1182 return WINED3DERR_NOTAVAILABLE;
1185 * Create an opengl context for the display visual
1186 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1187 * use different properties after that point in time. FIXME: How to handle when requested format
1188 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1189 * it chooses is identical to the one already being used!
1190 **********************************/
1192 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1193 ENTER_GL();
1195 /* Create a new context for this swapchain */
1196 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1197 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1198 (or the best possible if none is requested) */
1199 TRACE("Found x visual ID : %ld\n", template.visualid);
1201 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1202 if (NULL == object->visInfo) {
1203 ERR("cannot really get XVisual\n");
1204 LEAVE_GL();
1205 return WINED3DERR_NOTAVAILABLE;
1206 } else {
1207 int n, value;
1208 /* Write out some debug info about the visual/s */
1209 TRACE("Using x visual ID : %ld\n", template.visualid);
1210 TRACE(" visual info: %p\n", object->visInfo);
1211 TRACE(" num items : %d\n", num);
1212 for (n = 0;n < num; n++) {
1213 TRACE("=====item=====: %d\n", n + 1);
1214 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1215 TRACE(" screen : %d\n", object->visInfo[n].screen);
1216 TRACE(" depth : %u\n", object->visInfo[n].depth);
1217 TRACE(" class : %d\n", object->visInfo[n].class);
1218 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1219 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1220 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1221 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1222 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1223 /* log some extra glx info */
1224 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1225 TRACE(" gl_aux_buffers : %d\n", value);
1226 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1227 TRACE(" gl_buffer_size : %d\n", value);
1228 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1229 TRACE(" gl_red_size : %d\n", value);
1230 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1231 TRACE(" gl_green_size : %d\n", value);
1232 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1233 TRACE(" gl_blue_size : %d\n", value);
1234 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1235 TRACE(" gl_alpha_size : %d\n", value);
1236 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1237 TRACE(" gl_depth_size : %d\n", value);
1238 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1239 TRACE(" gl_stencil_size : %d\n", value);
1241 /* Now choose a simila visual ID*/
1243 #ifdef USE_CONTEXT_MANAGER
1245 /** TODO: use a context mamager **/
1246 #endif
1249 IWineD3DSwapChain *implSwapChain;
1250 if (WINED3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1251 /* The first time around we create the context that is shared with all other swapchains and render targets */
1252 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1253 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1254 } else {
1256 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1257 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1258 /* and create a new context with the implicit swapchains context as the shared context */
1259 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1260 IWineD3DSwapChain_Release(implSwapChain);
1264 /* Cleanup */
1265 XFree(object->visInfo);
1266 object->visInfo = NULL;
1268 if (NULL == object->glCtx) {
1269 ERR("cannot create glxContext\n");
1270 LEAVE_GL();
1271 return WINED3DERR_NOTAVAILABLE;
1274 LEAVE_GL();
1275 if (object->glCtx == NULL) {
1276 ERR("Error in context creation !\n");
1277 return WINED3DERR_INVALIDCALL;
1278 } else {
1279 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1280 object->win_handle, object->glCtx, object->win, object->visInfo);
1283 /*********************
1284 * Windowed / Fullscreen
1285 *******************/
1288 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1289 * so we should really check to see if there is a fullscreen swapchain already
1290 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1291 **************************************/
1293 if (!*(pPresentationParameters->Windowed)) {
1295 DEVMODEW devmode;
1296 HDC hdc;
1297 int bpp = 0;
1299 /* Get info on the current display setup */
1300 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1301 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1302 DeleteDC(hdc);
1304 /* Change the display settings */
1305 memset(&devmode, 0, sizeof(DEVMODEW));
1306 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1307 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1308 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1309 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1310 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1311 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1313 /* Make popup window */
1314 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1315 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1316 *(pPresentationParameters->BackBufferWidth),
1317 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1323 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1324 * then the corresponding dimension of the client area of the hDeviceWindow
1325 * (or the focus window, if hDeviceWindow is NULL) is taken.
1326 **********************/
1328 if (*(pPresentationParameters->Windowed) &&
1329 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1330 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1332 RECT Rect;
1333 GetClientRect(object->win_handle, &Rect);
1335 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1336 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1337 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1339 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1340 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1341 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1345 /*********************
1346 * finish off parameter initialization
1347 *******************/
1349 /* Put the correct figures in the presentation parameters */
1350 TRACE("Coppying accross presentaion paraneters\n");
1351 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1352 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1353 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1354 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1355 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1356 object->presentParms.MultiSampleQuality = NULL == pPresentationParameters->MultiSampleQuality ? 0 : *(pPresentationParameters->MultiSampleQuality);
1357 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1358 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1359 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1360 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1361 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1362 object->presentParms.Flags = *(pPresentationParameters->Flags);
1363 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1364 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1367 /*********************
1368 * Create the back, front and stencil buffers
1369 *******************/
1370 TRACE("calling rendertarget CB\n");
1371 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1372 object->presentParms.BackBufferWidth,
1373 object->presentParms.BackBufferHeight,
1374 object->presentParms.BackBufferFormat,
1375 object->presentParms.MultiSampleType,
1376 object->presentParms.MultiSampleQuality,
1377 TRUE /* Lockable */,
1378 &object->frontBuffer,
1379 NULL /* pShared (always null)*/);
1380 if (object->frontBuffer != NULL)
1381 IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
1382 if(object->presentParms.BackBufferCount > 0) {
1383 TRACE("calling rendertarget CB\n");
1384 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1385 object->presentParms.BackBufferWidth,
1386 object->presentParms.BackBufferHeight,
1387 object->presentParms.BackBufferFormat,
1388 object->presentParms.MultiSampleType,
1389 object->presentParms.MultiSampleQuality,
1390 TRUE /* Lockable */,
1391 &object->backBuffer,
1392 NULL /* pShared (always null)*/);
1393 } else {
1394 object->backBuffer = NULL;
1397 if (object->backBuffer != NULL) {
1398 IWineD3DSurface_SetContainer(object->backBuffer, (IWineD3DBase *)object);
1399 ENTER_GL();
1400 glDrawBuffer(GL_BACK);
1401 checkGLcall("glDrawBuffer(GL_BACK)");
1402 LEAVE_GL();
1403 } else {
1404 /* Single buffering - draw to front buffer */
1405 ENTER_GL();
1406 glDrawBuffer(GL_FRONT);
1407 checkGLcall("glDrawBuffer(GL_FRONT)");
1408 LEAVE_GL();
1411 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1412 if (pPresentationParameters->EnableAutoDepthStencil) {
1413 TRACE("Creating depth stencil buffer\n");
1414 if (This->depthStencilBuffer == NULL ) {
1415 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1416 object->presentParms.BackBufferWidth,
1417 object->presentParms.BackBufferHeight,
1418 object->presentParms.AutoDepthStencilFormat,
1419 object->presentParms.MultiSampleType,
1420 object->presentParms.MultiSampleQuality,
1421 FALSE /* FIXME: Discard */,
1422 &This->depthStencilBuffer,
1423 NULL /* pShared (always null)*/ );
1424 if (This->depthStencilBuffer != NULL)
1425 IWineD3DSurface_SetContainer(This->depthStencilBuffer, 0);
1428 /** TODO: A check on width, height and multisample types
1429 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1430 ****************************/
1431 object->wantsDepthStencilBuffer = TRUE;
1432 } else {
1433 object->wantsDepthStencilBuffer = FALSE;
1436 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1439 /*********************
1440 * init the default renderTarget management
1441 *******************/
1442 object->drawable = object->win;
1443 object->render_ctx = object->glCtx;
1445 if (hr == WINED3D_OK) {
1446 /*********************
1447 * Setup some defaults and clear down the buffers
1448 *******************/
1449 ENTER_GL();
1450 /** save current context and drawable **/
1451 oldContext = glXGetCurrentContext();
1452 oldDrawable = glXGetCurrentDrawable();
1454 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1455 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1456 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1458 checkGLcall("glXMakeCurrent");
1460 TRACE("Setting up the screen\n");
1461 /* Clear the screen */
1462 glClearColor(1.0, 0.0, 0.0, 0.0);
1463 checkGLcall("glClearColor");
1464 glClearIndex(0);
1465 glClearDepth(1);
1466 glClearStencil(0xffff);
1468 checkGLcall("glClear");
1470 glColor3f(1.0, 1.0, 1.0);
1471 checkGLcall("glColor3f");
1473 glEnable(GL_LIGHTING);
1474 checkGLcall("glEnable");
1476 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1477 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1479 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1480 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1482 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1483 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1485 /* switch back to the original context (if there was one)*/
1486 if (This->swapchains != NULL) {
1487 /** TODO: restore the context and drawable **/
1488 glXMakeCurrent(object->display, oldDrawable, oldContext);
1491 LEAVE_GL();
1493 { /* Finally add the swapchain to the end of the devices' swapchain list */
1494 SwapChainList **nextSwapchain;
1495 nextSwapchain = &This->swapchains;
1496 while (*nextSwapchain != NULL) {
1497 nextSwapchain = &((*nextSwapchain)->next);
1499 (*nextSwapchain) = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->swapchains));
1500 (*nextSwapchain)->swapchain = (IWineD3DSwapChain *)object;
1502 TRACE("Set swapchain to %p\n", object);
1503 } else { /* something went wrong so clean up */
1504 IUnknown* bufferParent;
1505 if (object->frontBuffer) {
1507 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1508 IUnknown_Release(bufferParent); /* once for the get parent */
1509 if (IUnknown_Release(bufferParent) > 0) {
1510 FIXME("(%p) Something's still holding the front buffer\n",This);
1513 if (object->backBuffer) {
1514 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1515 IUnknown_Release(bufferParent); /* once for the get parent */
1516 if (IUnknown_Release(bufferParent) > 0) {
1517 FIXME("(%p) Something's still holding the back buffer\n",This);
1520 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1521 /* Clean up the context */
1522 /* check that we are the current context first (we shouldn't be though!) */
1523 if (object->glCtx != 0) {
1524 if(glXGetCurrentContext() == object->glCtx) {
1525 glXMakeCurrent(object->display, None, NULL);
1527 glXDestroyContext(object->display, object->glCtx);
1529 HeapFree(GetProcessHeap(), 0, object);
1533 return hr;
1536 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1537 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1538 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1539 unsigned int numberOfSwapChains = 0;
1540 SwapChainList *swapchain;
1542 swapchain = This->swapchains;
1543 /* itterate through the list to get a count */
1544 while (swapchain != NULL) {
1545 swapchain = swapchain->next;
1546 numberOfSwapChains++;
1549 TRACE("(%p) returning %d\n", This, numberOfSwapChains);
1550 return numberOfSwapChains;
1553 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1554 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1555 SwapChainList *swapchain;
1556 int i = iSwapChain;
1557 HRESULT hr = WINED3DERR_INVALIDCALL;
1558 swapchain = This->swapchains;
1559 TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1562 TRACE("(%p) Finding swapchain %d\n", This, iSwapChain);
1563 while (i > 0 && swapchain != NULL) {
1564 swapchain = swapchain->next;
1565 --i;
1568 if (i > 0) {
1569 FIXME("(%p) Unable to find swapchain %d\n", This, iSwapChain);
1570 *pSwapChain = NULL;
1571 } else if (swapchain != NULL) {
1572 /** TODO: move off to a linkesList implementation **/
1573 *pSwapChain = swapchain->swapchain;
1574 IWineD3DSwapChain_AddRef(*pSwapChain);
1575 hr = WINED3D_OK;
1578 TRACE("(%p) returning %p\n", This, *pSwapChain);
1579 return hr;
1582 /*****
1583 * Vertex Declaration
1584 *****/
1585 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1586 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1587 IWineD3DVertexDeclarationImpl *object = NULL;
1588 HRESULT hr = WINED3D_OK;
1589 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1590 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1591 object->allFVF = 0;
1593 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1595 return hr;
1598 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1599 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pDeclaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1600 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1601 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1602 HRESULT hr = WINED3D_OK;
1603 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1604 object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins;
1606 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1608 /* If a vertex declaration has been passed, save it to the vertex shader, this affects d3d8 only. */
1609 /* Further it needs to be set before calling SetFunction as SetFunction needs the declaration. */
1610 if (pDeclaration != NULL) {
1611 IWineD3DVertexDeclaration *vertexDeclaration;
1612 hr = IWineD3DDevice_CreateVertexDeclaration(iface, pDeclaration, &vertexDeclaration ,NULL);
1613 if (WINED3D_OK == hr) {
1614 TRACE("(%p) : Setting vertex declaration to %p\n", This, vertexDeclaration);
1615 object->vertexDeclaration = vertexDeclaration;
1616 } else {
1617 FIXME("(%p) : Failed to set the declaration, returning WINED3DERR_INVALIDCALL\n", iface);
1618 IWineD3DVertexShader_Release(*ppVertexShader);
1619 return WINED3DERR_INVALIDCALL;
1623 hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1625 if (WINED3D_OK != hr) {
1626 FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface);
1627 IWineD3DVertexShader_Release(*ppVertexShader);
1628 return WINED3DERR_INVALIDCALL;
1631 #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. */
1632 if(Usage == WINED3DUSAGE_SOFTWAREVERTEXPROCESSING) {
1633 /* Foo */
1634 } else {
1635 /* Bar */
1638 #endif
1640 return WINED3D_OK;
1643 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
1644 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1645 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1646 HRESULT hr = WINED3D_OK;
1648 D3DCREATEOBJECTINSTANCE(object, PixelShader)
1649 object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins;
1650 hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
1651 if (WINED3D_OK == hr) {
1652 TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
1653 } else {
1654 WARN("(%p) : Failed to create pixel shader\n", This);
1657 return hr;
1660 HRESULT WINAPI IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice *iface, DWORD Flags, PALETTEENTRY *PalEnt, IWineD3DPalette **Palette, IUnknown *Parent) {
1661 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1662 IWineD3DPaletteImpl *object;
1663 HRESULT hr;
1664 TRACE("(%p)->(%lx, %p, %p, %p)\n", This, Flags, PalEnt, Palette, Parent);
1666 /* Create the new object */
1667 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DPaletteImpl));
1668 if(!object) {
1669 ERR("Out of memory when allocating memory for a IWineD3DPalette implementation\n");
1670 return E_OUTOFMEMORY;
1673 object->lpVtbl = &IWineD3DPalette_Vtbl;
1674 object->ref = 1;
1675 object->Flags = Flags;
1676 object->parent = Parent;
1677 object->wineD3DDevice = This;
1678 object->palNumEntries = IWineD3DPaletteImpl_Size(Flags);
1680 object->hpal = CreatePalette((const LOGPALETTE*)&(object->palVersion));
1682 if(!object->hpal) {
1683 HeapFree( GetProcessHeap(), 0, object);
1684 return E_OUTOFMEMORY;
1687 hr = IWineD3DPalette_SetEntries((IWineD3DPalette *) object, 0, 0, IWineD3DPaletteImpl_Size(Flags), PalEnt);
1688 if(FAILED(hr)) {
1689 IWineD3DPalette_Release((IWineD3DPalette *) object);
1690 return hr;
1693 *Palette = (IWineD3DPalette *) object;
1695 return WINED3D_OK;
1698 HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) {
1699 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1700 IWineD3DSwapChainImpl *swapchain;
1702 TRACE("(%p)->(%p,%p)\n", This, pPresentationParameters, D3DCB_CreateAdditionalSwapChain);
1703 if(This->d3d_initialized) return WINED3DERR_INVALIDCALL;
1705 /* TODO: Test if OpenGL is compiled in and loaded */
1707 /* Setup the implicit swapchain */
1708 TRACE("Creating implicit swapchain\n");
1709 if (D3D_OK != D3DCB_CreateAdditionalSwapChain((IUnknown *) This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain) || swapchain == NULL) {
1710 WARN("Failed to create implicit swapchain\n");
1711 return WINED3DERR_INVALIDCALL;
1714 if(swapchain->backBuffer) {
1715 TRACE("Setting rendertarget to %p\n", swapchain->backBuffer);
1716 This->renderTarget = swapchain->backBuffer;
1718 else {
1719 TRACE("Setting rendertarget to %p\n", swapchain->frontBuffer);
1720 This->renderTarget = swapchain->frontBuffer;
1722 IWineD3DSurface_AddRef(This->renderTarget);
1723 /* Depth Stencil support */
1724 This->stencilBufferTarget = This->depthStencilBuffer;
1725 if (NULL != This->stencilBufferTarget) {
1726 IWineD3DSurface_AddRef(This->stencilBufferTarget);
1729 /* Set up some starting GL setup */
1730 ENTER_GL();
1732 * Initialize openGL extension related variables
1733 * with Default values
1736 ((IWineD3DImpl *) This->wineD3D)->isGLInfoValid = IWineD3DImpl_FillGLCaps( &((IWineD3DImpl *) This->wineD3D)->gl_info, swapchain->display);
1737 /* Setup all the devices defaults */
1738 IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)This->stateBlock);
1739 #if 0
1740 IWineD3DImpl_CheckGraphicsMemory();
1741 #endif
1742 LEAVE_GL();
1744 { /* Set a default viewport */
1745 D3DVIEWPORT9 vp;
1746 vp.X = 0;
1747 vp.Y = 0;
1748 vp.Width = *(pPresentationParameters->BackBufferWidth);
1749 vp.Height = *(pPresentationParameters->BackBufferHeight);
1750 vp.MinZ = 0.0f;
1751 vp.MaxZ = 1.0f;
1752 IWineD3DDevice_SetViewport((IWineD3DDevice *)This, &vp);
1756 /* Initialize the current view state */
1757 This->modelview_valid = 1;
1758 This->proj_valid = 0;
1759 This->view_ident = 1;
1760 This->last_was_rhw = 0;
1761 glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights);
1762 TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This, This);
1764 /* Clear the screen */
1765 IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
1767 This->d3d_initialized = TRUE;
1768 return WINED3D_OK;
1771 HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface) {
1772 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1773 int texstage;
1774 IUnknown* stencilBufferParent;
1775 IUnknown* swapChainParent;
1776 SwapChainList *nextSwapchain;
1777 TRACE("(%p)\n", This);
1779 if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL;
1781 for(texstage = 0; texstage < GL_LIMITS(textures); texstage++) {
1782 IWineD3DDevice_SetTexture(iface, texstage, NULL);
1785 /* NOTE: You must release the parent if the object was created via a callback
1786 ** ***************************/
1787 /* Release all of the swapchains, except the implicit swapchain */
1789 /* NOTE: Don't release swapchain 0 here, it's 'special' */
1790 TRACE("Finding implicit swapchain\n");
1791 nextSwapchain = This->swapchains;
1792 if (nextSwapchain != NULL) {
1793 nextSwapchain = nextSwapchain->next;
1794 } else {
1795 WARN("Expected to find the implicit swapchain\n");
1798 TRACE("Releasing swapchains. nextSwapchain = %p\n", nextSwapchain);
1799 /* release all the other swapchains */
1800 while (nextSwapchain != NULL) {
1801 SwapChainList *prevSwapchain = nextSwapchain;
1802 nextSwapchain = nextSwapchain->next;
1803 TRACE("Releasing swapchain %p\n", prevSwapchain->swapchain);
1804 IWineD3DSwapChain_Release(prevSwapchain->swapchain);
1805 /* NOTE: no need to free the list element, it will be done by the release callback
1806 HeapFree(GetProcessHeap(), 0, prevSwapchain); */
1808 /* Release the buffers (with sanity checks)*/
1809 TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget);
1810 if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
1811 if(This->depthStencilBuffer != This->stencilBufferTarget)
1812 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
1814 This->stencilBufferTarget = NULL;
1816 TRACE("Releasing the render target at %p\n", This->renderTarget);
1817 if(IWineD3DSurface_Release(This->renderTarget) >0){
1818 /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
1820 TRACE("Setting rendertarget to NULL\n");
1821 This->renderTarget = NULL;
1823 IWineD3DSurface_GetParent(This->depthStencilBuffer, &stencilBufferParent);
1824 IUnknown_Release(stencilBufferParent); /* once for the get parent */
1825 if(IUnknown_Release(stencilBufferParent) >0){ /* the second time for when it was created */
1826 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
1828 This->depthStencilBuffer = NULL;
1830 TRACE("Releasing the implicit swapchain\n");
1831 if (This->swapchains != NULL) {
1832 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
1833 IWineD3DSwapChain_GetParent(This->swapchains->swapchain, &swapChainParent);
1834 IUnknown_Release(swapChainParent); /* once for the get parent */
1835 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
1836 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
1839 This->swapchains = NULL;
1841 This->d3d_initialized = FALSE;
1842 return WINED3D_OK;
1845 HRESULT WINAPI IWineD3DDeviceImpl_EnumDisplayModes(IWineD3DDevice *iface, DWORD Flags, UINT Width, UINT Height, WINED3DFORMAT pixelformat, LPVOID context, D3DCB_ENUMDISPLAYMODESCALLBACK callback) {
1846 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1848 DEVMODEW DevModeW;
1849 int i;
1851 TRACE("(%p)->(%lx,%d,%d,%d,%p,%p)\n", This, Flags, Width, Height, pixelformat, context, callback);
1853 for (i = 0; EnumDisplaySettingsExW(NULL, i, &DevModeW, 0); i++) {
1854 /* Ignore some modes if a description was passed */
1855 if ( (Width > 0) && (Width != DevModeW.dmPelsWidth)) continue;
1856 if ( (Height > 0) && (Height != DevModeW.dmPelsHeight)) continue;
1857 if ( (pixelformat != WINED3DFMT_UNKNOWN) && ( D3DFmtGetBpp(NULL, pixelformat) != DevModeW.dmBitsPerPel) ) continue;
1859 TRACE("Enumerating %ldx%ld@%s\n", DevModeW.dmPelsWidth, DevModeW.dmPelsHeight, debug_d3dformat(pixelformat_for_depth(DevModeW.dmBitsPerPel)));
1861 if (callback((IUnknown *) This, (UINT) DevModeW.dmPelsWidth, (UINT) DevModeW.dmPelsHeight, pixelformat_for_depth(DevModeW.dmBitsPerPel), 60.0, context) == DDENUMRET_CANCEL)
1862 return D3D_OK;
1865 return D3D_OK;
1868 HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
1869 FIXME("This call is a d3d7 merge stub. It will be implemented later\n");
1870 return WINED3DERR_INVALIDCALL;
1873 HRESULT WINAPI IWineD3DDeviceImpl_EnumZBufferFormats(IWineD3DDevice *iface, D3DCB_ENUMPIXELFORMATS Callback, void *Context) {
1874 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1875 HRESULT ret;
1876 int i = 0;
1877 WINED3DFORMAT FormatList[] = {
1878 WINED3DFMT_D16,
1879 WINED3DFMT_D32,
1880 WINED3DFMT_D24X4S4,
1881 WINED3DFMT_D24S8,
1882 WINED3DFMT_D24X8,
1883 WINED3DFMT_D15S1,
1884 WINED3DFMT_UNKNOWN /* Terminate the list */
1887 TRACE("(%p)->(%p,%p)\n", This, Callback, Context);
1889 while(FormatList[i] != WINED3DFMT_UNKNOWN) {
1890 TRACE("Enumerating %s\n", debug_d3dformat(FormatList[i]));
1891 ret = Callback((IUnknown *) This, FormatList[i], Context);
1892 if(ret != DDENUMRET_OK) {
1893 TRACE("Enumeration cancelled by Application\n");
1894 return WINED3D_OK;
1896 i++;
1899 TRACE("End of Enumeration\n");
1901 return WINED3D_OK;
1904 HRESULT WINAPI IWineD3DDeviceImpl_EnumTextureFormats(IWineD3DDevice *iface, D3DCB_ENUMPIXELFORMATS Callback, void *Context) {
1905 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1906 HRESULT ret;
1907 int i = 0;
1909 /* From old ddraw:
1910 * WINED3DFMT_A1R5G5B5 needs to be the first 16 bit format, as some dumb apps depend on this
1912 * Do not enumerate RGBA pixel formats: "some games choose the first 16 bit texture format
1913 * with alpha they find enumerated, others the last one. And both want to have the ARGB one."
1914 * But WineD3D doesn't support RGBA formats anyway...
1917 WINED3DFORMAT FormatList[] = {
1918 /* 32 bit */
1919 WINED3DFMT_A8R8G8B8,
1920 WINED3DFMT_X8R8G8B8,
1921 /* 24 bit */
1922 WINED3DFMT_R8G8B8,
1923 /* 16 Bit */
1924 WINED3DFMT_A1R5G5B5,
1925 WINED3DFMT_A4R4G4B4,
1926 WINED3DFMT_R5G6B5,
1927 WINED3DFMT_X1R5G5B5,
1928 /* 8 Bit */
1929 WINED3DFMT_R3G3B2,
1930 WINED3DFMT_P8,
1931 /* FOURCC codes */
1932 WINED3DFMT_DXT1,
1933 WINED3DFMT_DXT3,
1934 WINED3DFMT_DXT5,
1935 /* Terminate the list */
1936 WINED3DFMT_UNKNOWN
1939 TRACE("(%p)->(%p,%p)\n", This, Callback, Context);
1941 while(FormatList[i] != WINED3DFMT_UNKNOWN) {
1942 TRACE("Enumerating %s\n", debug_d3dformat(FormatList[i]));
1943 ret = Callback((IUnknown *) This, FormatList[i], Context);
1944 if(ret != DDENUMRET_OK) {
1945 TRACE("Enumeration cancelled by Application\n");
1946 return WINED3D_OK;
1948 i++;
1951 TRACE("End of Enumeration\n");
1953 return WINED3D_OK;
1956 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
1957 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1958 *ppD3D= This->wineD3D;
1959 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1960 IWineD3D_AddRef(*ppD3D);
1961 return WINED3D_OK;
1964 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1965 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1966 * Into the video ram as possible and seeing how many fit
1967 * you can also get the correct initial value from via X and ATI's driver
1968 *******************/
1969 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1970 static BOOL showfixmes = TRUE;
1971 if (showfixmes) {
1972 FIXME("(%p) : stub, emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1973 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1974 showfixmes = FALSE;
1976 TRACE("(%p) : emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1977 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1978 /* videomemory is simulated videomemory + AGP memory left */
1979 return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1984 /*****
1985 * Get / Set FVF
1986 *****/
1987 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1988 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1989 HRESULT hr = WINED3D_OK;
1991 /* Update the current state block */
1992 This->updateStateBlock->fvf = fvf;
1993 This->updateStateBlock->changed.fvf = TRUE;
1994 This->updateStateBlock->set.fvf = TRUE;
1996 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1998 if (0 != fvf) {
1999 /* clear down the vertex declaration
2000 NOTE: Axis and Allies doesn't work properly otherwise
2001 (may be a stateblock problem though!)
2003 hr = IWineD3DDevice_SetVertexDeclaration(iface, NULL);
2006 return hr;
2010 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
2011 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2012 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
2013 *pfvf = This->stateBlock->fvf;
2014 return WINED3D_OK;
2017 /*****
2018 * Get / Set Stream Source
2019 *****/
2020 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
2021 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2022 IWineD3DVertexBuffer *oldSrc;
2024 /**TODO: instance and index data, see
2025 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2027 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
2028 **************/
2030 /* D3d9 only, but shouldn't hurt d3d8 */
2031 UINT streamFlags;
2033 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2034 if (streamFlags) {
2035 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2036 FIXME("stream index data not supported\n");
2038 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2039 FIXME("stream instance data not supported\n");
2043 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2045 if (StreamNumber >= MAX_STREAMS) {
2046 WARN("Stream out of range %d\n", StreamNumber);
2047 return WINED3DERR_INVALIDCALL;
2050 oldSrc = This->stateBlock->streamSource[StreamNumber];
2051 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
2053 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
2054 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
2055 This->updateStateBlock->streamStride[StreamNumber] = Stride;
2056 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
2057 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
2058 This->updateStateBlock->streamFlags[StreamNumber] = streamFlags;
2060 /* Handle recording of state blocks */
2061 if (This->isRecordingState) {
2062 TRACE("Recording... not performing anything\n");
2063 return WINED3D_OK;
2066 /* Not recording... */
2067 /* Need to do a getParent and pass the reffs up */
2068 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
2069 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
2070 so for now, just count internally */
2071 if (pStreamData != NULL) {
2072 IWineD3DVertexBuffer_AddRef(pStreamData);
2074 if (oldSrc != NULL) {
2075 IWineD3DVertexBuffer_Release(oldSrc);
2078 return WINED3D_OK;
2081 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
2082 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2083 UINT streamFlags;
2085 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
2086 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
2089 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2090 if (streamFlags) {
2091 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2092 FIXME("stream index data not supported\n");
2094 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2095 FIXME("stream instance data not supported\n");
2099 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2101 if (StreamNumber >= MAX_STREAMS) {
2102 WARN("Stream out of range %d\n", StreamNumber);
2103 return WINED3DERR_INVALIDCALL;
2105 *pStream = This->stateBlock->streamSource[StreamNumber];
2106 *pStride = This->stateBlock->streamStride[StreamNumber];
2107 *pOffset = This->stateBlock->streamOffset[StreamNumber];
2109 if (*pStream == NULL) {
2110 FIXME("Attempting to get an empty stream %d, returning WINED3DERR_INVALIDCALL\n", StreamNumber);
2111 return WINED3DERR_INVALIDCALL;
2114 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
2115 return WINED3D_OK;
2118 /*Should be quite easy, just an extension of vertexdata
2119 ref...
2120 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2122 The divider is a bit odd though
2124 VertexOffset = StartVertex / Divider * StreamStride +
2125 VertexIndex / Divider * StreamStride + StreamOffset
2128 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
2129 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2131 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
2132 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (D3DSTREAMSOURCE_INSTANCEDATA | D3DSTREAMSOURCE_INDEXEDDATA );
2134 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
2135 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
2136 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
2138 if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
2139 FIXME("Stream indexing not fully supported\n");
2142 return WINED3D_OK;
2145 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
2146 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2148 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
2149 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
2151 TRACE("(%p) : returning %d\n", This, *Divider);
2153 return WINED3D_OK;
2156 /*****
2157 * Get / Set & Multiply Transform
2158 *****/
2159 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
2160 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2162 /* Most of this routine, comments included copied from ddraw tree initially: */
2163 TRACE("(%p) : Transform State=%d\n", This, d3dts);
2165 /* Handle recording of state blocks */
2166 if (This->isRecordingState) {
2167 TRACE("Recording... not performing anything\n");
2168 This->updateStateBlock->changed.transform[d3dts] = TRUE;
2169 This->updateStateBlock->set.transform[d3dts] = TRUE;
2170 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
2171 return WINED3D_OK;
2175 * If the new matrix is the same as the current one,
2176 * we cut off any further processing. this seems to be a reasonable
2177 * optimization because as was noticed, some apps (warcraft3 for example)
2178 * tend towards setting the same matrix repeatedly for some reason.
2180 * From here on we assume that the new matrix is different, wherever it matters.
2182 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
2183 TRACE("The app is setting the same matrix over again\n");
2184 return WINED3D_OK;
2185 } else {
2186 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
2190 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2191 where ViewMat = Camera space, WorldMat = world space.
2193 In OpenGL, camera and world space is combined into GL_MODELVIEW
2194 matrix. The Projection matrix stay projection matrix.
2197 /* Capture the times we can just ignore the change for now */
2198 if (d3dts == D3DTS_WORLDMATRIX(0)) {
2199 This->modelview_valid = FALSE;
2200 return WINED3D_OK;
2202 } else if (d3dts == D3DTS_PROJECTION) {
2203 This->proj_valid = FALSE;
2204 return WINED3D_OK;
2206 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
2207 /* Indexed Vertex Blending Matrices 256 -> 511 */
2208 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
2209 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
2210 return WINED3D_OK;
2213 /* Now we really are going to have to change a matrix */
2214 ENTER_GL();
2216 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
2217 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
2218 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
2219 unsigned int k;
2221 /* If we are changing the View matrix, reset the light and clipping planes to the new view
2222 * NOTE: We have to reset the positions even if the light/plane is not currently
2223 * enabled, since the call to enable it will not reset the position.
2224 * NOTE2: Apparently texture transforms do NOT need reapplying
2227 PLIGHTINFOEL *lightChain = NULL;
2228 This->modelview_valid = FALSE;
2229 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
2231 glMatrixMode(GL_MODELVIEW);
2232 checkGLcall("glMatrixMode(GL_MODELVIEW)");
2233 glPushMatrix();
2234 glLoadMatrixf((float *)lpmatrix);
2235 checkGLcall("glLoadMatrixf(...)");
2237 /* Reset lights */
2238 lightChain = This->stateBlock->lights;
2239 while (lightChain && lightChain->glIndex != -1) {
2240 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
2241 checkGLcall("glLightfv posn");
2242 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
2243 checkGLcall("glLightfv dirn");
2244 lightChain = lightChain->next;
2247 /* Reset Clipping Planes if clipping is enabled */
2248 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2249 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
2250 checkGLcall("glClipPlane");
2252 glPopMatrix();
2254 } else { /* What was requested!?? */
2255 WARN("invalid matrix specified: %i\n", d3dts);
2258 /* Release lock, all done */
2259 LEAVE_GL();
2260 return WINED3D_OK;
2263 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
2264 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2265 TRACE("(%p) : for Transform State %d\n", This, State);
2266 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
2267 return WINED3D_OK;
2270 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
2271 D3DMATRIX *mat = NULL;
2272 D3DMATRIX temp;
2274 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2275 * below means it will be recorded in a state block change, but it
2276 * works regardless where it is recorded.
2277 * If this is found to be wrong, change to StateBlock.
2279 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2280 TRACE("(%p) : For state %u\n", This, State);
2282 if (State < HIGHEST_TRANSFORMSTATE)
2284 mat = &This->updateStateBlock->transforms[State];
2285 } else {
2286 FIXME("Unhandled transform state!!\n");
2289 multiply_matrix(&temp, mat, (D3DMATRIX *) pMatrix);
2291 /* Apply change via set transform - will reapply to eg. lights this way */
2292 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2295 /*****
2296 * Get / Set Light
2297 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
2298 *****/
2299 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2300 you can reference any indexes you want as long as that number max are enabled at any
2301 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2302 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2303 but when recording, just build a chain pretty much of commands to be replayed. */
2305 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2306 float rho;
2307 PLIGHTINFOEL *object, *temp;
2309 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2310 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2312 /* If recording state block, just add to end of lights chain */
2313 if (This->isRecordingState) {
2314 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2315 if (NULL == object) {
2316 return WINED3DERR_OUTOFVIDEOMEMORY;
2318 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2319 object->OriginalIndex = Index;
2320 object->glIndex = -1;
2321 object->changed = TRUE;
2323 /* Add to the END of the chain of lights changes to be replayed */
2324 if (This->updateStateBlock->lights == NULL) {
2325 This->updateStateBlock->lights = object;
2326 } else {
2327 temp = This->updateStateBlock->lights;
2328 while (temp->next != NULL) temp=temp->next;
2329 temp->next = object;
2331 TRACE("Recording... not performing anything more\n");
2332 return WINED3D_OK;
2335 /* Ok, not recording any longer so do real work */
2336 object = This->stateBlock->lights;
2337 while (object != NULL && object->OriginalIndex != Index) object = object->next;
2339 /* If we didn't find it in the list of lights, time to add it */
2340 if (object == NULL) {
2341 PLIGHTINFOEL *insertAt,*prevPos;
2343 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2344 if (NULL == object) {
2345 return WINED3DERR_OUTOFVIDEOMEMORY;
2347 object->OriginalIndex = Index;
2348 object->glIndex = -1;
2350 /* Add it to the front of list with the idea that lights will be changed as needed
2351 BUT after any lights currently assigned GL indexes */
2352 insertAt = This->stateBlock->lights;
2353 prevPos = NULL;
2354 while (insertAt != NULL && insertAt->glIndex != -1) {
2355 prevPos = insertAt;
2356 insertAt = insertAt->next;
2359 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2360 This->stateBlock->lights = object;
2361 } else if (insertAt == NULL) { /* End of list */
2362 prevPos->next = object;
2363 object->prev = prevPos;
2364 } else { /* Middle of chain */
2365 if (prevPos == NULL) {
2366 This->stateBlock->lights = object;
2367 } else {
2368 prevPos->next = object;
2370 object->prev = prevPos;
2371 object->next = insertAt;
2372 insertAt->prev = object;
2376 /* Initialize the object */
2377 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,
2378 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2379 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2380 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2381 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2382 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2383 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2385 /* Save away the information */
2386 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2388 switch (pLight->Type) {
2389 case D3DLIGHT_POINT:
2390 /* Position */
2391 object->lightPosn[0] = pLight->Position.x;
2392 object->lightPosn[1] = pLight->Position.y;
2393 object->lightPosn[2] = pLight->Position.z;
2394 object->lightPosn[3] = 1.0f;
2395 object->cutoff = 180.0f;
2396 /* FIXME: Range */
2397 break;
2399 case D3DLIGHT_DIRECTIONAL:
2400 /* Direction */
2401 object->lightPosn[0] = -pLight->Direction.x;
2402 object->lightPosn[1] = -pLight->Direction.y;
2403 object->lightPosn[2] = -pLight->Direction.z;
2404 object->lightPosn[3] = 0.0;
2405 object->exponent = 0.0f;
2406 object->cutoff = 180.0f;
2407 break;
2409 case D3DLIGHT_SPOT:
2410 /* Position */
2411 object->lightPosn[0] = pLight->Position.x;
2412 object->lightPosn[1] = pLight->Position.y;
2413 object->lightPosn[2] = pLight->Position.z;
2414 object->lightPosn[3] = 1.0;
2416 /* Direction */
2417 object->lightDirn[0] = pLight->Direction.x;
2418 object->lightDirn[1] = pLight->Direction.y;
2419 object->lightDirn[2] = pLight->Direction.z;
2420 object->lightDirn[3] = 1.0;
2423 * opengl-ish and d3d-ish spot lights use too different models for the
2424 * light "intensity" as a function of the angle towards the main light direction,
2425 * so we only can approximate very roughly.
2426 * however spot lights are rather rarely used in games (if ever used at all).
2427 * furthermore if still used, probably nobody pays attention to such details.
2429 if (pLight->Falloff == 0) {
2430 rho = 6.28f;
2431 } else {
2432 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2434 if (rho < 0.0001) rho = 0.0001f;
2435 object->exponent = -0.3/log(cos(rho/2));
2436 object->cutoff = pLight->Phi*90/M_PI;
2438 /* FIXME: Range */
2439 break;
2441 default:
2442 FIXME("Unrecognized light type %d\n", pLight->Type);
2445 /* Update the live definitions if the light is currently assigned a glIndex */
2446 if (object->glIndex != -1) {
2447 setup_light(iface, object->glIndex, object);
2449 return WINED3D_OK;
2452 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2453 PLIGHTINFOEL *lightInfo = NULL;
2454 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2455 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2457 /* Locate the light in the live lights */
2458 lightInfo = This->stateBlock->lights;
2459 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2461 if (lightInfo == NULL) {
2462 TRACE("Light information requested but light not defined\n");
2463 return WINED3DERR_INVALIDCALL;
2466 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
2467 return WINED3D_OK;
2470 /*****
2471 * Get / Set Light Enable
2472 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2473 *****/
2474 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2475 PLIGHTINFOEL *lightInfo = NULL;
2476 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2477 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2479 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2480 if (This->isRecordingState) {
2481 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2482 if (NULL == lightInfo) {
2483 return WINED3DERR_OUTOFVIDEOMEMORY;
2485 lightInfo->OriginalIndex = Index;
2486 lightInfo->glIndex = -1;
2487 lightInfo->enabledChanged = TRUE;
2489 /* Add to the END of the chain of lights changes to be replayed */
2490 if (This->updateStateBlock->lights == NULL) {
2491 This->updateStateBlock->lights = lightInfo;
2492 } else {
2493 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2494 while (temp->next != NULL) temp=temp->next;
2495 temp->next = lightInfo;
2497 TRACE("Recording... not performing anything more\n");
2498 return WINED3D_OK;
2501 /* Not recording... So, locate the light in the live lights */
2502 lightInfo = This->stateBlock->lights;
2503 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2505 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2506 if (lightInfo == NULL) {
2507 D3DLIGHT9 lightParms;
2508 /* Warning - untested code :-) Prob safe to change fixme to a trace but
2509 wait until someone confirms it seems to work! */
2510 TRACE("Light enabled requested but light not defined, so defining one!\n");
2511 lightParms.Type = D3DLIGHT_DIRECTIONAL;
2512 lightParms.Diffuse.r = 1.0;
2513 lightParms.Diffuse.g = 1.0;
2514 lightParms.Diffuse.b = 1.0;
2515 lightParms.Diffuse.a = 0.0;
2516 lightParms.Specular.r = 0.0;
2517 lightParms.Specular.g = 0.0;
2518 lightParms.Specular.b = 0.0;
2519 lightParms.Specular.a = 0.0;
2520 lightParms.Ambient.r = 0.0;
2521 lightParms.Ambient.g = 0.0;
2522 lightParms.Ambient.b = 0.0;
2523 lightParms.Ambient.a = 0.0;
2524 lightParms.Position.x = 0.0;
2525 lightParms.Position.y = 0.0;
2526 lightParms.Position.z = 0.0;
2527 lightParms.Direction.x = 0.0;
2528 lightParms.Direction.y = 0.0;
2529 lightParms.Direction.z = 1.0;
2530 lightParms.Range = 0.0;
2531 lightParms.Falloff = 0.0;
2532 lightParms.Attenuation0 = 0.0;
2533 lightParms.Attenuation1 = 0.0;
2534 lightParms.Attenuation2 = 0.0;
2535 lightParms.Theta = 0.0;
2536 lightParms.Phi = 0.0;
2537 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
2539 /* Search for it again! Should be fairly quick as near head of list */
2540 lightInfo = This->stateBlock->lights;
2541 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2542 if (lightInfo == NULL) {
2543 FIXME("Adding default lights has failed dismally\n");
2544 return WINED3DERR_INVALIDCALL;
2548 /* OK, we now have a light... */
2549 if (Enable == FALSE) {
2551 /* If we are disabling it, check it was enabled, and
2552 still only do something if it has assigned a glIndex (which it should have!) */
2553 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2554 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2555 ENTER_GL();
2556 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2557 checkGLcall("glDisable GL_LIGHT0+Index");
2558 LEAVE_GL();
2559 } else {
2560 TRACE("Nothing to do as light was not enabled\n");
2562 lightInfo->lightEnabled = FALSE;
2563 } else {
2565 /* We are enabling it. If it is enabled, it's really simple */
2566 if (lightInfo->lightEnabled) {
2567 /* nop */
2568 TRACE("Nothing to do as light was enabled\n");
2570 /* If it already has a glIndex, it's still simple */
2571 } else if (lightInfo->glIndex != -1) {
2572 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2573 lightInfo->lightEnabled = TRUE;
2574 ENTER_GL();
2575 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2576 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2577 LEAVE_GL();
2579 /* Otherwise got to find space - lights are ordered gl indexes first */
2580 } else {
2581 PLIGHTINFOEL *bsf = NULL;
2582 PLIGHTINFOEL *pos = This->stateBlock->lights;
2583 PLIGHTINFOEL *prev = NULL;
2584 int Index= 0;
2585 int glIndex = -1;
2587 /* Try to minimize changes as much as possible */
2588 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2590 /* Try to remember which index can be replaced if necessary */
2591 if (bsf==NULL && pos->lightEnabled == FALSE) {
2592 /* Found a light we can replace, save as best replacement */
2593 bsf = pos;
2596 /* Step to next space */
2597 prev = pos;
2598 pos = pos->next;
2599 Index ++;
2602 /* If we have too many active lights, fail the call */
2603 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2604 FIXME("Program requests too many concurrent lights\n");
2605 return WINED3DERR_INVALIDCALL;
2607 /* If we have allocated all lights, but not all are enabled,
2608 reuse one which is not enabled */
2609 } else if (Index == This->maxConcurrentLights) {
2610 /* use bsf - Simply swap the new light and the BSF one */
2611 PLIGHTINFOEL *bsfNext = bsf->next;
2612 PLIGHTINFOEL *bsfPrev = bsf->prev;
2614 /* Sort out ends */
2615 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2616 if (bsf->prev != NULL) {
2617 bsf->prev->next = lightInfo;
2618 } else {
2619 This->stateBlock->lights = lightInfo;
2622 /* If not side by side, lots of chains to update */
2623 if (bsf->next != lightInfo) {
2624 lightInfo->prev->next = bsf;
2625 bsf->next->prev = lightInfo;
2626 bsf->next = lightInfo->next;
2627 bsf->prev = lightInfo->prev;
2628 lightInfo->next = bsfNext;
2629 lightInfo->prev = bsfPrev;
2631 } else {
2632 /* Simple swaps */
2633 bsf->prev = lightInfo;
2634 bsf->next = lightInfo->next;
2635 lightInfo->next = bsf;
2636 lightInfo->prev = bsfPrev;
2640 /* Update states */
2641 glIndex = bsf->glIndex;
2642 bsf->glIndex = -1;
2643 lightInfo->glIndex = glIndex;
2644 lightInfo->lightEnabled = TRUE;
2646 /* Finally set up the light in gl itself */
2647 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2648 ENTER_GL();
2649 setup_light(iface, glIndex, lightInfo);
2650 glEnable(GL_LIGHT0 + glIndex);
2651 checkGLcall("glEnable GL_LIGHT0 new setup");
2652 LEAVE_GL();
2654 /* If we reached the end of the allocated lights, with space in the
2655 gl lights, setup a new light */
2656 } else if (pos->glIndex == -1) {
2658 /* We reached the end of the allocated gl lights, so already
2659 know the index of the next one! */
2660 glIndex = Index;
2661 lightInfo->glIndex = glIndex;
2662 lightInfo->lightEnabled = TRUE;
2664 /* In an ideal world, it's already in the right place */
2665 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2666 /* No need to move it */
2667 } else {
2668 /* Remove this light from the list */
2669 lightInfo->prev->next = lightInfo->next;
2670 if (lightInfo->next != NULL) {
2671 lightInfo->next->prev = lightInfo->prev;
2674 /* Add in at appropriate place (inbetween prev and pos) */
2675 lightInfo->prev = prev;
2676 lightInfo->next = pos;
2677 if (prev == NULL) {
2678 This->stateBlock->lights = lightInfo;
2679 } else {
2680 prev->next = lightInfo;
2682 if (pos != NULL) {
2683 pos->prev = lightInfo;
2687 /* Finally set up the light in gl itself */
2688 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2689 ENTER_GL();
2690 setup_light(iface, glIndex, lightInfo);
2691 glEnable(GL_LIGHT0 + glIndex);
2692 checkGLcall("glEnable GL_LIGHT0 new setup");
2693 LEAVE_GL();
2698 return WINED3D_OK;
2701 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2703 PLIGHTINFOEL *lightInfo = NULL;
2704 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2705 TRACE("(%p) : for idx(%ld)\n", This, Index);
2707 /* Locate the light in the live lights */
2708 lightInfo = This->stateBlock->lights;
2709 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2711 if (lightInfo == NULL) {
2712 TRACE("Light enabled state requested but light not defined\n");
2713 return WINED3DERR_INVALIDCALL;
2715 *pEnable = lightInfo->lightEnabled;
2716 return WINED3D_OK;
2719 /*****
2720 * Get / Set Clip Planes
2721 *****/
2722 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2723 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2724 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2726 /* Validate Index */
2727 if (Index >= GL_LIMITS(clipplanes)) {
2728 TRACE("Application has requested clipplane this device doesn't support\n");
2729 return WINED3DERR_INVALIDCALL;
2732 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2733 This->updateStateBlock->set.clipplane[Index] = TRUE;
2734 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2735 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2736 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2737 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2739 /* Handle recording of state blocks */
2740 if (This->isRecordingState) {
2741 TRACE("Recording... not performing anything\n");
2742 return WINED3D_OK;
2745 /* Apply it */
2747 ENTER_GL();
2749 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2750 glMatrixMode(GL_MODELVIEW);
2751 glPushMatrix();
2752 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2754 TRACE("Clipplane [%f,%f,%f,%f]\n",
2755 This->updateStateBlock->clipplane[Index][0],
2756 This->updateStateBlock->clipplane[Index][1],
2757 This->updateStateBlock->clipplane[Index][2],
2758 This->updateStateBlock->clipplane[Index][3]);
2759 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2760 checkGLcall("glClipPlane");
2762 glPopMatrix();
2763 LEAVE_GL();
2765 return WINED3D_OK;
2768 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2769 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2770 TRACE("(%p) : for idx %ld\n", This, Index);
2772 /* Validate Index */
2773 if (Index >= GL_LIMITS(clipplanes)) {
2774 TRACE("Application has requested clipplane this device doesn't support\n");
2775 return WINED3DERR_INVALIDCALL;
2778 pPlane[0] = This->stateBlock->clipplane[Index][0];
2779 pPlane[1] = This->stateBlock->clipplane[Index][1];
2780 pPlane[2] = This->stateBlock->clipplane[Index][2];
2781 pPlane[3] = This->stateBlock->clipplane[Index][3];
2782 return WINED3D_OK;
2785 /*****
2786 * Get / Set Clip Plane Status
2787 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2788 *****/
2789 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2790 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2791 FIXME("(%p) : stub\n", This);
2792 if (NULL == pClipStatus) {
2793 return WINED3DERR_INVALIDCALL;
2795 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2796 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2797 return WINED3D_OK;
2800 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2801 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2802 FIXME("(%p) : stub\n", This);
2803 if (NULL == pClipStatus) {
2804 return WINED3DERR_INVALIDCALL;
2806 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2807 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2808 return WINED3D_OK;
2811 /*****
2812 * Get / Set Material
2813 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2814 *****/
2815 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2816 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2818 This->updateStateBlock->changed.material = TRUE;
2819 This->updateStateBlock->set.material = TRUE;
2820 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2822 /* Handle recording of state blocks */
2823 if (This->isRecordingState) {
2824 TRACE("Recording... not performing anything\n");
2825 return WINED3D_OK;
2828 ENTER_GL();
2829 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2830 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2831 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2832 pMaterial->Ambient.b, pMaterial->Ambient.a);
2833 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2834 pMaterial->Specular.b, pMaterial->Specular.a);
2835 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2836 pMaterial->Emissive.b, pMaterial->Emissive.a);
2837 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2839 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2840 checkGLcall("glMaterialfv(GL_AMBIENT)");
2841 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2842 checkGLcall("glMaterialfv(GL_DIFFUSE)");
2844 /* Only change material color if specular is enabled, otherwise it is set to black */
2845 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2846 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2847 checkGLcall("glMaterialfv(GL_SPECULAR");
2848 } else {
2849 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2850 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2851 checkGLcall("glMaterialfv(GL_SPECULAR");
2853 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2854 checkGLcall("glMaterialfv(GL_EMISSION)");
2855 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2856 checkGLcall("glMaterialf(GL_SHININESS");
2858 LEAVE_GL();
2859 return WINED3D_OK;
2862 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2863 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2864 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2865 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2866 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2867 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2868 pMaterial->Ambient.b, pMaterial->Ambient.a);
2869 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2870 pMaterial->Specular.b, pMaterial->Specular.a);
2871 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2872 pMaterial->Emissive.b, pMaterial->Emissive.a);
2873 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2875 return WINED3D_OK;
2878 /*****
2879 * Get / Set Indices
2880 *****/
2881 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2882 UINT BaseVertexIndex) {
2883 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2884 IWineD3DIndexBuffer *oldIdxs;
2886 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2887 oldIdxs = This->updateStateBlock->pIndexData;
2889 This->updateStateBlock->changed.indices = TRUE;
2890 This->updateStateBlock->set.indices = TRUE;
2891 This->updateStateBlock->pIndexData = pIndexData;
2892 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2894 /* Handle recording of state blocks */
2895 if (This->isRecordingState) {
2896 TRACE("Recording... not performing anything\n");
2897 return WINED3D_OK;
2900 if (NULL != pIndexData) {
2901 IWineD3DIndexBuffer_AddRef(pIndexData);
2903 if (NULL != oldIdxs) {
2904 IWineD3DIndexBuffer_Release(oldIdxs);
2906 return WINED3D_OK;
2909 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2910 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2912 *ppIndexData = This->stateBlock->pIndexData;
2914 /* up ref count on ppindexdata */
2915 if (*ppIndexData) {
2916 IWineD3DIndexBuffer_AddRef(*ppIndexData);
2917 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2918 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
2919 }else{
2920 TRACE("(%p) No index data set\n", This);
2922 TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
2924 return WINED3D_OK;
2927 /*****
2928 * Get / Set Viewports
2929 *****/
2930 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2931 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2933 TRACE("(%p)\n", This);
2934 This->updateStateBlock->changed.viewport = TRUE;
2935 This->updateStateBlock->set.viewport = TRUE;
2936 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2938 /* Handle recording of state blocks */
2939 if (This->isRecordingState) {
2940 TRACE("Recording... not performing anything\n");
2941 return WINED3D_OK;
2943 This->viewport_changed = TRUE;
2945 ENTER_GL();
2947 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2948 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2950 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2951 checkGLcall("glDepthRange");
2952 /* Note: GL requires lower left, DirectX supplies upper left */
2953 /* TODO: replace usage of renderTarget with context management */
2954 glViewport(pViewport->X,
2955 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2956 pViewport->Width, pViewport->Height);
2958 checkGLcall("glViewport");
2960 LEAVE_GL();
2962 return WINED3D_OK;
2966 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2967 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2968 TRACE("(%p)\n", This);
2969 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2970 return WINED3D_OK;
2973 /*****
2974 * Get / Set Render States
2975 * TODO: Verify against dx9 definitions
2976 *****/
2977 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2979 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2980 DWORD OldValue = This->stateBlock->renderState[State];
2982 /* Simple way of referring to either a DWORD or a 4 byte float */
2983 union {
2984 DWORD d;
2985 float f;
2986 } tmpvalue;
2988 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2989 This->updateStateBlock->changed.renderState[State] = TRUE;
2990 This->updateStateBlock->set.renderState[State] = TRUE;
2991 This->updateStateBlock->renderState[State] = Value;
2993 /* Handle recording of state blocks */
2994 if (This->isRecordingState) {
2995 TRACE("Recording... not performing anything\n");
2996 return WINED3D_OK;
2999 ENTER_GL();
3001 switch (State) {
3002 case WINED3DRS_FILLMODE :
3003 switch ((D3DFILLMODE) Value) {
3004 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
3005 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
3006 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
3007 default:
3008 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
3010 checkGLcall("glPolygonMode (fillmode)");
3011 break;
3013 case WINED3DRS_LIGHTING :
3014 if (Value) {
3015 glEnable(GL_LIGHTING);
3016 checkGLcall("glEnable GL_LIGHTING");
3017 } else {
3018 glDisable(GL_LIGHTING);
3019 checkGLcall("glDisable GL_LIGHTING");
3021 break;
3023 case WINED3DRS_ZENABLE :
3024 switch ((D3DZBUFFERTYPE) Value) {
3025 case D3DZB_FALSE:
3026 glDisable(GL_DEPTH_TEST);
3027 checkGLcall("glDisable GL_DEPTH_TEST");
3028 break;
3029 case D3DZB_TRUE:
3030 glEnable(GL_DEPTH_TEST);
3031 checkGLcall("glEnable GL_DEPTH_TEST");
3032 break;
3033 case D3DZB_USEW:
3034 glEnable(GL_DEPTH_TEST);
3035 checkGLcall("glEnable GL_DEPTH_TEST");
3036 FIXME("W buffer is not well handled\n");
3037 break;
3038 default:
3039 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
3041 break;
3043 case WINED3DRS_CULLMODE :
3045 /* If we are culling "back faces with clockwise vertices" then
3046 set front faces to be counter clockwise and enable culling
3047 of back faces */
3048 switch ((D3DCULL) Value) {
3049 case D3DCULL_NONE:
3050 glDisable(GL_CULL_FACE);
3051 checkGLcall("glDisable GL_CULL_FACE");
3052 break;
3053 case D3DCULL_CW:
3054 glEnable(GL_CULL_FACE);
3055 checkGLcall("glEnable GL_CULL_FACE");
3056 if (This->renderUpsideDown) {
3057 glFrontFace(GL_CW);
3058 checkGLcall("glFrontFace GL_CW");
3059 } else {
3060 glFrontFace(GL_CCW);
3061 checkGLcall("glFrontFace GL_CCW");
3063 glCullFace(GL_BACK);
3064 break;
3065 case D3DCULL_CCW:
3066 glEnable(GL_CULL_FACE);
3067 checkGLcall("glEnable GL_CULL_FACE");
3068 if (This->renderUpsideDown) {
3069 glFrontFace(GL_CCW);
3070 checkGLcall("glFrontFace GL_CCW");
3071 } else {
3072 glFrontFace(GL_CW);
3073 checkGLcall("glFrontFace GL_CW");
3075 glCullFace(GL_BACK);
3076 break;
3077 default:
3078 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
3080 break;
3082 case WINED3DRS_SHADEMODE :
3083 switch ((D3DSHADEMODE) Value) {
3084 case D3DSHADE_FLAT:
3085 glShadeModel(GL_FLAT);
3086 checkGLcall("glShadeModel");
3087 break;
3088 case D3DSHADE_GOURAUD:
3089 glShadeModel(GL_SMOOTH);
3090 checkGLcall("glShadeModel");
3091 break;
3092 case D3DSHADE_PHONG:
3093 FIXME("D3DSHADE_PHONG isn't supported?\n");
3095 LEAVE_GL();
3096 return WINED3DERR_INVALIDCALL;
3097 default:
3098 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
3100 break;
3102 case WINED3DRS_DITHERENABLE :
3103 if (Value) {
3104 glEnable(GL_DITHER);
3105 checkGLcall("glEnable GL_DITHER");
3106 } else {
3107 glDisable(GL_DITHER);
3108 checkGLcall("glDisable GL_DITHER");
3110 break;
3112 case WINED3DRS_ZWRITEENABLE :
3113 if (Value) {
3114 glDepthMask(1);
3115 checkGLcall("glDepthMask");
3116 } else {
3117 glDepthMask(0);
3118 checkGLcall("glDepthMask");
3120 break;
3122 case WINED3DRS_ZFUNC :
3124 int glParm = GL_LESS;
3126 switch ((D3DCMPFUNC) Value) {
3127 case D3DCMP_NEVER: glParm=GL_NEVER; break;
3128 case D3DCMP_LESS: glParm=GL_LESS; break;
3129 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
3130 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
3131 case D3DCMP_GREATER: glParm=GL_GREATER; break;
3132 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
3133 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
3134 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
3135 default:
3136 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3138 glDepthFunc(glParm);
3139 checkGLcall("glDepthFunc");
3141 break;
3143 case WINED3DRS_AMBIENT :
3145 float col[4];
3146 D3DCOLORTOGLFLOAT4(Value, col);
3147 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
3148 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
3149 checkGLcall("glLightModel for MODEL_AMBIENT");
3152 break;
3154 case WINED3DRS_ALPHABLENDENABLE :
3155 if (Value) {
3156 glEnable(GL_BLEND);
3157 checkGLcall("glEnable GL_BLEND");
3158 } else {
3159 glDisable(GL_BLEND);
3160 checkGLcall("glDisable GL_BLEND");
3162 break;
3164 case WINED3DRS_SRCBLEND :
3165 case WINED3DRS_DESTBLEND :
3167 int newVal = GL_ZERO;
3168 switch (Value) {
3169 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
3170 case D3DBLEND_ONE : newVal = GL_ONE; break;
3171 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
3172 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
3173 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
3174 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
3175 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
3176 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
3177 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
3178 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
3179 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
3181 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
3182 This->srcBlend = newVal;
3183 This->dstBlend = newVal;
3184 break;
3186 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
3187 This->srcBlend = newVal;
3188 This->dstBlend = newVal;
3189 break;
3190 default:
3191 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
3194 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
3195 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
3196 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
3197 glBlendFunc(This->srcBlend, This->dstBlend);
3199 checkGLcall("glBlendFunc");
3201 break;
3203 case WINED3DRS_ALPHATESTENABLE :
3204 if (Value) {
3205 glEnable(GL_ALPHA_TEST);
3206 checkGLcall("glEnable GL_ALPHA_TEST");
3207 } else {
3208 glDisable(GL_ALPHA_TEST);
3209 checkGLcall("glDisable GL_ALPHA_TEST");
3211 break;
3213 case WINED3DRS_ALPHAFUNC :
3215 int glParm = GL_LESS;
3216 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
3218 switch ((D3DCMPFUNC) Value) {
3219 case D3DCMP_NEVER: glParm = GL_NEVER; break;
3220 case D3DCMP_LESS: glParm = GL_LESS; break;
3221 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
3222 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
3223 case D3DCMP_GREATER: glParm = GL_GREATER; break;
3224 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
3225 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
3226 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
3227 default:
3228 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3230 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
3231 glAlphaFunc(glParm, ref);
3232 This->alphafunc = glParm;
3233 checkGLcall("glAlphaFunc");
3235 break;
3237 case WINED3DRS_ALPHAREF :
3239 int glParm = This->alphafunc;
3240 float ref = 1.0f;
3242 ref = ((float) Value) / 255.0f;
3243 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
3244 glAlphaFunc(glParm, ref);
3245 checkGLcall("glAlphaFunc");
3247 break;
3249 case WINED3DRS_CLIPPLANEENABLE :
3250 case WINED3DRS_CLIPPING :
3252 /* Ensure we only do the changed clip planes */
3253 DWORD enable = 0xFFFFFFFF;
3254 DWORD disable = 0x00000000;
3256 /* If enabling / disabling all */
3257 if (State == WINED3DRS_CLIPPING) {
3258 if (Value) {
3259 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3260 disable = 0x00;
3261 } else {
3262 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3263 enable = 0x00;
3265 } else {
3266 enable = Value & ~OldValue;
3267 disable = ~Value & OldValue;
3270 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
3271 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
3272 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
3273 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
3274 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
3275 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
3277 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
3278 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
3279 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
3280 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
3281 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
3282 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
3284 /** update clipping status */
3285 if (enable) {
3286 This->stateBlock->clip_status.ClipUnion = 0;
3287 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
3288 } else {
3289 This->stateBlock->clip_status.ClipUnion = 0;
3290 This->stateBlock->clip_status.ClipIntersection = 0;
3293 break;
3295 case WINED3DRS_BLENDOP :
3297 int glParm = GL_FUNC_ADD;
3299 switch ((D3DBLENDOP) Value) {
3300 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
3301 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
3302 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3303 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
3304 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
3305 default:
3306 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
3308 TRACE("glBlendEquation(%x)\n", glParm);
3309 glBlendEquation(glParm);
3310 checkGLcall("glBlendEquation");
3312 break;
3314 case WINED3DRS_TEXTUREFACTOR :
3316 unsigned int i;
3318 /* Note the texture color applies to all textures whereas
3319 GL_TEXTURE_ENV_COLOR applies to active only */
3320 float col[4];
3321 D3DCOLORTOGLFLOAT4(Value, col);
3322 /* Set the default alpha blend color */
3323 glBlendColor(col[0], col[1], col[2], col[3]);
3324 checkGLcall("glBlendColor");
3326 /* And now the default texture color as well */
3327 for (i = 0; i < GL_LIMITS(textures); i++) {
3329 /* Note the D3DRS value applies to all textures, but GL has one
3330 per texture, so apply it now ready to be used! */
3331 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3332 GLACTIVETEXTURE(i);
3333 } else if (i>0) {
3334 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3337 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3338 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3341 break;
3343 case WINED3DRS_SPECULARENABLE :
3345 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3346 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3347 specular color. This is wrong:
3348 Separate specular color means the specular colour is maintained separately, whereas
3349 single color means it is merged in. However in both cases they are being used to
3350 some extent.
3351 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3352 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3353 running 1.4 yet!
3355 if (Value) {
3356 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3357 checkGLcall("glMaterialfv");
3358 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3359 glEnable(GL_COLOR_SUM_EXT);
3360 } else {
3361 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3363 checkGLcall("glEnable(GL_COLOR_SUM)");
3364 } else {
3365 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3367 /* for the case of enabled lighting: */
3368 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3369 checkGLcall("glMaterialfv");
3371 /* for the case of disabled lighting: */
3372 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3373 glDisable(GL_COLOR_SUM_EXT);
3374 } else {
3375 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3377 checkGLcall("glDisable(GL_COLOR_SUM)");
3380 break;
3382 case WINED3DRS_STENCILENABLE :
3383 if (Value) {
3384 glEnable(GL_STENCIL_TEST);
3385 checkGLcall("glEnable GL_STENCIL_TEST");
3386 } else {
3387 glDisable(GL_STENCIL_TEST);
3388 checkGLcall("glDisable GL_STENCIL_TEST");
3390 break;
3392 case WINED3DRS_STENCILFUNC :
3394 GLint func;
3395 GLint ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3396 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3398 func = GL_ALWAYS;
3399 switch ((D3DCMPFUNC)Value) {
3400 case D3DCMP_NEVER: func = GL_NEVER; break;
3401 case D3DCMP_LESS: func = GL_LESS; break;
3402 case D3DCMP_EQUAL: func = GL_EQUAL; break;
3403 case D3DCMP_LESSEQUAL: func = GL_LEQUAL; break;
3404 case D3DCMP_GREATER: func = GL_GREATER; break;
3405 case D3DCMP_NOTEQUAL: func = GL_NOTEQUAL; break;
3406 case D3DCMP_GREATEREQUAL: func = GL_GEQUAL; break;
3407 case D3DCMP_ALWAYS: func = GL_ALWAYS; break;
3408 default:
3409 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3411 This->stencilfunc = func;
3412 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3413 #if 0 /* Don't use OpenGL 2.0 calls for now */
3414 if(GL_EXTCALL(glStencilFuncSeparate)) {
3415 GL_EXTCALL(glStencilFuncSeparate(GL_FRONT, func, ref, mask));
3416 checkGLcall("glStencilFuncSeparate(GL_FRONT,...)");
3418 else
3419 #endif
3420 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3421 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3422 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3423 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
3424 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
3425 glStencilFunc(func, ref, mask);
3426 checkGLcall("glStencilFunc(...)");
3428 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3429 GL_EXTCALL(glStencilFuncSeparateATI(GL_FRONT, func, ref, mask));
3430 checkGLcall("glStencilFuncSeparateATI(GL_FRONT,...)");
3431 } else {
3432 TRACE("Separate stencil function not supported on this version of opengl");
3433 glStencilFunc(func, ref, mask);
3434 checkGLcall("glStencilFunc(...)");
3436 } else {
3437 glStencilFunc(func, ref, mask);
3438 checkGLcall("glStencilFunc(...)");
3440 break;
3442 case WINED3DRS_STENCILREF :
3444 int glParm = This->stencilfunc;
3445 int ref = 0;
3446 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3448 ref = Value;
3449 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3450 glStencilFunc(glParm, ref, mask);
3451 checkGLcall("glStencilFunc");
3453 break;
3455 case WINED3DRS_STENCILMASK :
3457 int glParm = This->stencilfunc;
3458 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3459 GLuint mask = Value;
3461 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3462 glStencilFunc(glParm, ref, mask);
3463 checkGLcall("glStencilFunc");
3465 break;
3467 case WINED3DRS_STENCILFAIL :
3468 case WINED3DRS_STENCILZFAIL :
3469 case WINED3DRS_STENCILPASS :
3471 GLint stencilFail;
3472 GLint depthFail;
3473 GLint stencilPass;
3475 GLint action = StencilOp(Value);
3477 glGetIntegerv(GL_STENCIL_FAIL, &stencilFail);
3478 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &depthFail);
3479 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &stencilPass);
3481 if(WINED3DRS_STENCILFAIL == State) {
3482 stencilFail = action;
3484 else if(WINED3DRS_STENCILZFAIL == State) {
3485 depthFail = action;
3487 else if(WINED3DRS_STENCILPASS == State) {
3488 stencilPass = action;
3491 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3492 #if 0 /* Don't use OpenGL 2.0 calls for now */
3493 if(GL_EXTCALL(glStencilOpSeparate)) {
3494 GL_EXTCALL(glStencilOpSeparate(GL_FRONT, stencilFail, depthFail, stencilPass));
3495 checkGLcall("glStencilOpSeparate(GL_FRONT,...)");
3497 else
3498 #endif
3499 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3500 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3501 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3502 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
3503 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
3504 glStencilOp(stencilFail, depthFail, stencilPass);
3505 checkGLcall("glStencilOp(...)");
3507 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3508 GL_EXTCALL(glStencilOpSeparateATI(GL_FRONT, stencilFail, depthFail, stencilPass));
3509 checkGLcall("glStencilOpSeparateATI(GL_FRONT,...)");
3510 } else {
3511 TRACE("Separate stencil operation not supported on this version of opengl");
3512 glStencilOp(stencilFail, depthFail, stencilPass);
3513 checkGLcall("glStencilOp(...)");
3515 } else {
3516 glStencilOp(stencilFail, depthFail, stencilPass);
3517 checkGLcall("glStencilOp(...)");
3519 break;
3521 case WINED3DRS_STENCILWRITEMASK :
3523 glStencilMask(Value);
3524 TRACE("glStencilMask(%lu)\n", Value);
3525 checkGLcall("glStencilMask");
3527 break;
3529 case WINED3DRS_FOGENABLE :
3531 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
3532 glEnable(GL_FOG);
3533 checkGLcall("glEnable GL_FOG");
3534 } else {
3535 glDisable(GL_FOG);
3536 checkGLcall("glDisable GL_FOG");
3539 break;
3541 case WINED3DRS_RANGEFOGENABLE :
3543 if (Value) {
3544 TRACE("Enabled RANGEFOG");
3545 } else {
3546 TRACE("Disabled RANGEFOG");
3549 break;
3551 case WINED3DRS_FOGCOLOR :
3553 float col[4];
3554 D3DCOLORTOGLFLOAT4(Value, col);
3555 /* Set the default alpha blend color */
3556 glFogfv(GL_FOG_COLOR, &col[0]);
3557 checkGLcall("glFog GL_FOG_COLOR");
3559 break;
3561 case WINED3DRS_FOGTABLEMODE :
3563 glHint(GL_FOG_HINT, GL_NICEST);
3564 switch (Value) {
3565 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3566 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3567 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3568 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3569 default:
3570 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3572 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3573 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3576 break;
3578 case WINED3DRS_FOGVERTEXMODE :
3580 glHint(GL_FOG_HINT, GL_FASTEST);
3581 switch (Value) {
3582 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3583 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3584 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3585 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3586 default:
3587 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3589 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3590 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
3593 break;
3595 case WINED3DRS_FOGSTART :
3597 tmpvalue.d = Value;
3598 glFogfv(GL_FOG_START, &tmpvalue.f);
3599 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3600 TRACE("Fog Start == %f\n", tmpvalue.f);
3602 break;
3604 case WINED3DRS_FOGEND :
3606 tmpvalue.d = Value;
3607 glFogfv(GL_FOG_END, &tmpvalue.f);
3608 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3609 TRACE("Fog End == %f\n", tmpvalue.f);
3611 break;
3613 case WINED3DRS_FOGDENSITY :
3615 tmpvalue.d = Value;
3616 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3617 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3619 break;
3621 case WINED3DRS_VERTEXBLEND :
3623 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3624 TRACE("Vertex Blending state to %ld\n", Value);
3626 break;
3628 case WINED3DRS_TWEENFACTOR :
3630 tmpvalue.d = Value;
3631 This->updateStateBlock->tween_factor = tmpvalue.f;
3632 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3634 break;
3636 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
3638 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3640 break;
3642 case WINED3DRS_COLORVERTEX :
3643 case WINED3DRS_DIFFUSEMATERIALSOURCE :
3644 case WINED3DRS_SPECULARMATERIALSOURCE :
3645 case WINED3DRS_AMBIENTMATERIALSOURCE :
3646 case WINED3DRS_EMISSIVEMATERIALSOURCE :
3648 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3650 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3651 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3652 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3653 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3654 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3655 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3657 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3658 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3659 Parm = GL_AMBIENT_AND_DIFFUSE;
3660 } else {
3661 Parm = GL_DIFFUSE;
3663 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3664 Parm = GL_AMBIENT;
3665 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3666 Parm = GL_EMISSION;
3667 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3668 Parm = GL_SPECULAR;
3669 } else {
3670 Parm = -1;
3673 if (Parm == -1) {
3674 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3675 } else {
3676 This->tracking_color = NEEDS_TRACKING;
3677 This->tracking_parm = Parm;
3680 } else {
3681 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3684 break;
3686 case WINED3DRS_LINEPATTERN :
3688 union {
3689 DWORD d;
3690 D3DLINEPATTERN lp;
3691 } tmppattern;
3692 tmppattern.d = Value;
3694 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3696 if (tmppattern.lp.wRepeatFactor) {
3697 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3698 checkGLcall("glLineStipple(repeat, linepattern)");
3699 glEnable(GL_LINE_STIPPLE);
3700 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3701 } else {
3702 glDisable(GL_LINE_STIPPLE);
3703 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3706 break;
3708 case WINED3DRS_ZBIAS : /* D3D8 only */
3710 if (Value) {
3711 tmpvalue.d = Value;
3712 TRACE("ZBias value %f\n", tmpvalue.f);
3713 glPolygonOffset(0, -tmpvalue.f);
3714 checkGLcall("glPolygonOffset(0, -Value)");
3715 glEnable(GL_POLYGON_OFFSET_FILL);
3716 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3717 glEnable(GL_POLYGON_OFFSET_LINE);
3718 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3719 glEnable(GL_POLYGON_OFFSET_POINT);
3720 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3721 } else {
3722 glDisable(GL_POLYGON_OFFSET_FILL);
3723 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3724 glDisable(GL_POLYGON_OFFSET_LINE);
3725 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3726 glDisable(GL_POLYGON_OFFSET_POINT);
3727 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3730 break;
3732 case WINED3DRS_NORMALIZENORMALS :
3733 if (Value) {
3734 glEnable(GL_NORMALIZE);
3735 checkGLcall("glEnable(GL_NORMALIZE);");
3736 } else {
3737 glDisable(GL_NORMALIZE);
3738 checkGLcall("glDisable(GL_NORMALIZE);");
3740 break;
3742 case WINED3DRS_POINTSIZE :
3743 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
3744 tmpvalue.d = Value;
3745 TRACE("Set point size to %f\n", tmpvalue.f);
3746 glPointSize(tmpvalue.f);
3747 checkGLcall("glPointSize(...);");
3748 break;
3750 case WINED3DRS_POINTSIZE_MIN :
3751 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3752 tmpvalue.d = Value;
3753 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3754 checkGLcall("glPointParameterfEXT(...);");
3755 } else {
3756 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3758 break;
3760 case WINED3DRS_POINTSIZE_MAX :
3761 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3762 tmpvalue.d = Value;
3763 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3764 checkGLcall("glPointParameterfEXT(...);");
3765 } else {
3766 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3768 break;
3770 case WINED3DRS_POINTSCALE_A :
3771 case WINED3DRS_POINTSCALE_B :
3772 case WINED3DRS_POINTSCALE_C :
3773 case WINED3DRS_POINTSCALEENABLE :
3776 * POINTSCALEENABLE controls how point size value is treated. If set to
3777 * true, the point size is scaled with respect to height of viewport.
3778 * When set to false point size is in pixels.
3780 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
3783 /* Default values */
3784 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3787 * Minimum valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
3788 * This means that OpenGL will clamp really small point sizes to 1.0f.
3789 * To correct for this we need to multiply by the scale factor when sizes
3790 * are less than 1.0f. scale_factor = 1.0f / point_size.
3792 GLfloat pointSize = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSIZE]);
3793 if(pointSize > 0.0f) {
3794 GLfloat scaleFactor;
3796 if(pointSize < 1.0f) {
3797 scaleFactor = pointSize * pointSize;
3798 } else {
3799 scaleFactor = 1.0f;
3802 if(This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3803 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]) /
3804 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3805 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]) /
3806 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3807 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) /
3808 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3812 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
3813 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
3814 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
3816 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3817 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3818 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
3819 } else {
3820 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
3822 break;
3824 case WINED3DRS_COLORWRITEENABLE :
3826 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3827 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3828 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3829 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3830 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3831 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3832 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3833 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3834 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3835 checkGLcall("glColorMask(...)");
3837 break;
3839 case WINED3DRS_LOCALVIEWER :
3841 GLint state = (Value) ? 1 : 0;
3842 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3843 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3845 break;
3847 case WINED3DRS_LASTPIXEL :
3849 if (Value) {
3850 TRACE("Last Pixel Drawing Enabled\n");
3851 } else {
3852 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3855 break;
3857 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3859 if (Value) {
3860 TRACE("Software Processing Enabled\n");
3861 } else {
3862 TRACE("Software Processing Disabled\n");
3865 break;
3867 /** not supported */
3868 case WINED3DRS_ZVISIBLE :
3870 LEAVE_GL();
3871 return WINED3DERR_INVALIDCALL;
3873 case WINED3DRS_POINTSPRITEENABLE :
3875 /* TODO: NV_POINT_SPRITE */
3876 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
3877 TRACE("Point sprites not supported\n");
3878 break;
3882 * Point sprites are always enabled. Value controls texture coordinate
3883 * replacement mode. Must be set true for point sprites to use
3884 * textures.
3886 glEnable(GL_POINT_SPRITE_ARB);
3887 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
3889 if (Value) {
3890 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
3891 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, TRUE)");
3892 } else {
3893 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, FALSE);
3894 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, FALSE)");
3896 break;
3898 case WINED3DRS_EDGEANTIALIAS :
3900 if(Value) {
3901 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3902 glEnable(GL_BLEND);
3903 checkGLcall("glEnable(GL_BLEND)");
3904 glEnable(GL_LINE_SMOOTH);
3905 checkGLcall("glEnable(GL_LINE_SMOOTH)");
3906 } else {
3907 glDisable(GL_BLEND);
3908 checkGLcall("glDisable(GL_BLEND)");
3909 glDisable(GL_LINE_SMOOTH);
3910 checkGLcall("glDisable(GL_LINE_SMOOTH)");
3912 break;
3914 case WINED3DRS_WRAP0 :
3915 case WINED3DRS_WRAP1 :
3916 case WINED3DRS_WRAP2 :
3917 case WINED3DRS_WRAP3 :
3918 case WINED3DRS_WRAP4 :
3919 case WINED3DRS_WRAP5 :
3920 case WINED3DRS_WRAP6 :
3921 case WINED3DRS_WRAP7 :
3922 case WINED3DRS_WRAP8 :
3923 case WINED3DRS_WRAP9 :
3924 case WINED3DRS_WRAP10 :
3925 case WINED3DRS_WRAP11 :
3926 case WINED3DRS_WRAP12 :
3927 case WINED3DRS_WRAP13 :
3928 case WINED3DRS_WRAP14 :
3929 case WINED3DRS_WRAP15 :
3931 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
3932 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
3933 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
3934 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
3935 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
3937 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
3939 TRACE("(%p)->(%s,%ld) Texture wraping not yet supported\n",This, debug_d3drenderstate(State), Value);
3940 break;
3941 case WINED3DRS_MULTISAMPLEANTIALIAS :
3943 if (!GL_SUPPORT(ARB_MULTISAMPLE)) {
3944 TRACE("Multisample antialiasing not supported\n");
3945 break;
3948 if(Value) {
3949 glEnable(GL_MULTISAMPLE_ARB);
3950 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
3951 } else {
3952 glDisable(GL_MULTISAMPLE_ARB);
3953 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
3955 break;
3957 case WINED3DRS_SCISSORTESTENABLE :
3959 if(Value) {
3960 glEnable(GL_SCISSOR_TEST);
3961 checkGLcall("glEnable(GL_SCISSOR_TEST)");
3962 } else {
3963 glDisable(GL_SCISSOR_TEST);
3964 checkGLcall("glDisable(GL_SCISSOR_TEST)");
3966 break;
3968 case WINED3DRS_SLOPESCALEDEPTHBIAS :
3970 if(Value) {
3971 tmpvalue.d = Value;
3972 glEnable(GL_POLYGON_OFFSET_FILL);
3973 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
3974 glPolygonOffset(tmpvalue.f, *((float*)&This->stateBlock->renderState[WINED3DRS_DEPTHBIAS]));
3975 checkGLcall("glPolygonOffset(...)");
3976 } else {
3977 glDisable(GL_POLYGON_OFFSET_FILL);
3978 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
3980 break;
3982 case WINED3DRS_ANTIALIASEDLINEENABLE :
3984 if(Value) {
3985 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3986 glEnable(GL_BLEND);
3987 checkGLcall("glEnable(GL_BLEND)");
3988 glEnable(GL_LINE_SMOOTH);
3989 checkGLcall("glEnable(GL_LINE_SMOOTH)");
3990 } else {
3991 glDisable(GL_BLEND);
3992 checkGLcall("glDisable(GL_BLEND)");
3993 glDisable(GL_LINE_SMOOTH);
3994 checkGLcall("glDisable(GL_LINE_SMOOTH)");
3996 break;
3998 case WINED3DRS_TWOSIDEDSTENCILMODE :
4000 if(Value) {
4001 TRACE("Two-sided stencil mode enabled\n");
4002 } else {
4003 TRACE("Two-sided stencil mode disabled\n");
4005 break;
4007 case WINED3DRS_CCW_STENCILFAIL :
4008 case WINED3DRS_CCW_STENCILZFAIL :
4009 case WINED3DRS_CCW_STENCILPASS :
4011 GLint stencilFail;
4012 GLint depthFail;
4013 GLint stencilPass;
4015 GLint action = StencilOp(Value);
4017 glGetIntegerv(GL_STENCIL_BACK_FAIL, &stencilFail);
4018 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &depthFail);
4019 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS, &stencilPass);
4021 if(WINED3DRS_CCW_STENCILFAIL == State) {
4022 stencilFail = action;
4024 else if(WINED3DRS_CCW_STENCILZFAIL == State) {
4025 depthFail = action;
4027 else if(WINED3DRS_CCW_STENCILPASS == State) {
4028 stencilPass = action;
4031 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
4032 #if 0 /* Don't use OpenGL 2.0 calls for now */
4033 if(GL_EXTCALL(glStencilOpSeparate)) {
4034 GL_EXTCALL(glStencilOpSeparate(GL_BACK, stencilFail, depthFail, stencilPass));
4035 checkGLcall("glStencilOpSeparate(GL_BACK,...)");
4037 else
4038 #endif
4039 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
4040 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
4041 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
4042 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
4043 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
4044 glStencilOp(stencilFail, depthFail, stencilPass);
4045 checkGLcall("glStencilOp(...)");
4047 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
4048 GL_EXTCALL(glStencilOpSeparateATI(GL_BACK, stencilFail, depthFail, stencilPass));
4049 checkGLcall("glStencilOpSeparateATI(GL_BACK,...)");
4050 } else {
4051 TRACE("Separate stencil operation not supported on this version of opengl");
4052 glStencilOp(stencilFail, depthFail, stencilPass);
4053 checkGLcall("glStencilOp(...)");
4055 } else {
4056 glStencilOp(stencilFail, depthFail, stencilPass);
4057 checkGLcall("glStencilOp(...)");
4059 break;
4061 case WINED3DRS_CCW_STENCILFUNC :
4063 GLint func;
4064 GLint ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
4065 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
4067 func = GL_ALWAYS;
4068 switch ((D3DCMPFUNC)Value) {
4069 case D3DCMP_NEVER: func = GL_NEVER; break;
4070 case D3DCMP_LESS: func = GL_LESS; break;
4071 case D3DCMP_EQUAL: func = GL_EQUAL; break;
4072 case D3DCMP_LESSEQUAL: func = GL_LEQUAL; break;
4073 case D3DCMP_GREATER: func = GL_GREATER; break;
4074 case D3DCMP_NOTEQUAL: func = GL_NOTEQUAL; break;
4075 case D3DCMP_GREATEREQUAL: func = GL_GEQUAL; break;
4076 case D3DCMP_ALWAYS: func = GL_ALWAYS; break;
4077 default:
4078 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
4080 This->stencilfunc = func;
4081 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
4082 #if 0 /* Don't use OpenGL 2.0 calls for now */
4083 if(GL_EXTCALL(glStencilFuncSeparate)) {
4084 GL_EXTCALL(glStencilFuncSeparate(GL_BACK, func, ref, mask));
4085 checkGLcall("glStencilFuncSeparate(GL_BACK,...)");
4087 else
4088 #endif
4089 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
4090 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
4091 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
4092 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
4093 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
4094 glStencilFunc(func, ref, mask);
4095 checkGLcall("glStencilFunc(...)");
4097 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
4098 GL_EXTCALL(glStencilFuncSeparateATI(GL_BACK, func, ref, mask));
4099 checkGLcall("glStencilFuncSeparateATI(GL_BACK,...)");
4100 } else {
4101 TRACE("Separate stencil function not supported on this version of opengl");
4102 glStencilFunc(func, ref, mask);
4103 checkGLcall("glStencilFunc(...)");
4105 } else {
4106 glStencilFunc(func, ref, mask);
4107 checkGLcall("glStencilFunc(...)");
4109 break;
4111 case WINED3DRS_DEPTHBIAS :
4113 if(Value) {
4114 tmpvalue.d = Value;
4115 glEnable(GL_POLYGON_OFFSET_FILL);
4116 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4117 glPolygonOffset(*((float*)&This->stateBlock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS]), tmpvalue.f);
4118 checkGLcall("glPolygonOffset(...)");
4119 } else {
4120 glDisable(GL_POLYGON_OFFSET_FILL);
4121 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4123 break;
4126 case WINED3DRS_TEXTUREPERSPECTIVE :
4128 if (Value)
4129 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
4130 else
4131 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
4132 break;
4135 case WINED3DRS_STIPPLEDALPHA :
4137 if (Value)
4138 ERR(" Stippled Alpha not supported yet.\n");
4139 break;
4141 case WINED3DRS_ANTIALIAS :
4143 if (Value)
4144 ERR(" Antialias not supported yet.\n");
4145 break;
4147 default:
4148 FIXME("(%p)->(%s,%ld) not handled yet\n", This, debug_d3drenderstate(State), Value);
4151 LEAVE_GL();
4153 return WINED3D_OK;
4156 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
4157 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4158 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
4159 *pValue = This->stateBlock->renderState[State];
4160 return WINED3D_OK;
4163 /*****
4164 * Get / Set Sampler States
4165 * TODO: Verify against dx9 definitions
4166 *****/
4168 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
4169 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4171 * SetSampler is designed to allow for more than the standard up to 8 textures
4172 * and Geforce has stopped supporting more than 6 standard textures in openGL.
4173 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
4175 * http://developer.nvidia.com/object/General_FAQ.html#t6
4177 * There are two new settings for GForce
4178 * the sampler one:
4179 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
4180 * and the texture one:
4181 * GL_MAX_TEXTURE_COORDS_ARB.
4182 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
4183 ******************/
4184 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
4185 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
4187 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
4188 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE, Sampler, Type);
4189 return WINED3DERR_INVALIDCALL;
4191 TRACE("Setting sampler %ld %d to %ld\n", Sampler, Type, Value);
4192 This->updateStateBlock->samplerState[Sampler][Type] = Value;
4193 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
4194 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
4196 /* Handle recording of state blocks */
4197 if (This->isRecordingState) {
4198 TRACE("Recording... not performing anything\n");
4199 return WINED3D_OK;
4202 return WINED3D_OK;
4205 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
4206 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4207 /** TODO: check that sampler is in range **/
4208 *Value = This->updateStateBlock->samplerState[Sampler][Type];
4209 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
4211 return WINED3D_OK;
4214 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
4215 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4216 ENTER_GL();
4218 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4219 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4220 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
4221 LEAVE_GL();
4223 return WINED3D_OK;
4226 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
4227 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4228 GLint scissorBox[4];
4230 ENTER_GL();
4231 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4232 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
4233 pRect->left = scissorBox[1];
4234 pRect->top = scissorBox[2];
4235 pRect->right = scissorBox[1] + scissorBox[3];
4236 pRect->bottom = scissorBox[2] + scissorBox[4];
4237 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4238 LEAVE_GL();
4239 return WINED3D_OK;
4242 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
4243 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4244 IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
4246 TRACE("(%p) : pDecl=%p\n", This, pDecl);
4248 This->updateStateBlock->vertexDecl = pDecl;
4249 This->updateStateBlock->changed.vertexDecl = TRUE;
4250 This->updateStateBlock->set.vertexDecl = TRUE;
4252 if (This->isRecordingState) {
4253 TRACE("Recording... not performing anything\n");
4256 if (NULL != pDecl) {
4257 IWineD3DVertexDeclaration_AddRef(pDecl);
4259 if (NULL != oldDecl) {
4260 IWineD3DVertexDeclaration_Release(oldDecl);
4262 return WINED3D_OK;
4265 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
4266 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4268 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
4270 *ppDecl = This->stateBlock->vertexDecl;
4271 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
4272 return WINED3D_OK;
4275 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
4276 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4277 IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
4279 This->updateStateBlock->vertexShader = pShader;
4280 This->updateStateBlock->changed.vertexShader = TRUE;
4281 This->updateStateBlock->set.vertexShader = TRUE;
4283 if (This->isRecordingState) {
4284 TRACE("Recording... not performing anything\n");
4287 if (NULL != pShader) {
4288 IWineD3DVertexShader_AddRef(pShader);
4290 if (NULL != oldShader) {
4291 IWineD3DVertexShader_Release(oldShader);
4294 if (pShader != NULL && ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration != NULL) {
4295 TRACE("(%p) : setting vertexDeclaration(%p)\n", This, ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration);
4296 IWineD3DDevice_SetVertexDeclaration(iface, ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration);
4299 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4301 * TODO: merge HAL shaders context switching from prototype
4303 return WINED3D_OK;
4306 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
4307 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4309 if (NULL == ppShader) {
4310 return WINED3DERR_INVALIDCALL;
4312 *ppShader = This->stateBlock->vertexShader;
4313 if( NULL != *ppShader)
4314 IWineD3DVertexShader_AddRef(*ppShader);
4316 TRACE("(%p) : returning %p\n", This, *ppShader);
4317 return WINED3D_OK;
4320 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4321 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4323 int i;
4324 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4326 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4327 iface, dstData, srcData, type, start, count, registersize);
4329 if (type != WINESHADERCNST_NONE) {
4330 if (srcData == NULL || cnt < 0) {
4331 return WINED3DERR_INVALIDCALL;
4334 CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
4337 for (i = start; i < cnt + start; ++i) {
4338 This->updateStateBlock->changed.vertexShaderConstants[i] = TRUE;
4339 This->updateStateBlock->set.vertexShaderConstants[i] = TRUE;
4340 This->updateStateBlock->vertexShaderConstantT[i] = type;
4343 return WINED3D_OK;
4346 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4347 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4349 int i;
4350 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4352 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4353 iface, dstData, srcData, type, start, count, registersize);
4355 /* Verify that the requested shader constant was populated with the correct type */
4356 for (i = start; i < cnt + start; ++i) {
4357 if (This->updateStateBlock->vertexShaderConstantT[i] != type) {
4358 TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning WINED3DERR_INVALIDCALL\n",
4359 This, type, This->updateStateBlock->vertexShaderConstantT[i]);
4360 return WINED3DERR_INVALIDCALL;
4364 if (dstData == NULL || cnt < 0) {
4365 return WINED3DERR_INVALIDCALL;
4368 CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
4370 return WINED3D_OK;
4373 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
4374 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4376 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4377 This->updateStateBlock->vertexShaderConstantB,
4378 pConstantData,
4379 WINESHADERCNST_BOOL,
4380 StartRegister,
4381 BoolCount,
4382 sizeof(*pConstantData));
4385 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
4386 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4388 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4389 pConstantData,
4390 This->updateStateBlock->vertexShaderConstantB,
4391 WINESHADERCNST_BOOL,
4392 StartRegister,
4393 BoolCount,
4394 sizeof(*pConstantData));
4397 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
4398 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4400 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4401 This->updateStateBlock->vertexShaderConstantI,
4402 pConstantData,
4403 WINESHADERCNST_INTEGER,
4404 StartRegister,
4405 Vector4iCount,
4406 4 * sizeof(*pConstantData));
4409 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
4410 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4412 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4413 pConstantData,
4414 This->updateStateBlock->vertexShaderConstantI,
4415 WINESHADERCNST_INTEGER,
4416 StartRegister,
4417 Vector4iCount,
4418 4 * sizeof(*pConstantData));
4422 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
4423 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4425 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4426 This->updateStateBlock->vertexShaderConstantF,
4427 pConstantData,
4428 WINESHADERCNST_FLOAT,
4429 StartRegister,
4430 Vector4fCount,
4431 4 * sizeof(*pConstantData));
4434 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
4435 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4437 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4438 pConstantData,
4439 This->updateStateBlock->vertexShaderConstantF,
4440 WINESHADERCNST_FLOAT,
4441 StartRegister,
4442 Vector4fCount,
4443 4 * sizeof(*pConstantData));
4446 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
4447 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4448 NULL,
4449 NULL,
4450 WINESHADERCNST_NONE,
4451 StartRegister,
4452 VectorNCount,
4456 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
4457 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4458 IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader;
4459 This->updateStateBlock->pixelShader = pShader;
4460 This->updateStateBlock->changed.pixelShader = TRUE;
4461 This->updateStateBlock->set.pixelShader = TRUE;
4463 /* Handle recording of state blocks */
4464 if (This->isRecordingState) {
4465 TRACE("Recording... not performing anything\n");
4468 if (NULL != pShader) {
4469 IWineD3DPixelShader_AddRef(pShader);
4471 if (NULL != oldShader) {
4472 IWineD3DPixelShader_Release(oldShader);
4475 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4477 * TODO: merge HAL shaders context switching from prototype
4479 return WINED3D_OK;
4482 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
4483 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4485 if (NULL == ppShader) {
4486 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
4487 return WINED3DERR_INVALIDCALL;
4490 *ppShader = This->stateBlock->pixelShader;
4491 if (NULL != *ppShader) {
4492 IWineD3DPixelShader_AddRef(*ppShader);
4494 TRACE("(%p) : returning %p\n", This, *ppShader);
4495 return WINED3D_OK;
4498 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4499 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4501 int i;
4502 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4504 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4505 iface, dstData, srcData, type, start, count, registersize);
4507 if (type != WINESHADERCNST_NONE) {
4508 if (srcData == NULL || cnt < 0) {
4509 return WINED3DERR_INVALIDCALL;
4512 CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
4515 for (i = start; i < cnt + start; ++i) {
4516 This->updateStateBlock->changed.pixelShaderConstants[i] = TRUE;
4517 This->updateStateBlock->set.pixelShaderConstants[i] = TRUE;
4518 This->updateStateBlock->pixelShaderConstantT[i] = type;
4521 return WINED3D_OK;
4524 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4525 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4527 int i;
4528 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4530 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4531 iface, dstData, srcData, type, start, count, registersize);
4533 /* Verify that the requested shader constant was populated with the correct type */
4534 for (i = start; i < cnt + start; ++i) {
4535 if (This->updateStateBlock->pixelShaderConstantT[i] != type) {
4536 TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning WINED3DERR_INVALIDCALL\n",
4537 This, type, This->updateStateBlock->pixelShaderConstantT[i]);
4538 return WINED3DERR_INVALIDCALL;
4542 if (dstData == NULL || cnt < 0) {
4543 return WINED3DERR_INVALIDCALL;
4546 CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
4548 return WINED3D_OK;
4551 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
4552 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4554 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4555 This->updateStateBlock->pixelShaderConstantB,
4556 pConstantData,
4557 WINESHADERCNST_BOOL,
4558 StartRegister,
4559 BoolCount,
4560 sizeof(*pConstantData));
4563 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
4564 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4566 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4567 pConstantData,
4568 This->updateStateBlock->pixelShaderConstantB,
4569 WINESHADERCNST_BOOL,
4570 StartRegister,
4571 BoolCount,
4572 sizeof(*pConstantData));
4575 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
4576 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4578 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4579 This->updateStateBlock->pixelShaderConstantI,
4580 pConstantData,
4581 WINESHADERCNST_INTEGER,
4582 StartRegister,
4583 Vector4iCount,
4584 4 * sizeof(*pConstantData));
4587 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
4588 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4590 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4591 pConstantData,
4592 This->updateStateBlock->pixelShaderConstantI,
4593 WINESHADERCNST_INTEGER,
4594 StartRegister,
4595 Vector4iCount,
4596 4 * sizeof(*pConstantData));
4599 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
4600 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4602 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4603 This->updateStateBlock->pixelShaderConstantF,
4604 pConstantData,
4605 WINESHADERCNST_FLOAT,
4606 StartRegister,
4607 Vector4fCount,
4608 4 * sizeof(*pConstantData));
4611 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
4612 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4614 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4615 pConstantData,
4616 This->updateStateBlock->pixelShaderConstantF,
4617 WINESHADERCNST_FLOAT,
4618 StartRegister,
4619 Vector4fCount,
4620 4 * sizeof(*pConstantData));
4623 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
4624 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4625 NULL,
4626 NULL,
4627 WINESHADERCNST_NONE,
4628 StartRegister,
4629 VectorNCount,
4633 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
4634 static HRESULT
4635 process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, WineDirect3DVertexStridedData *lpStrideData, DWORD SrcFVF, IWineD3DVertexBufferImpl *dest, DWORD dwFlags) {
4636 char *dest_ptr;
4637 unsigned int i;
4638 DWORD DestFVF = dest->fvf;
4639 D3DVIEWPORT9 vp;
4640 D3DMATRIX mat, proj_mat, view_mat, world_mat;
4641 BOOL doClip;
4642 int numTextures;
4644 if (SrcFVF & D3DFVF_NORMAL) {
4645 WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
4648 if ( (SrcFVF & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
4649 ERR("Source has no position mask\n");
4650 return WINED3DERR_INVALIDCALL;
4653 if (dest->resource.allocatedMemory == NULL) {
4654 ERR("Destination buffer has no memory allocated\n");
4655 return WINED3DERR_INVALIDCALL;
4658 /* Should I clip?
4659 * a) D3DRS_CLIPPING is enabled
4660 * b) WINED3DVOP_CLIP is passed
4662 if(This->stateBlock->renderState[WINED3DRS_CLIPPING] == TRUE) {
4663 static BOOL warned = FALSE;
4665 * The clipping code is not quite correct. Some things need
4666 * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
4667 * so disable clipping for now.
4668 * (The graphics in Half-Life are broken, and my processvertices
4669 * test crashes with IDirect3DDevice3)
4670 doClip = TRUE;
4672 doClip = FALSE;
4673 if(!warned) {
4674 warned = TRUE;
4675 FIXME("Clipping is broken and disabled for now\n");
4677 } else doClip = FALSE;
4678 dest_ptr = ((char *) dest->resource.allocatedMemory) + dwDestIndex * get_flexible_vertex_size(DestFVF);
4680 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
4681 D3DTS_VIEW,
4682 &view_mat);
4683 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
4684 D3DTS_PROJECTION,
4685 &proj_mat);
4686 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
4687 D3DTS_WORLDMATRIX(0),
4688 &world_mat);
4690 TRACE("View mat: \n");
4691 TRACE("%f %f %f %f\n", view_mat.u.s._11, view_mat.u.s._12, view_mat.u.s._13, view_mat.u.s._14); \
4692 TRACE("%f %f %f %f\n", view_mat.u.s._21, view_mat.u.s._22, view_mat.u.s._23, view_mat.u.s._24); \
4693 TRACE("%f %f %f %f\n", view_mat.u.s._31, view_mat.u.s._32, view_mat.u.s._33, view_mat.u.s._34); \
4694 TRACE("%f %f %f %f\n", view_mat.u.s._41, view_mat.u.s._42, view_mat.u.s._43, view_mat.u.s._44); \
4696 TRACE("Proj mat: \n");
4697 TRACE("%f %f %f %f\n", proj_mat.u.s._11, proj_mat.u.s._12, proj_mat.u.s._13, proj_mat.u.s._14); \
4698 TRACE("%f %f %f %f\n", proj_mat.u.s._21, proj_mat.u.s._22, proj_mat.u.s._23, proj_mat.u.s._24); \
4699 TRACE("%f %f %f %f\n", proj_mat.u.s._31, proj_mat.u.s._32, proj_mat.u.s._33, proj_mat.u.s._34); \
4700 TRACE("%f %f %f %f\n", proj_mat.u.s._41, proj_mat.u.s._42, proj_mat.u.s._43, proj_mat.u.s._44); \
4702 TRACE("World mat: \n");
4703 TRACE("%f %f %f %f\n", world_mat.u.s._11, world_mat.u.s._12, world_mat.u.s._13, world_mat.u.s._14); \
4704 TRACE("%f %f %f %f\n", world_mat.u.s._21, world_mat.u.s._22, world_mat.u.s._23, world_mat.u.s._24); \
4705 TRACE("%f %f %f %f\n", world_mat.u.s._31, world_mat.u.s._32, world_mat.u.s._33, world_mat.u.s._34); \
4706 TRACE("%f %f %f %f\n", world_mat.u.s._41, world_mat.u.s._42, world_mat.u.s._43, world_mat.u.s._44); \
4708 /* Get the viewport */
4709 IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
4710 TRACE("Viewport: X=%ld, Y=%ld, Width=%ld, Height=%ld, MinZ=%f, MaxZ=%f\n",
4711 vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
4713 multiply_matrix(&mat,&view_mat,&world_mat);
4714 multiply_matrix(&mat,&proj_mat,&mat);
4716 numTextures = (DestFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
4718 for (i = 0; i < dwCount; i+= 1) {
4719 unsigned int tex_index;
4721 if ( ((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZ ) ||
4722 ((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW ) ) {
4723 /* The position first */
4724 float *p =
4725 (float *) (((char *) lpStrideData->u.s.position.lpData) + i * lpStrideData->u.s.position.dwStride);
4726 float x, y, z, rhw;
4727 TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
4729 /* Multiplication with world, view and projection matrix */
4730 x = (p[0] * mat.u.s._11) + (p[1] * mat.u.s._21) + (p[2] * mat.u.s._31) + (1.0 * mat.u.s._41);
4731 y = (p[0] * mat.u.s._12) + (p[1] * mat.u.s._22) + (p[2] * mat.u.s._32) + (1.0 * mat.u.s._42);
4732 z = (p[0] * mat.u.s._13) + (p[1] * mat.u.s._23) + (p[2] * mat.u.s._33) + (1.0 * mat.u.s._43);
4733 rhw = (p[0] * mat.u.s._14) + (p[1] * mat.u.s._24) + (p[2] * mat.u.s._34) + (1.0 * mat.u.s._44);
4735 TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
4737 /* WARNING: The following things are taken from d3d7 and were not yet checked
4738 * against d3d8 or d3d9!
4741 /* Clipping conditions: From
4742 * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp
4744 * A vertex is clipped if it does not match the following requirements
4745 * -rhw < x <= rhw
4746 * -rhw < y <= rhw
4747 * 0 < z <= rhw
4748 * 0 < rhw ( Not in d3d7, but tested in d3d7)
4750 * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
4751 * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
4755 if( doClip == FALSE ||
4756 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
4757 (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) &&
4758 ( rhw > eps ) ) ) {
4760 /* "Normal" viewport transformation (not clipped)
4761 * 1) The values are divided trough rhw
4762 * 2) The y axis is negative, so multiply it with -1
4763 * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
4764 * -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
4765 * 4) Multiply x with Width/2 and add Width/2
4766 * 5) The same for the height
4767 * 6) Add the viewpoint X and Y to the 2D coordinates and
4768 * The minimum Z value to z
4769 * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
4771 * Well, basically it's simply a linear transformation into viewport
4772 * coordinates
4775 x /= rhw;
4776 y /= rhw;
4777 z /= rhw;
4779 y *= -1;
4781 x *= vp.Width / 2;
4782 y *= vp.Height / 2;
4783 z *= vp.MaxZ - vp.MinZ;
4785 x += vp.Width / 2 + vp.X;
4786 y += vp.Height / 2 + vp.Y;
4787 z += vp.MinZ;
4789 rhw = 1 / rhw;
4790 } else {
4791 /* That vertex got clipped
4792 * Contrary to OpenGL it is not dropped completely, it just
4793 * undergoes a different calculation.
4795 TRACE("Vertex got clipped\n");
4796 x += rhw;
4797 y += rhw;
4799 x /= 2;
4800 y /= 2;
4802 /* Msdn mentiones that Direct3D9 keeps a list of clipped vertices
4803 * outside of the main vertex buffer memory. That needs some more
4804 * investigation...
4808 TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
4811 ( (float *) dest_ptr)[0] = x;
4812 ( (float *) dest_ptr)[1] = y;
4813 ( (float *) dest_ptr)[2] = z;
4814 ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
4816 dest_ptr += 3 * sizeof(float);
4818 if((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
4819 dest_ptr += sizeof(float);
4822 if (DestFVF & D3DFVF_PSIZE) {
4823 dest_ptr += sizeof(DWORD);
4825 if (DestFVF & D3DFVF_NORMAL) {
4826 float *normal =
4827 (float *) (((float *) lpStrideData->u.s.normal.lpData) + i * lpStrideData->u.s.normal.dwStride);
4828 /* AFAIK this should go into the lighting information */
4829 FIXME("Didn't expect the destination to have a normal\n");
4830 copy_and_next(dest_ptr, normal, 3 * sizeof(float));
4833 if (DestFVF & D3DFVF_DIFFUSE) {
4834 DWORD *color_d =
4835 (DWORD *) (((char *) lpStrideData->u.s.diffuse.lpData) + i * lpStrideData->u.s.diffuse.dwStride);
4836 if(!color_d) {
4837 static BOOL warned = FALSE;
4839 if(warned == FALSE) {
4840 ERR("No diffuse color in source, but destination has one\n");
4841 warned = TRUE;
4844 *( (DWORD *) dest_ptr) = 0xffffffff;
4845 dest_ptr += sizeof(DWORD);
4847 else
4848 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
4851 if (DestFVF & D3DFVF_SPECULAR) {
4852 /* What's the color value in the feedback buffer? */
4853 DWORD *color_s =
4854 (DWORD *) (((char *) lpStrideData->u.s.specular.lpData) + i * lpStrideData->u.s.specular.dwStride);
4855 if(!color_s) {
4856 static BOOL warned = FALSE;
4858 if(warned == FALSE) {
4859 ERR("No specular color in source, but destination has one\n");
4860 warned = TRUE;
4863 *( (DWORD *) dest_ptr) = 0xFF000000;
4864 dest_ptr += sizeof(DWORD);
4866 else {
4867 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
4871 for (tex_index = 0; tex_index < numTextures; tex_index++) {
4872 float *tex_coord =
4873 (float *) (((char *) lpStrideData->u.s.texCoords[tex_index].lpData) +
4874 i * lpStrideData->u.s.texCoords[tex_index].dwStride);
4875 if(!tex_coord) {
4876 ERR("No source texture, but destination requests one\n");
4877 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
4879 else {
4880 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
4885 return WINED3D_OK;
4887 #undef copy_and_next
4889 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
4890 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4891 IWineD3DVertexBufferImpl *SrcImpl = (IWineD3DVertexBufferImpl *) pVertexDecl;
4892 WineDirect3DVertexStridedData strided;
4893 HRESULT hr;
4894 TRACE("(%p)->(%d,%d,%d,%p,%p,%ld\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
4896 hr = IWineD3DDevice_SetFVF(iface, SrcImpl->fvf);
4897 hr = IWineD3DDevice_SetStreamSource(iface, 0, pVertexDecl, get_flexible_vertex_size(SrcImpl->fvf) * SrcStartIndex, get_flexible_vertex_size(SrcImpl->fvf));
4899 memset(&strided, 0, sizeof(strided));
4900 primitiveConvertToStridedData(iface, &strided, 0);
4902 return process_vertices_strided(This, DestIndex, VertexCount, &strided, SrcImpl->fvf, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags);
4905 /*****
4906 * Apply / Get / Set Texture Stage States
4907 * TODO: Verify against dx9 definitions
4908 *****/
4910 /* 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 */
4911 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
4912 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4913 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
4914 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4916 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4918 /* Check that the stage is within limits */
4919 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4920 TRACE("Attempt to access invalid texture rejected\n");
4921 return;
4924 ENTER_GL();
4926 switch (Type) {
4927 case WINED3DTSS_ALPHAOP :
4928 case WINED3DTSS_COLOROP :
4929 /* nothing to do as moved to drawprim for now */
4930 break;
4931 case WINED3DTSS_ADDRESSW :
4932 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
4933 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
4934 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
4936 } else {
4937 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
4938 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
4939 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
4940 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
4942 #endif
4943 case WINED3DTSS_TEXCOORDINDEX :
4945 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
4947 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
4948 one flag, you can still specify an index value, which the system uses to
4949 determine the texture wrapping mode.
4950 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
4951 means use the vertex position (camera-space) as the input texture coordinates
4952 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
4953 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
4954 to the TEXCOORDINDEX value */
4957 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
4959 switch (Value & 0xFFFF0000) {
4960 case D3DTSS_TCI_PASSTHRU:
4961 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
4962 glDisable(GL_TEXTURE_GEN_S);
4963 glDisable(GL_TEXTURE_GEN_T);
4964 glDisable(GL_TEXTURE_GEN_R);
4965 glDisable(GL_TEXTURE_GEN_Q);
4966 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
4967 break;
4969 case D3DTSS_TCI_CAMERASPACEPOSITION:
4970 /* CameraSpacePosition means use the vertex position, transformed to camera space,
4971 as the input texture coordinates for this stage's texture transformation. This
4972 equates roughly to EYE_LINEAR */
4974 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4975 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4976 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4977 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4978 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4980 glMatrixMode(GL_MODELVIEW);
4981 glPushMatrix();
4982 glLoadIdentity();
4983 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4984 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4985 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4986 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4987 glPopMatrix();
4989 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
4990 glEnable(GL_TEXTURE_GEN_S);
4991 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4992 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4993 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4994 glEnable(GL_TEXTURE_GEN_T);
4995 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4996 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4997 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4998 glEnable(GL_TEXTURE_GEN_R);
4999 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5000 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5001 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5003 break;
5005 case D3DTSS_TCI_CAMERASPACENORMAL:
5007 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5008 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5009 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5010 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5011 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5012 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
5014 glMatrixMode(GL_MODELVIEW);
5015 glPushMatrix();
5016 glLoadIdentity();
5017 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5018 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5019 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5020 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5021 glPopMatrix();
5023 glEnable(GL_TEXTURE_GEN_S);
5024 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5025 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5026 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5027 glEnable(GL_TEXTURE_GEN_T);
5028 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5029 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5030 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5031 glEnable(GL_TEXTURE_GEN_R);
5032 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5033 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5034 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5037 break;
5039 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
5041 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5042 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5043 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5044 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5045 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5046 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
5048 glMatrixMode(GL_MODELVIEW);
5049 glPushMatrix();
5050 glLoadIdentity();
5051 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5052 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5053 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5054 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5055 glPopMatrix();
5057 glEnable(GL_TEXTURE_GEN_S);
5058 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5059 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5060 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5061 glEnable(GL_TEXTURE_GEN_T);
5062 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5063 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5064 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5065 glEnable(GL_TEXTURE_GEN_R);
5066 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5067 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5068 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5071 break;
5073 /* Unhandled types: */
5074 default:
5075 /* Todo: */
5076 /* ? disable GL_TEXTURE_GEN_n ? */
5077 glDisable(GL_TEXTURE_GEN_S);
5078 glDisable(GL_TEXTURE_GEN_T);
5079 glDisable(GL_TEXTURE_GEN_R);
5080 glDisable(GL_TEXTURE_GEN_Q);
5081 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
5082 break;
5085 break;
5087 /* Unhandled */
5088 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
5089 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);
5090 break;
5092 case WINED3DTSS_BUMPENVMAT00 :
5093 case WINED3DTSS_BUMPENVMAT01 :
5094 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
5095 break;
5096 case WINED3DTSS_BUMPENVMAT10 :
5097 case WINED3DTSS_BUMPENVMAT11 :
5098 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
5099 break;
5101 case WINED3DTSS_BUMPENVLSCALE :
5102 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5103 break;
5105 case WINED3DTSS_BUMPENVLOFFSET :
5106 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5107 break;
5109 case WINED3DTSS_RESULTARG :
5110 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5111 break;
5113 default:
5114 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
5115 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5118 LEAVE_GL();
5120 return;
5123 /*****
5124 * Get / Set Texture Stage States
5125 * TODO: Verify against dx9 definitions
5126 *****/
5127 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
5128 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5130 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5132 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
5134 /* Reject invalid texture units */
5135 if (Stage >= GL_LIMITS(textures)) {
5136 TRACE("Attempt to access invalid texture rejected\n");
5137 return WINED3DERR_INVALIDCALL;
5140 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
5141 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
5142 This->updateStateBlock->textureState[Stage][Type] = Value;
5144 return WINED3D_OK;
5147 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
5148 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5149 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
5150 *pValue = This->updateStateBlock->textureState[Stage][Type];
5151 return WINED3D_OK;
5154 /*****
5155 * Get / Set Texture
5156 *****/
5157 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
5159 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5160 IWineD3DBaseTexture *oldTexture;
5162 oldTexture = This->updateStateBlock->textures[Stage];
5163 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
5165 #if 0 /* TODO: check so vertex textures */
5166 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
5167 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
5168 return WINED3D_OK;
5170 #endif
5172 /* Reject invalid texture units */
5173 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
5174 WARN("Attempt to access invalid texture rejected\n");
5175 return WINED3DERR_INVALIDCALL;
5178 if(pTexture != NULL) {
5179 /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH; The same is
5180 * the case for WINED3DPOOL_SYSTEMMEM textures unless WINED3DDEVCAPS_TEXTURESYSTEMMORY is set.
5181 * We don't check the caps as GetDeviceCaps is inefficient and we don't set the cap anyway.
5183 if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH || ((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SYSTEMMEM) {
5184 WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
5185 return WINED3DERR_INVALIDCALL;
5189 oldTexture = This->updateStateBlock->textures[Stage];
5190 TRACE("GL_LIMITS %d\n",GL_LIMITS(textures));
5191 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
5193 This->updateStateBlock->set.textures[Stage] = TRUE;
5194 This->updateStateBlock->changed.textures[Stage] = TRUE;
5195 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
5196 This->updateStateBlock->textures[Stage] = pTexture;
5198 /* Handle recording of state blocks */
5199 if (This->isRecordingState) {
5200 TRACE("Recording... not performing anything\n");
5201 return WINED3D_OK;
5204 /** NOTE: MSDN says that setTexture increases the reference count,
5205 * and the the application nust set the texture back to null (or have a leaky application),
5206 * This means we should pass the refcount up to the parent
5207 *******************************/
5208 if (NULL != This->updateStateBlock->textures[Stage]) {
5209 IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
5212 if (NULL != oldTexture) {
5213 IWineD3DBaseTexture_Release(oldTexture);
5216 return WINED3D_OK;
5219 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
5220 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5221 TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
5223 /* Reject invalid texture units */
5224 if (Stage >= GL_LIMITS(textures)) {
5225 TRACE("Attempt to access invalid texture rejected\n");
5226 return WINED3DERR_INVALIDCALL;
5228 *ppTexture=This->updateStateBlock->textures[Stage];
5229 if (*ppTexture)
5230 IWineD3DBaseTexture_AddRef(*ppTexture);
5231 else
5232 return WINED3DERR_INVALIDCALL;
5233 return WINED3D_OK;
5236 /*****
5237 * Get Back Buffer
5238 *****/
5239 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
5240 IWineD3DSurface **ppBackBuffer) {
5241 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5242 IWineD3DSwapChain *swapChain;
5243 HRESULT hr;
5245 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
5247 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
5248 if (hr == WINED3D_OK) {
5249 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
5250 IWineD3DSwapChain_Release(swapChain);
5251 } else {
5252 *ppBackBuffer = NULL;
5254 return hr;
5257 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
5258 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5259 WARN("(%p) : stub, calling idirect3d for now\n", This);
5260 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
5263 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
5264 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5265 IWineD3DSwapChain *swapChain;
5266 HRESULT hr;
5268 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5269 if (hr == WINED3D_OK) {
5270 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
5271 IWineD3DSwapChain_Release(swapChain);
5272 } else {
5273 FIXME("(%p) Error getting display mode\n", This);
5275 return hr;
5278 HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
5279 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5280 TRACE("(%p)->(%p)\n", This, hWnd);
5282 This->ddraw_window = hWnd;
5283 return WINED3D_OK;
5286 HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
5287 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5288 TRACE("(%p)->(%p)\n", This, hWnd);
5290 *hWnd = This->ddraw_window;
5291 return WINED3D_OK;
5294 /*****
5295 * Stateblock related functions
5296 *****/
5298 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
5299 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5300 IWineD3DStateBlockImpl *object;
5301 TRACE("(%p)", This);
5303 if (This->isRecordingState) {
5304 return WINED3DERR_INVALIDCALL;
5307 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
5308 if (NULL == object ) {
5309 FIXME("(%p)Error allocating memory for stateblock\n", This);
5310 return E_OUTOFMEMORY;
5312 TRACE("(%p) creted object %p\n", This, object);
5313 object->wineD3DDevice= This;
5314 /** FIXME: object->parent = parent; **/
5315 object->parent = NULL;
5316 object->blockType = WINED3DSBT_ALL;
5317 object->ref = 1;
5318 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
5320 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
5321 This->updateStateBlock = object;
5322 This->isRecordingState = TRUE;
5324 TRACE("(%p) recording stateblock %p\n",This , object);
5325 return WINED3D_OK;
5328 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
5329 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5331 if (!This->isRecordingState) {
5332 FIXME("(%p) not recording! returning error\n", This);
5333 *ppStateBlock = NULL;
5334 return WINED3DERR_INVALIDCALL;
5337 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
5338 This->isRecordingState = FALSE;
5339 This->updateStateBlock = This->stateBlock;
5340 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
5341 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
5342 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
5343 return WINED3D_OK;
5346 /*****
5347 * Scene related functions
5348 *****/
5349 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
5350 /* At the moment we have no need for any functionality at the beginning
5351 of a scene */
5352 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5353 TRACE("(%p) : stub\n", This);
5354 return WINED3D_OK;
5357 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
5358 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5359 TRACE("(%p)\n", This);
5360 ENTER_GL();
5361 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
5362 glFlush();
5363 checkGLcall("glFlush");
5365 TRACE("End Scene\n");
5366 if(This->renderTarget != NULL) {
5368 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
5369 IUnknown *targetContainer = NULL;
5370 if (WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
5371 || WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
5372 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
5373 /** always dirtify for now. we must find a better way to see that surface have been modified
5374 (Modifications should will only occur via draw-primitive, but we do need better locking
5375 switching to render-to-texture should remove the overhead though.
5377 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
5378 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
5379 IWineD3DSurface_PreLoad(This->renderTarget);
5380 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
5381 IUnknown_Release(targetContainer);
5384 This->sceneEnded = TRUE;
5385 LEAVE_GL();
5386 return WINED3D_OK;
5389 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
5390 CONST RECT* pSourceRect, CONST RECT* pDestRect,
5391 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
5392 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5393 IWineD3DSwapChain *swapChain = NULL;
5394 int i;
5395 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
5397 TRACE("(%p) Presenting the frame\n", This);
5399 for(i = 0 ; i < swapchains ; i ++) {
5401 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
5402 TRACE("presentinng chain %d, %p\n", i, swapChain);
5403 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
5404 IWineD3DSwapChain_Release(swapChain);
5407 return WINED3D_OK;
5410 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
5411 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
5412 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5414 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
5415 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
5416 when the depth-buffer format does not contain stencil buffer information, this method fails. */
5417 GLbitfield glMask = 0;
5418 GLboolean old_ztest;
5419 GLfloat old_z_clear_value;
5420 GLint old_stencil_clear_value;
5421 GLfloat old_color_clear_value[4];
5422 unsigned int i;
5423 CONST D3DRECT* curRect;
5425 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
5426 Count, pRects, Flags, Z, Stencil);
5428 ENTER_GL();
5430 glEnable(GL_SCISSOR_TEST);
5431 checkGLcall("glEnable GL_SCISSOR_TEST");
5433 if (Count > 0 && pRects) {
5434 curRect = pRects;
5435 } else {
5436 curRect = NULL;
5439 /* Only set the values up once, as they are not changing */
5440 if (Flags & D3DCLEAR_STENCIL) {
5441 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
5442 glClearStencil(Stencil);
5443 checkGLcall("glClearStencil");
5444 glMask = glMask | GL_STENCIL_BUFFER_BIT;
5445 glStencilMask(0xFFFFFFFF);
5448 if (Flags & D3DCLEAR_ZBUFFER) {
5449 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
5450 glDepthMask(GL_TRUE);
5451 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
5452 glClearDepth(Z);
5453 checkGLcall("glClearDepth");
5454 glMask = glMask | GL_DEPTH_BUFFER_BIT;
5457 if (Flags & D3DCLEAR_TARGET) {
5458 TRACE("Clearing screen with glClear to color %lx\n", Color);
5459 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
5460 glClearColor(D3DCOLOR_R(Color),
5461 D3DCOLOR_G(Color),
5462 D3DCOLOR_B(Color),
5463 D3DCOLOR_A(Color));
5464 checkGLcall("glClearColor");
5466 /* Clear ALL colors! */
5467 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5468 glMask = glMask | GL_COLOR_BUFFER_BIT;
5471 /* Now process each rect in turn */
5472 for (i = 0; i < Count || i == 0; i++) {
5474 if (curRect) {
5475 /* Note gl uses lower left, width/height */
5476 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
5477 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
5478 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
5479 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
5480 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
5481 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
5482 checkGLcall("glScissor");
5483 } else {
5484 glScissor(This->stateBlock->viewport.X,
5485 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
5486 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
5487 This->stateBlock->viewport.Width,
5488 This->stateBlock->viewport.Height);
5489 checkGLcall("glScissor");
5492 /* Clear the selected rectangle (or full screen) */
5493 glClear(glMask);
5494 checkGLcall("glClear");
5496 /* Step to the next rectangle */
5497 if (curRect) curRect = curRect + sizeof(D3DRECT);
5500 /* Restore the old values (why..?) */
5501 if (Flags & D3DCLEAR_STENCIL) {
5502 glClearStencil(old_stencil_clear_value);
5503 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
5505 if (Flags & D3DCLEAR_ZBUFFER) {
5506 glDepthMask(old_ztest);
5507 glClearDepth(old_z_clear_value);
5509 if (Flags & D3DCLEAR_TARGET) {
5510 glClearColor(old_color_clear_value[0],
5511 old_color_clear_value[1],
5512 old_color_clear_value[2],
5513 old_color_clear_value[3]);
5514 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
5515 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
5516 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
5517 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
5520 glDisable(GL_SCISSOR_TEST);
5521 checkGLcall("glDisable");
5522 LEAVE_GL();
5524 return WINED3D_OK;
5527 /*****
5528 * Drawing functions
5529 *****/
5530 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
5531 UINT PrimitiveCount) {
5533 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5534 This->stateBlock->streamIsUP = FALSE;
5536 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
5537 debug_d3dprimitivetype(PrimitiveType),
5538 StartVertex, PrimitiveCount);
5539 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
5540 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */, NULL);
5543 return WINED3D_OK;
5546 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
5547 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
5548 D3DPRIMITIVETYPE PrimitiveType,
5549 INT baseVIndex, UINT minIndex,
5550 UINT NumVertices, UINT startIndex, UINT primCount) {
5552 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5553 UINT idxStride = 2;
5554 IWineD3DIndexBuffer *pIB;
5555 WINED3DINDEXBUFFER_DESC IdxBufDsc;
5557 pIB = This->stateBlock->pIndexData;
5558 This->stateBlock->streamIsUP = FALSE;
5560 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
5561 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5562 minIndex, NumVertices, startIndex, baseVIndex, primCount);
5564 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
5565 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
5566 idxStride = 2;
5567 } else {
5568 idxStride = 4;
5571 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
5572 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex, NULL);
5574 return WINED3D_OK;
5577 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
5578 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
5579 UINT VertexStreamZeroStride) {
5580 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5582 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
5583 debug_d3dprimitivetype(PrimitiveType),
5584 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
5586 /* release the stream source */
5587 if (This->stateBlock->streamSource[0] != NULL) {
5588 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5591 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5592 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5593 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5594 This->stateBlock->streamIsUP = TRUE;
5596 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
5597 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */, NULL);
5599 /* MSDN specifies stream zero settings must be set to NULL */
5600 This->stateBlock->streamStride[0] = 0;
5601 This->stateBlock->streamSource[0] = NULL;
5603 /*stream zero settings set to null at end, as per the msdn */
5604 return WINED3D_OK;
5607 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
5608 UINT MinVertexIndex, UINT NumVertices,
5609 UINT PrimitiveCount, CONST void* pIndexData,
5610 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
5611 UINT VertexStreamZeroStride) {
5612 int idxStride;
5613 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5615 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
5616 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5617 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
5618 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
5620 if (IndexDataFormat == WINED3DFMT_INDEX16) {
5621 idxStride = 2;
5622 } else {
5623 idxStride = 4;
5626 /* release the stream and index data */
5627 if (This->stateBlock->streamSource[0] != NULL) {
5628 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5630 if (This->stateBlock->pIndexData) {
5631 IWineD3DIndexBuffer_Release(This->stateBlock->pIndexData);
5634 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5635 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5636 This->stateBlock->streamIsUP = TRUE;
5637 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5639 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex, NULL);
5641 /* MSDN specifies stream zero settings and index buffer must be set to NULL */
5642 This->stateBlock->streamSource[0] = NULL;
5643 This->stateBlock->streamStride[0] = 0;
5644 This->stateBlock->pIndexData = NULL;
5646 return WINED3D_OK;
5649 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
5651 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0, DrawPrimStrideData);
5652 return WINED3D_OK;
5654 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
5655 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
5656 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5657 HRESULT hr = WINED3D_OK;
5658 WINED3DRESOURCETYPE sourceType;
5659 WINED3DRESOURCETYPE destinationType;
5660 int i ,levels;
5662 /* TODO: think about moving the code into IWineD3DBaseTexture */
5664 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
5666 /* verify that the source and destination textures aren't NULL */
5667 if (NULL == pSourceTexture || NULL == pDestinationTexture) {
5668 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
5669 This, pSourceTexture, pDestinationTexture);
5670 hr = WINED3DERR_INVALIDCALL;
5673 if (pSourceTexture == pDestinationTexture) {
5674 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
5675 This, pSourceTexture, pDestinationTexture);
5676 hr = WINED3DERR_INVALIDCALL;
5678 /* Verify that the source and destination textures are the same type */
5679 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
5680 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
5682 if (sourceType != destinationType) {
5683 WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
5684 This);
5685 hr = WINED3DERR_INVALIDCALL;
5688 /* check that both textures have the identical numbers of levels */
5689 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
5690 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
5691 hr = WINED3DERR_INVALIDCALL;
5694 if (WINED3D_OK == hr) {
5696 /* Make sure that the destination texture is loaded */
5697 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
5699 /* Update every surface level of the texture */
5700 levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
5702 switch (sourceType) {
5703 case WINED3DRTYPE_TEXTURE:
5705 IWineD3DSurface *srcSurface;
5706 IWineD3DSurface *destSurface;
5708 for (i = 0 ; i < levels ; ++i) {
5709 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture, i, &srcSurface);
5710 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
5711 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5712 IWineD3DSurface_Release(srcSurface);
5713 IWineD3DSurface_Release(destSurface);
5714 if (WINED3D_OK != hr) {
5715 WARN("(%p) : Call to update surface failed\n", This);
5716 return hr;
5720 break;
5721 case WINED3DRTYPE_CUBETEXTURE:
5723 IWineD3DSurface *srcSurface;
5724 IWineD3DSurface *destSurface;
5725 WINED3DCUBEMAP_FACES faceType;
5727 for (i = 0 ; i < levels ; ++i) {
5728 /* Update each cube face */
5729 for (faceType = D3DCUBEMAP_FACE_POSITIVE_X; faceType <= D3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
5730 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture, faceType, i, &srcSurface);
5731 if (WINED3D_OK != hr) {
5732 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5733 } else {
5734 TRACE("Got srcSurface %p\n", srcSurface);
5736 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
5737 if (WINED3D_OK != hr) {
5738 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5739 } else {
5740 TRACE("Got desrSurface %p\n", destSurface);
5742 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5743 IWineD3DSurface_Release(srcSurface);
5744 IWineD3DSurface_Release(destSurface);
5745 if (WINED3D_OK != hr) {
5746 WARN("(%p) : Call to update surface failed\n", This);
5747 return hr;
5752 break;
5753 #if 0 /* TODO: Add support for volume textures */
5754 case WINED3DRTYPE_VOLUMETEXTURE:
5756 IWineD3DVolume srcVolume = NULL;
5757 IWineD3DSurface destVolume = NULL;
5759 for (i = 0 ; i < levels ; ++i) {
5760 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture, i, &srcVolume);
5761 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
5762 hr = IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
5763 IWineD3DVolume_Release(srcSurface);
5764 IWineD3DVolume_Release(destSurface);
5765 if (WINED3D_OK != hr) {
5766 WARN("(%p) : Call to update volume failed\n", This);
5767 return hr;
5771 break;
5772 #endif
5773 default:
5774 FIXME("(%p) : Unsupported source and destination type\n", This);
5775 hr = WINED3DERR_INVALIDCALL;
5779 return hr;
5782 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
5783 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
5784 CONST RECT* pDestRect, WINED3DTEXTUREFILTERTYPE Filter) {
5785 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5787 TRACE("(%p) : stub\n", This);
5788 return WINED3D_OK;
5790 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
5791 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5792 /** TODO: remove remove casts to IWineD3DSurfaceImpl *
5793 * NOTE It may be best to move the code into surface to occomplish this
5794 ****************************************/
5796 WINED3DSURFACE_DESC surfaceDesc;
5797 unsigned int surfaceWidth, surfaceHeight;
5798 glDescriptor *targetGlDescription = NULL;
5799 glDescriptor *surfaceGlDescription = NULL;
5800 IWineD3DSwapChainImpl *container = NULL;
5802 IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
5803 IWineD3DSurface_GetGlDesc(pSurface, &surfaceGlDescription);
5804 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5806 surfaceDesc.Width = &surfaceWidth;
5807 surfaceDesc.Height = &surfaceHeight;
5808 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5809 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
5811 /* Ok, I may need to setup some kind of active swapchain reference on the device */
5812 IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
5813 ENTER_GL();
5814 /* TODO: opengl Context switching for swapchains etc... */
5815 if (NULL != container || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
5816 if (NULL != container && (pRenderTarget == container->backBuffer)) {
5817 glReadBuffer(GL_BACK);
5818 vcheckGLcall("glReadBuffer(GL_BACK)");
5819 } else if ((NULL != container && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
5820 glReadBuffer(GL_FRONT);
5821 vcheckGLcall("glReadBuffer(GL_FRONT)");
5822 } else if (pRenderTarget == This->depthStencilBuffer) {
5823 FIXME("Reading of depthstencil not yet supported\n");
5826 glReadPixels(surfaceGlDescription->target,
5827 surfaceGlDescription->level,
5828 surfaceWidth,
5829 surfaceHeight,
5830 surfaceGlDescription->glFormat,
5831 surfaceGlDescription->glType,
5832 (void *)IWineD3DSurface_GetData(pSurface));
5833 vcheckGLcall("glReadPixels(...)");
5834 if(NULL != container ){
5835 IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
5837 } else {
5838 IWineD3DBaseTexture *container;
5839 GLenum textureDimensions = GL_TEXTURE_2D;
5841 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
5842 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
5843 IWineD3DBaseTexture_Release(container);
5845 /* TODO: 2D -> Cube surface coppies etc.. */
5846 if (surfaceGlDescription->target != textureDimensions) {
5847 FIXME("(%p) : Texture dimension mismatch\n", This);
5849 glEnable(textureDimensions);
5850 vcheckGLcall("glEnable(GL_TEXTURE_...)");
5851 /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
5852 glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
5853 vcheckGLcall("glBindTexture");
5854 glGetTexImage(surfaceGlDescription->target,
5855 surfaceGlDescription->level,
5856 surfaceGlDescription->glFormat,
5857 surfaceGlDescription->glType,
5858 (void *)IWineD3DSurface_GetData(pSurface));
5859 glDisable(textureDimensions);
5860 vcheckGLcall("glDisable(GL_TEXTURE_...)");
5863 LEAVE_GL();
5864 return WINED3D_OK;
5867 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
5868 IWineD3DSwapChain *swapChain;
5869 HRESULT hr;
5870 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5871 if(hr == WINED3D_OK) {
5872 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
5873 IWineD3DSwapChain_Release(swapChain);
5875 return hr;
5878 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5879 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5880 /* return a sensible default */
5881 *pNumPasses = 1;
5882 /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
5883 FIXME("(%p) : stub\n", This);
5884 return WINED3D_OK;
5887 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5888 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5889 int j;
5890 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5891 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5892 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5893 return WINED3DERR_INVALIDCALL;
5895 for (j = 0; j < 256; ++j) {
5896 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
5897 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5898 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
5899 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5901 TRACE("(%p) : returning\n", This);
5902 return WINED3D_OK;
5905 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5906 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5907 int j;
5908 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5909 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5910 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5911 return WINED3DERR_INVALIDCALL;
5913 for (j = 0; j < 256; ++j) {
5914 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
5915 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5916 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
5917 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5919 TRACE("(%p) : returning\n", This);
5920 return WINED3D_OK;
5923 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5924 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5925 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5926 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5927 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5928 return WINED3DERR_INVALIDCALL;
5930 /*TODO: stateblocks */
5931 This->currentPalette = PaletteNumber;
5932 TRACE("(%p) : returning\n", This);
5933 return WINED3D_OK;
5936 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
5937 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5938 if (PaletteNumber == NULL) {
5939 WARN("(%p) : returning Invalid Call\n", This);
5940 return WINED3DERR_INVALIDCALL;
5942 /*TODO: stateblocks */
5943 *PaletteNumber = This->currentPalette;
5944 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
5945 return WINED3D_OK;
5948 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
5949 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5950 static BOOL showFixmes = TRUE;
5951 if (showFixmes) {
5952 FIXME("(%p) : stub\n", This);
5953 showFixmes = FALSE;
5956 This->softwareVertexProcessing = bSoftware;
5957 return WINED3D_OK;
5961 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
5962 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5963 static BOOL showFixmes = TRUE;
5964 if (showFixmes) {
5965 FIXME("(%p) : stub\n", This);
5966 showFixmes = FALSE;
5968 return This->softwareVertexProcessing;
5972 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
5973 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5974 IWineD3DSwapChain *swapChain;
5975 HRESULT hr;
5977 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
5979 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5980 if(hr == WINED3D_OK){
5981 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
5982 IWineD3DSwapChain_Release(swapChain);
5983 }else{
5984 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
5986 return hr;
5990 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
5991 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5992 static BOOL showfixmes = TRUE;
5993 if(nSegments != 0.0f) {
5994 if( showfixmes) {
5995 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
5996 showfixmes = FALSE;
5999 return WINED3D_OK;
6002 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
6003 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6004 static BOOL showfixmes = TRUE;
6005 if( showfixmes) {
6006 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
6007 showfixmes = FALSE;
6009 return 0.0f;
6012 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
6013 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6014 /** TODO: remove casts to IWineD3DSurfaceImpl
6015 * NOTE: move code to surface to accomplish this
6016 ****************************************/
6017 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
6018 int srcWidth, srcHeight;
6019 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
6020 WINED3DFORMAT destFormat, srcFormat;
6021 UINT destSize;
6022 int destLeft, destTop;
6023 WINED3DPOOL srcPool, destPool;
6024 int offset = 0;
6025 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
6026 glDescriptor *glDescription = NULL;
6027 GLenum textureDimensions = GL_TEXTURE_2D;
6028 IWineD3DBaseTexture *baseTexture;
6030 WINED3DSURFACE_DESC winedesc;
6032 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
6033 memset(&winedesc, 0, sizeof(winedesc));
6034 winedesc.Width = &srcSurfaceWidth;
6035 winedesc.Height = &srcSurfaceHeight;
6036 winedesc.Pool = &srcPool;
6037 winedesc.Format = &srcFormat;
6039 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
6041 winedesc.Width = &destSurfaceWidth;
6042 winedesc.Height = &destSurfaceHeight;
6043 winedesc.Pool = &destPool;
6044 winedesc.Format = &destFormat;
6045 winedesc.Size = &destSize;
6047 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6049 if(srcPool != WINED3DPOOL_SYSTEMMEM || destPool != WINED3DPOOL_DEFAULT){
6050 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
6051 return WINED3DERR_INVALIDCALL;
6054 if (destFormat == WINED3DFMT_UNKNOWN) {
6055 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
6056 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
6058 /* Get the update surface description */
6059 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6062 /* Make sure the surface is loaded and up to date */
6063 IWineD3DSurface_PreLoad(pDestinationSurface);
6065 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
6067 ENTER_GL();
6069 /* this needs to be done in lines if the sourceRect != the sourceWidth */
6070 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
6071 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
6072 destLeft = pDestPoint ? pDestPoint->x : 0;
6073 destTop = pDestPoint ? pDestPoint->y : 0;
6076 /* This function doesn't support compressed textures
6077 the pitch is just bytesPerPixel * width */
6078 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
6079 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
6080 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
6081 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
6083 /* TODO DXT formats */
6085 if(pSourceRect != NULL && pSourceRect->top != 0){
6086 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
6088 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
6089 ,This
6090 ,glDescription->level
6091 ,destLeft
6092 ,destTop
6093 ,srcWidth
6094 ,srcHeight
6095 ,glDescription->glFormat
6096 ,glDescription->glType
6097 ,IWineD3DSurface_GetData(pSourceSurface)
6100 /* Sanity check */
6101 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
6103 /* need to lock the surface to get the data */
6104 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
6107 /* TODO: Cube and volume support */
6108 if(rowoffset != 0){
6109 /* not a whole row so we have to do it a line at a time */
6110 int j;
6112 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
6113 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
6115 for(j = destTop ; j < (srcHeight + destTop) ; j++){
6117 glTexSubImage2D(glDescription->target
6118 ,glDescription->level
6119 ,destLeft
6121 ,srcWidth
6123 ,glDescription->glFormat
6124 ,glDescription->glType
6125 ,data /* could be quicker using */
6127 data += rowoffset;
6130 } else { /* Full width, so just write out the whole texture */
6132 if (WINED3DFMT_DXT1 == destFormat ||
6133 WINED3DFMT_DXT2 == destFormat ||
6134 WINED3DFMT_DXT3 == destFormat ||
6135 WINED3DFMT_DXT4 == destFormat ||
6136 WINED3DFMT_DXT5 == destFormat) {
6137 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
6138 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
6139 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
6140 FIXME("Updating part of a compressed texture is not supported at the moment\n");
6141 } if (destFormat != srcFormat) {
6142 FIXME("Updating mixed format compressed texture is not curretly support\n");
6143 } else {
6144 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
6145 glDescription->level,
6146 glDescription->glFormatInternal,
6147 srcWidth,
6148 srcHeight,
6150 destSize,
6151 IWineD3DSurface_GetData(pSourceSurface));
6153 } else {
6154 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
6158 } else {
6159 if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
6161 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
6162 to repack the data from pow2Width/Height to expected Width,Height, this makes the
6163 data returned by GetData non-power2 width/height with hardware non-power2
6164 pow2Width/height are set to surface width height, repacking isn't needed so it
6165 doesn't matter which function gets called. */
6166 glTexSubImage2D(glDescription->target
6167 ,glDescription->level
6168 ,destLeft
6169 ,destTop
6170 ,srcWidth
6171 ,srcHeight
6172 ,glDescription->glFormat
6173 ,glDescription->glType
6174 ,IWineD3DSurface_GetData(pSourceSurface)
6176 } else {
6178 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
6179 glTexSubImage2D(glDescription->target
6180 ,glDescription->level
6181 ,destLeft
6182 ,destTop
6183 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
6184 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
6185 ,glDescription->glFormat
6186 ,glDescription->glType
6187 ,IWineD3DSurface_GetData(pSourceSurface)
6193 checkGLcall("glTexSubImage2D");
6195 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
6196 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
6197 * surface bigger than it needs to be hmm.. */
6198 if (WINED3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
6199 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
6200 IWineD3DBaseTexture_Release(baseTexture);
6203 glDisable(textureDimensions); /* This needs to be managed better.... */
6204 LEAVE_GL();
6206 return WINED3D_OK;
6209 /* Used by DirectX 8 */
6210 HRESULT WINAPI IWineD3DDeviceImpl_CopyRects(IWineD3DDevice *iface,
6211 IWineD3DSurface* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
6212 IWineD3DSurface* pDestinationSurface, CONST POINT* pDestPointsArray) {
6214 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6215 HRESULT hr = WINED3D_OK;
6216 WINED3DFORMAT srcFormat, destFormat;
6217 UINT srcWidth, destWidth;
6218 UINT srcHeight, destHeight;
6219 UINT srcSize;
6220 WINED3DSURFACE_DESC winedesc;
6222 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
6223 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
6226 /* Check that the source texture is in WINED3DPOOL_SYSTEMMEM and the destination texture is in WINED3DPOOL_DEFAULT */
6227 memset(&winedesc, 0, sizeof(winedesc));
6229 winedesc.Format = &srcFormat;
6230 winedesc.Width = &srcWidth;
6231 winedesc.Height = &srcHeight;
6232 winedesc.Size = &srcSize;
6233 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
6235 winedesc.Format = &destFormat;
6236 winedesc.Width = &destWidth;
6237 winedesc.Height = &destHeight;
6238 winedesc.Size = NULL;
6239 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6241 /* Check that the source and destination formats match */
6242 if (srcFormat != destFormat && WINED3DFMT_UNKNOWN != destFormat) {
6243 WARN("(%p) source %p format must match the dest %p format, returning WINED3DERR_INVALIDCALL\n", This, pSourceSurface, pDestinationSurface);
6244 return WINED3DERR_INVALIDCALL;
6245 } else if (WINED3DFMT_UNKNOWN == destFormat) {
6246 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
6247 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
6248 destFormat = srcFormat;
6251 /* Quick if complete copy ... */
6252 if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
6254 if (srcWidth == destWidth && srcHeight == destHeight) {
6255 WINED3DLOCKED_RECT lrSrc;
6256 WINED3DLOCKED_RECT lrDst;
6257 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, NULL, WINED3DLOCK_READONLY);
6258 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, NULL, 0L);
6259 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", srcWidth, srcHeight);
6261 memcpy(lrDst.pBits, lrSrc.pBits, srcSize);
6263 IWineD3DSurface_UnlockRect(pSourceSurface);
6264 IWineD3DSurface_UnlockRect(pDestinationSurface);
6265 TRACE("Unlocked src and dst\n");
6267 } else {
6269 FIXME("Wanted to copy all surfaces but size not compatible, returning WINED3DERR_INVALIDCALL\n");
6270 hr = WINED3DERR_INVALIDCALL;
6273 } else {
6275 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
6277 int bytesPerPixel = ((IWineD3DSurfaceImpl *) pSourceSurface)->bytesPerPixel;
6278 unsigned int i;
6280 /* Copy rect by rect */
6281 for (i = 0; i < cRects; ++i) {
6282 CONST RECT* r = &pSourceRectsArray[i];
6283 CONST POINT* p = &pDestPointsArray[i];
6284 int copyperline;
6285 int j;
6286 WINED3DLOCKED_RECT lrSrc;
6287 WINED3DLOCKED_RECT lrDst;
6288 RECT dest_rect;
6290 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
6291 if (srcFormat == WINED3DFMT_DXT1) {
6292 copyperline = ((r->right - r->left) * bytesPerPixel) / 2; /* DXT1 is half byte per pixel */
6293 } else {
6294 copyperline = ((r->right - r->left) * bytesPerPixel);
6297 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, r, WINED3DLOCK_READONLY);
6298 dest_rect.left = p->x;
6299 dest_rect.top = p->y;
6300 dest_rect.right = p->x + (r->right - r->left);
6301 dest_rect.bottom= p->y + (r->bottom - r->top);
6302 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, &dest_rect, 0L);
6303 TRACE("Locked src and dst\n");
6305 /* Find where to start */
6306 for (j = 0; j < (r->bottom - r->top - 1); ++j) {
6307 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
6309 IWineD3DSurface_UnlockRect(pSourceSurface);
6310 IWineD3DSurface_UnlockRect(pDestinationSurface);
6311 TRACE("Unlocked src and dst\n");
6313 } else {
6314 FIXME("Wanted to copy partial surfaces not implemented, returning WINED3DERR_INVALIDCALL\n");
6315 hr = WINED3DERR_INVALIDCALL;
6319 return hr;
6322 /* Implementation details at http://developer.nvidia.com/attach/6494
6324 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
6325 hmm.. no longer supported use
6326 OpenGL evaluators or tessellate surfaces within your application.
6329 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
6330 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
6331 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6332 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
6333 FIXME("(%p) : Stub\n", This);
6334 return WINED3D_OK;
6338 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
6339 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
6340 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6341 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
6342 FIXME("(%p) : Stub\n", This);
6343 return WINED3D_OK;
6346 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
6347 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6348 TRACE("(%p) Handle(%d)\n", This, Handle);
6349 FIXME("(%p) : Stub\n", This);
6350 return WINED3D_OK;
6353 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
6354 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
6355 fill a surface with a block of color! */
6356 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6357 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
6358 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
6359 IWineD3DSwapChainImpl *container = NULL;
6360 BOOL isRenderTarget = FALSE;
6361 unsigned int width, height;
6362 unsigned int top, left;
6363 unsigned int u, v;
6364 DWORD *data;
6365 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
6367 if (surface->resource.pool != WINED3DPOOL_DEFAULT) {
6368 FIXME("call to colorfill with non WINED3DPOOL_DEFAULT surface\n");
6369 return WINED3DERR_INVALIDCALL;
6372 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
6373 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
6374 if (WINED3DUSAGE_RENDERTARGET & surface->resource.usage) {
6375 /* TODO: make sure we set everything back to the way it was, and context management!
6376 glGetIntegerv(GL_READ_BUFFER, &prev_read);
6377 vcheckGLcall("glIntegerv");
6378 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
6379 vcheckGLcall("glIntegerv");
6381 TRACE("Color fill to render targets may cause some graphics issues\n");
6382 if (pSurface == container->frontBuffer) {
6383 glDrawBuffer(GL_FRONT);
6384 } else {
6385 glDrawBuffer(GL_BACK);
6387 } else {
6388 if (WINED3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
6389 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld\n", surface, surface->resource.usage);
6390 } else {
6391 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
6393 if (container != NULL) {
6394 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
6396 /* we can use GL_STENCIL_INDEX etc...*/
6397 return WINED3D_OK;
6399 if (container != NULL) {
6400 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
6402 isRenderTarget = TRUE;
6404 /* TODO: drawing to GL_FRONT and GL_BACK */
6405 /* TODO: see if things can be speeded up by using the correct
6406 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
6407 if (pRect == NULL) {
6408 top = 0;
6409 left = 0;
6410 width = surface->currentDesc.Width;
6411 height = surface->currentDesc.Height;
6412 } else {
6413 left = pRect->x1;
6414 top = pRect->y1;
6415 width = pRect->x2 - left;
6416 height = pRect->y2 - top;
6419 data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
6420 /* Create a 'line' of color color, in the correct format for the surface */
6421 for (u = 0 ; u < width ; u ++) {
6422 data[u] = color;
6425 ENTER_GL();
6426 if (isRenderTarget == FALSE) {
6427 glDescriptor *glDesc;
6428 IWineD3DSurface_PreLoad(pSurface);
6430 /* draw a block of the coloured line on the sufrace */
6431 IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
6432 for (v = 0 ; v< height;v++) {
6433 glTexSubImage2D(glDesc->target
6434 ,glDesc->level /* level */
6435 ,left
6436 ,top + v
6437 ,width
6438 ,1 /* height */
6439 ,GL_RGBA
6440 ,GL_UNSIGNED_BYTE
6441 ,data
6444 checkGLcall("glTexSubImage2D");
6445 /* clean up */
6446 glDisable(glDesc->target);
6447 } else {
6448 /** FIXME: Using GLClear may be faster **/
6449 glRasterPos2i(left, top);
6450 glPixelZoom((float)width ,(float)height);
6451 glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
6452 checkGLcall("glDrawPixels");
6454 HeapFree(GetProcessHeap(), 0, data);
6455 LEAVE_GL();
6456 return WINED3D_OK;
6460 /* rendertarget and deptth stencil functions */
6461 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
6462 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6464 /* FIXME: Implelent RenderTargetIndex >0 */
6465 if(RenderTargetIndex > 0)
6466 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
6468 *ppRenderTarget = This->renderTarget;
6469 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
6470 /* Note inc ref on returned surface */
6471 if(*ppRenderTarget != NULL)
6472 IWineD3DSurface_AddRef(*ppRenderTarget);
6473 return WINED3D_OK;
6476 HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
6477 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6478 IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
6479 IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
6480 IWineD3DSwapChainImpl *Swapchain;
6481 HRESULT hr;
6483 TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
6485 hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
6486 if(hr != WINED3D_OK) {
6487 ERR("Can't get the swapchain\n");
6488 return hr;
6491 /* Make sure to release the swapchain */
6492 IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
6494 if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
6495 ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6496 return WINED3DERR_INVALIDCALL;
6498 else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
6499 ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6500 return WINED3DERR_INVALIDCALL;
6503 if(Swapchain->frontBuffer != Front) {
6504 TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
6506 if(Swapchain->frontBuffer)
6507 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
6508 Swapchain->frontBuffer = Front;
6510 if(Swapchain->frontBuffer) {
6511 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
6514 if(Swapchain->backBuffer != Back) {
6515 TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
6516 ENTER_GL();
6517 if(!Swapchain->backBuffer) {
6518 /* GL was told to draw to the front buffer at creation,
6519 * undo that
6521 glDrawBuffer(GL_BACK);
6522 checkGLcall("glDrawBuffer(GL_BACK)");
6523 } else if (!Back) {
6524 /* That makes problems - disable for now */
6525 /* glDrawBuffer(GL_FRONT); */
6526 checkGLcall("glDrawBuffer(GL_FRONT)");
6528 LEAVE_GL();
6530 if(Swapchain->backBuffer)
6531 IWineD3DSurface_SetContainer(Swapchain->backBuffer, NULL);
6532 Swapchain->backBuffer = Back;
6534 if(Swapchain->backBuffer) {
6535 IWineD3DSurface_SetContainer(Swapchain->backBuffer, (IWineD3DBase *) Swapchain);
6540 return WINED3D_OK;
6543 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
6544 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6545 *ppZStencilSurface = This->depthStencilBuffer;
6546 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
6548 if(*ppZStencilSurface != NULL) {
6549 /* Note inc ref on returned surface */
6550 IWineD3DSurface_AddRef(*ppZStencilSurface);
6552 return WINED3D_OK;
6555 /* internal static helper functions */
6556 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
6557 IWineD3DSurface *RenderSurface);
6559 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
6560 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6561 HRESULT hr = WINED3D_OK;
6562 WINED3DVIEWPORT viewport;
6564 TRACE("(%p) Swapping rendertarget\n",This);
6565 if (RenderTargetIndex > 0) {
6566 FIXME("(%p) Render targets other than the first are not supported\n",This);
6567 RenderTargetIndex = 0;
6570 /* MSDN says that null disables the render target
6571 but a device must always be associated with a render target
6572 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
6574 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
6575 for more details
6577 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
6578 FIXME("Trying to set render target 0 to NULL\n");
6579 return WINED3DERR_INVALIDCALL;
6581 /* TODO: replace Impl* usage with interface usage */
6582 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
6583 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);
6584 return WINED3DERR_INVALIDCALL;
6586 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
6587 * builds, but I think wine counts as a 'debug' build for now.
6588 ******************************/
6589 /* If we are trying to set what we already have, don't bother */
6590 if (pRenderTarget == This->renderTarget) {
6591 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6592 } else {
6593 /* Otherwise, set the render target up */
6595 if (FALSE == This->sceneEnded) {
6596 IWineD3DDevice_EndScene(iface);
6598 TRACE("clearing renderer\n");
6599 /* IWineD3DDeviceImpl_CleanRender(iface); */
6600 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6601 depending on the renter target implementation being used.
6602 A shared context implementation will share all buffers between all rendertargets (including swapchains),
6603 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6604 stencil buffer and incure an extra memory overhead */
6605 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
6608 if (SUCCEEDED(hr)) {
6609 /* Finally, reset the viewport as the MSDN states. */
6610 /* TODO: Replace impl usage */
6611 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
6612 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
6613 viewport.X = 0;
6614 viewport.Y = 0;
6615 viewport.MaxZ = 1.0f;
6616 viewport.MinZ = 0.0f;
6617 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
6618 } else {
6619 FIXME("Unknown error setting the render target\n");
6621 This->sceneEnded = FALSE;
6622 return hr;
6625 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
6626 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6627 HRESULT hr = WINED3D_OK;
6628 IWineD3DSurface *tmp;
6630 TRACE("(%p) Swapping z-buffer\n",This);
6632 if (pNewZStencil == This->stencilBufferTarget) {
6633 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6634 } else {
6635 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6636 * depending on the renter target implementation being used.
6637 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
6638 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6639 * stencil buffer and incure an extra memory overhead
6640 ******************************************************/
6643 tmp = This->stencilBufferTarget;
6644 This->stencilBufferTarget = pNewZStencil;
6645 /* should we be calling the parent or the wined3d surface? */
6646 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
6647 if (NULL != tmp) IWineD3DSurface_Release(tmp);
6648 hr = WINED3D_OK;
6649 /** TODO: glEnable/glDisable on depth/stencil depending on
6650 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
6651 **********************************************************/
6654 return hr;
6658 #ifdef GL_VERSION_1_3
6659 /* Internal functions not in DirectX */
6660 /** TODO: move this off to the opengl context manager
6661 *(the swapchain doesn't need to know anything about offscreen rendering!)
6662 ****************************************************/
6664 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
6666 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6668 TRACE("(%p), %p\n", This, swapchain);
6670 if (swapchain->win != swapchain->drawable) {
6671 /* Set everything back the way it ws */
6672 swapchain->render_ctx = swapchain->glCtx;
6673 swapchain->drawable = swapchain->win;
6675 return WINED3D_OK;
6678 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
6679 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
6680 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6681 int i;
6682 unsigned int width;
6683 unsigned int height;
6684 WINED3DFORMAT format;
6685 WINED3DSURFACE_DESC surfaceDesc;
6686 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
6687 surfaceDesc.Width = &width;
6688 surfaceDesc.Height = &height;
6689 surfaceDesc.Format = &format;
6690 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
6691 *context = NULL;
6692 /* I need a get width/height function (and should do something with the format) */
6693 for (i = 0; i < CONTEXT_CACHE; ++i) {
6694 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
6695 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
6696 the pSurface can be set to 0 allowing it to be reused from cache **/
6697 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
6698 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
6699 *context = &This->contextCache[i];
6700 break;
6702 if (This->contextCache[i].Width == 0) {
6703 This->contextCache[i].pSurface = pSurface;
6704 This->contextCache[i].Width = width;
6705 This->contextCache[i].Height = height;
6706 *context = &This->contextCache[i];
6707 break;
6710 if (i == CONTEXT_CACHE) {
6711 int minUsage = 0x7FFFFFFF; /* MAX_INT */
6712 glContext *dropContext = 0;
6713 for (i = 0; i < CONTEXT_CACHE; i++) {
6714 if (This->contextCache[i].usedcount < minUsage) {
6715 dropContext = &This->contextCache[i];
6716 minUsage = This->contextCache[i].usedcount;
6719 /* clean up the context (this doesn't work for ATI at the moment */
6720 #if 0
6721 glXDestroyContext(swapchain->display, dropContext->context);
6722 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
6723 #endif
6724 FIXME("Leak\n");
6725 dropContext->Width = 0;
6726 dropContext->pSurface = pSurface;
6727 *context = dropContext;
6728 } else {
6729 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
6730 for (i = 0; i < CONTEXT_CACHE; i++) {
6731 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
6735 if (*context != NULL)
6736 return WINED3D_OK;
6737 else
6738 return E_OUTOFMEMORY;
6740 #endif
6742 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
6743 * the functionality needs splitting up so that we don't do more than we should do.
6744 * this only seems to impact performance a little.
6745 ******************************/
6746 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
6747 IWineD3DSurface *RenderSurface) {
6748 HRESULT ret = WINED3DERR_INVALIDCALL;
6751 * Currently only active for GLX >= 1.3
6752 * for others versions we'll have to use GLXPixmaps
6754 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
6755 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
6756 * so only check OpenGL version
6757 * ..........................
6758 * I don't believe that it is a problem with NVidia headers,
6759 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
6760 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
6761 * ATI Note:
6762 * Your application will report GLX version 1.2 on glXQueryVersion.
6763 * However, it is safe to call the GLX 1.3 functions as described below.
6765 #if defined(GL_VERSION_1_3)
6767 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6768 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
6769 IWineD3DSurface *tmp;
6770 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
6771 GLXFBConfig* cfgs = NULL;
6772 int nCfgs = 0;
6773 int attribs[256];
6774 int nAttribs = 0;
6775 IWineD3DSwapChain *currentSwapchain;
6776 IWineD3DSwapChainImpl *swapchain;
6777 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
6778 * but switch them off if the StencilSurface is set to NULL
6779 ** *********************************************************/
6780 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
6781 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
6783 /**TODO:
6784 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
6785 it StencilSurface != NULL && zBufferTarget == NULL switch it on
6788 #define PUSH1(att) attribs[nAttribs++] = (att);
6789 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
6791 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
6793 /** TODO: remove the reff to Impl (context manager should fix this!) **/
6794 IWineD3DSwapChainImpl *impSwapChain;
6795 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
6796 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
6797 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
6800 ENTER_GL();
6802 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
6803 PUSH2(GLX_X_RENDERABLE, TRUE);
6804 PUSH2(GLX_DOUBLEBUFFER, TRUE);
6805 TRACE("calling makeglcfg\n");
6806 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
6807 PUSH1(None);
6809 TRACE("calling chooseFGConfig\n");
6810 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
6811 attribs, &nCfgs);
6813 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
6814 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
6815 why we failed and only show this message once! */
6816 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"); /**/
6817 nAttribs = 0;
6818 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
6819 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
6820 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
6821 PUSH2(GLX_DOUBLEBUFFER, FALSE);
6822 TRACE("calling makeglcfg\n");
6823 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
6824 PUSH1(None);
6825 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
6826 attribs, &nCfgs);
6829 if (NULL != cfgs) {
6830 #ifdef EXTRA_TRACES
6831 int i;
6832 for (i = 0; i < nCfgs; ++i) {
6833 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
6834 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
6835 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
6838 if (NULL != This->renderTarget) {
6839 glFlush();
6840 vcheckGLcall("glFlush");
6841 /** This is only useful if the old render target was a swapchain,
6842 * we need to supercede this with a function that displays
6843 * the current buffer on the screen. This is easy to do in glx1.3 but
6844 * we need to do copy-write pixels in glx 1.2.
6845 ************************************************/
6846 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
6848 printf("Hit Enter to get next frame ...\n");
6849 getchar();
6851 #endif
6854 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&currentSwapchain) != WINED3D_OK) {
6855 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
6856 IWineD3DDevice_GetSwapChain(iface, 0, &currentSwapchain);
6860 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
6861 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
6862 **********************************************************************/
6863 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == WINED3D_OK) {
6864 /* We also need to make sure that the lights &co are also in the context of the swapchains */
6865 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
6866 TRACE("making swapchain active\n");
6867 if (RenderSurface != This->renderTarget) {
6868 if (RenderSurface == swapchain->backBuffer) {
6869 } else {
6870 /* This could be flagged so that some operations work directly with the front buffer */
6871 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
6873 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
6874 == False) {
6875 TRACE("Error in setting current context: context %p drawable %ld !\n",
6876 impSwapChain->glCtx, impSwapChain->win);
6879 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
6881 checkGLcall("glXMakeContextCurrent");
6883 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
6885 else if (pbuffer_support == TRUE && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
6887 /** ********************************************************************
6888 * This is a quickly hacked out implementation of offscreen textures.
6889 * It will work in most cases but there may be problems if the client
6890 * modifies the texture directly, or expects the contents of the rendertarget
6891 * to be persistent.
6893 * There are some real speed vs compatibility issues here:
6894 * we should really use a new context for every texture, but that eats ram.
6895 * we should also be restoring the texture to the pbuffer but that eats CPU
6896 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
6897 * but if this means reusing the display backbuffer then we need to make sure that
6898 * states are correctly preserved.
6899 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
6900 * and gain a good performance increase at the cost of compatibility.
6901 * I would suggest that, when this is the case, a user configurable flag be made
6902 * available, allowing the user to choose the best emulated experience for them.
6903 *********************************************************************/
6905 XVisualInfo *visinfo;
6906 glContext *newContext;
6908 /* Here were using a shared context model */
6909 if (WINED3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
6910 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6913 /* If the context doesn't exist then create a new one */
6914 /* TODO: This should really be part of findGlContext */
6915 if (NULL == newContext->context) {
6917 TRACE("making new buffer\n");
6918 nAttribs = 0;
6919 PUSH2(GLX_PBUFFER_WIDTH, newContext->Width);
6920 PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
6921 PUSH1(None);
6923 newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
6925 /** ****************************************
6926 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
6927 *they note:
6928 * In future releases, we may provide the calls glXCreateNewContext,
6929 * glXQueryDrawable and glXMakeContextCurrent.
6930 * so until then we have to use glXGetVisualFromFBConfig &co..
6931 ********************************************/
6934 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
6935 if (!visinfo) {
6936 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
6937 } else {
6938 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
6939 XFree(visinfo);
6942 if (NULL == newContext || NULL == newContext->context) {
6943 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6944 } else {
6945 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
6946 if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
6947 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
6950 /* Clean up the old context */
6951 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
6952 /* Set the current context of the swapchain to the new context */
6953 impSwapChain->drawable = newContext->drawable;
6954 impSwapChain->render_ctx = newContext->context;
6958 #if 1 /* Apply the stateblock to the new context
6959 FIXME: This is a bit of a hack, each context should know it's own state,
6960 the directX current directX state should then be applied to the context */
6962 BOOL oldRecording;
6963 IWineD3DStateBlockImpl *oldUpdateStateBlock;
6964 oldUpdateStateBlock = This->updateStateBlock;
6965 oldRecording= This->isRecordingState;
6966 This->isRecordingState = FALSE;
6967 This->updateStateBlock = This->stateBlock;
6968 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
6970 This->isRecordingState = oldRecording;
6971 This->updateStateBlock = oldUpdateStateBlock;
6973 #endif
6976 /* clean up the current rendertargets swapchain (if it belonged to one) */
6977 if (currentSwapchain != NULL) {
6978 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
6981 /* Were done with the opengl context management, setup the rendertargets */
6983 tmp = This->renderTarget;
6984 This->renderTarget = RenderSurface;
6985 IWineD3DSurface_AddRef(This->renderTarget);
6986 IWineD3DSurface_Release(tmp);
6991 DWORD value;
6992 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
6993 /* Check that the container is not a swapchain member */
6995 IWineD3DSwapChain *tmpSwapChain;
6996 if (WINED3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
6997 This->renderUpsideDown = TRUE;
6998 }else{
6999 This->renderUpsideDown = FALSE;
7000 IWineD3DSwapChain_Release(tmpSwapChain);
7002 /* Force updating the cull mode */
7003 TRACE("setting render state\n");
7004 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
7005 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
7007 /* Force updating projection matrix */
7008 This->last_was_rhw = FALSE;
7009 This->proj_valid = FALSE;
7012 ret = WINED3D_OK;
7014 if (cfgs != NULL) {
7015 XFree(cfgs);
7016 } else {
7017 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
7018 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
7021 #undef PUSH1
7022 #undef PUSH2
7023 if ( NULL != impSwapChain) {
7024 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
7026 LEAVE_GL();
7028 #endif
7029 return ret;
7032 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
7033 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
7034 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7035 /* TODO: the use of Impl is deprecated. */
7036 /* some basic validation checks */
7037 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
7039 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
7041 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
7042 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
7043 return WINED3DERR_INVALIDCALL;
7045 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
7046 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
7047 return WINED3DERR_INVALIDCALL;
7049 /* TODO: make the cursor 'real' */
7051 This->xHotSpot = XHotSpot;
7052 This->yHotSpot = YHotSpot;
7054 return WINED3D_OK;
7057 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
7058 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7059 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
7061 This->xScreenSpace = XScreenSpace;
7062 This->yScreenSpace = YScreenSpace;
7064 return;
7068 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
7069 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7070 TRACE("(%p) : visible(%d)\n", This, bShow);
7072 This->bCursorVisible = bShow;
7074 return WINED3D_OK;
7077 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
7078 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7079 TRACE("(%p) : state (%lu)\n", This, This->state);
7080 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
7081 switch (This->state) {
7082 case WINED3D_OK:
7083 return WINED3D_OK;
7084 case WINED3DERR_DEVICELOST:
7086 ResourceList *resourceList = This->resources;
7087 while (NULL != resourceList) {
7088 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
7089 return WINED3DERR_DEVICENOTRESET;
7090 resourceList = resourceList->next;
7092 return WINED3DERR_DEVICELOST;
7094 case WINED3DERR_DRIVERINTERNALERROR:
7095 return WINED3DERR_DRIVERINTERNALERROR;
7098 /* Unknown state */
7099 return WINED3DERR_DRIVERINTERNALERROR;
7103 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
7104 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7105 /** FIXME: Resource tracking needs to be done,
7106 * The closes we can do to this is set the priorities of all managed textures low
7107 * and then reset them.
7108 ***********************************************************/
7109 FIXME("(%p) : stub\n", This);
7110 return WINED3D_OK;
7113 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
7114 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7115 /** FIXME: Resource trascking needs to be done.
7116 * in effect this pulls all non only default
7117 * textures out of video memory and deletes all glTextures (glDeleteTextures)
7118 * and should clear down the context and set it up according to pPresentationParameters
7119 ***********************************************************/
7120 FIXME("(%p) : stub\n", This);
7121 return WINED3D_OK;
7124 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
7125 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7126 /** FIXME: always true at the moment **/
7127 if(bEnableDialogs == FALSE) {
7128 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
7130 return WINED3D_OK;
7134 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
7135 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7136 TRACE("(%p) : pParameters %p\n", This, pParameters);
7138 *pParameters = This->createParms;
7139 return WINED3D_OK;
7142 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
7143 IWineD3DSwapChain *swapchain;
7144 HRESULT hrc = WINED3D_OK;
7146 TRACE("Relaying to swapchain\n");
7148 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7149 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
7150 IWineD3DSwapChain_Release(swapchain);
7152 return;
7155 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
7156 IWineD3DSwapChain *swapchain;
7157 HRESULT hrc = WINED3D_OK;
7159 TRACE("Relaying to swapchain\n");
7161 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7162 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
7163 IWineD3DSwapChain_Release(swapchain);
7165 return;
7169 /** ********************************************************
7170 * Notification functions
7171 ** ********************************************************/
7172 /** This function must be called in the release of a resource when ref == 0,
7173 * the contents of resource must still be correct,
7174 * any handels to other resource held by the caller must be closed
7175 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
7176 *****************************************************/
7177 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7178 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7179 ResourceList* resourceList;
7181 TRACE("(%p) : resource %p\n", This, resource);
7182 #if 0
7183 EnterCriticalSection(&resourceStoreCriticalSection);
7184 #endif
7185 /* add a new texture to the frot of the linked list */
7186 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
7187 resourceList->resource = resource;
7189 /* Get the old head */
7190 resourceList->next = This->resources;
7192 This->resources = resourceList;
7193 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
7195 #if 0
7196 LeaveCriticalSection(&resourceStoreCriticalSection);
7197 #endif
7198 return;
7201 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7202 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7203 ResourceList* resourceList = NULL;
7204 ResourceList* previousResourceList = NULL;
7206 TRACE("(%p) : resource %p\n", This, resource);
7208 #if 0
7209 EnterCriticalSection(&resourceStoreCriticalSection);
7210 #endif
7211 resourceList = This->resources;
7213 while (resourceList != NULL) {
7214 if(resourceList->resource == resource) break;
7215 previousResourceList = resourceList;
7216 resourceList = resourceList->next;
7219 if (resourceList == NULL) {
7220 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
7221 #if 0
7222 LeaveCriticalSection(&resourceStoreCriticalSection);
7223 #endif
7224 return;
7225 } else {
7226 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
7228 /* make sure we don't leave a hole in the list */
7229 if (previousResourceList != NULL) {
7230 previousResourceList->next = resourceList->next;
7231 } else {
7232 This->resources = resourceList->next;
7235 #if 0
7236 LeaveCriticalSection(&resourceStoreCriticalSection);
7237 #endif
7238 return;
7242 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
7243 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7244 int counter;
7246 TRACE("(%p) : resource %p\n", This, resource);
7247 switch(IWineD3DResource_GetType(resource)){
7248 case WINED3DRTYPE_SURFACE:
7249 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
7250 break;
7251 case WINED3DRTYPE_TEXTURE:
7252 case WINED3DRTYPE_CUBETEXTURE:
7253 case WINED3DRTYPE_VOLUMETEXTURE:
7254 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
7255 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7256 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7257 This->stateBlock->textures[counter] = NULL;
7259 if (This->updateStateBlock != This->stateBlock ){
7260 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7261 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7262 This->updateStateBlock->textures[counter] = NULL;
7266 break;
7267 case WINED3DRTYPE_VOLUME:
7268 /* TODO: nothing really? */
7269 break;
7270 case WINED3DRTYPE_VERTEXBUFFER:
7271 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
7273 int streamNumber;
7274 TRACE("Cleaning up stream pointers\n");
7276 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
7277 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
7278 FINDOUT: should changes.streamSource[StreamNumber] be set ?
7280 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7281 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
7282 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
7283 This->updateStateBlock->streamSource[streamNumber] = 0;
7284 /* Set changed flag? */
7287 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) */
7288 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
7289 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
7290 This->stateBlock->streamSource[streamNumber] = 0;
7293 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
7294 else { /* This shouldn't happen */
7295 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
7297 #endif
7301 break;
7302 case WINED3DRTYPE_INDEXBUFFER:
7303 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
7304 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7305 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7306 This->updateStateBlock->pIndexData = NULL;
7309 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
7310 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7311 This->stateBlock->pIndexData = NULL;
7315 break;
7316 default:
7317 FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
7318 break;
7322 /* Remove the resoruce from the resourceStore */
7323 IWineD3DDeviceImpl_RemoveResource(iface, resource);
7325 TRACE("Resource released\n");
7330 /** This function is to be called by the swapchain when it is released and it's ref = 0
7331 *****************************************************/
7332 void WINAPI IWineD3DDeviceImpl_SwapChainReleased(IWineD3DDevice *iface, IWineD3DSwapChain *swapChain){
7333 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7334 SwapChainList **nextSwapchain;
7335 nextSwapchain = &This->swapchains;
7337 /* Check to see if the swapchian is being used as the render target */
7338 if (This->renderTarget != NULL) {
7339 IWineD3DSurface *swapchainBackBuffer;
7341 IWineD3DSwapChain_GetBackBuffer(swapChain, 0 ,( D3DBACKBUFFER_TYPE) 0, &swapchainBackBuffer);
7342 if (This->renderTarget == swapchainBackBuffer) {
7343 /* Don't know what to do, so warn and carry on as usual (which in this case leaves the renderterget in limbo) */
7344 FIXME("Atempting to release a swapchain that is currently beuing used as a render target, behaviour is undefined\n");
7348 /* Go through the swapchain list and try to find the swapchain being released */
7349 while(*nextSwapchain != NULL && (*nextSwapchain)->swapchain != swapChain) {
7350 nextSwapchain = &(*nextSwapchain)->next;
7353 /* Check to see if we found the swapchain */
7354 if (NULL != *nextSwapchain) {
7355 /* We found the swapchain so remove it from the list */
7356 TRACE("(%p) releasing swapchain(%p)\n", iface, swapChain);
7357 HeapFree(GetProcessHeap(), 0 , *nextSwapchain);
7358 *nextSwapchain = (*nextSwapchain)->next;
7359 } else {
7360 /* We didn't find the swapchain on the list, this can only heppen because of a programming error in wined3d */
7361 FIXME("(%p) Attempting to release a swapchain (%p) that hasn't been stored\n", iface, swapChain);
7364 TRACE("swapchain (%p) released\n", swapChain);
7365 return;
7368 /**********************************************************
7369 * IWineD3DDevice VTbl follows
7370 **********************************************************/
7372 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
7374 /*** IUnknown methods ***/
7375 IWineD3DDeviceImpl_QueryInterface,
7376 IWineD3DDeviceImpl_AddRef,
7377 IWineD3DDeviceImpl_Release,
7378 /*** IWineD3DDevice methods ***/
7379 IWineD3DDeviceImpl_GetParent,
7380 /*** Creation methods**/
7381 IWineD3DDeviceImpl_CreateVertexBuffer,
7382 IWineD3DDeviceImpl_CreateIndexBuffer,
7383 IWineD3DDeviceImpl_CreateStateBlock,
7384 IWineD3DDeviceImpl_CreateSurface,
7385 IWineD3DDeviceImpl_CreateTexture,
7386 IWineD3DDeviceImpl_CreateVolumeTexture,
7387 IWineD3DDeviceImpl_CreateVolume,
7388 IWineD3DDeviceImpl_CreateCubeTexture,
7389 IWineD3DDeviceImpl_CreateQuery,
7390 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
7391 IWineD3DDeviceImpl_CreateVertexDeclaration,
7392 IWineD3DDeviceImpl_CreateVertexShader,
7393 IWineD3DDeviceImpl_CreatePixelShader,
7394 IWineD3DDeviceImpl_CreatePalette,
7395 /*** Odd functions **/
7396 IWineD3DDeviceImpl_Init3D,
7397 IWineD3DDeviceImpl_Uninit3D,
7398 IWineD3DDeviceImpl_EnumDisplayModes,
7399 IWineD3DDeviceImpl_EvictManagedResources,
7400 IWineD3DDeviceImpl_GetAvailableTextureMem,
7401 IWineD3DDeviceImpl_GetBackBuffer,
7402 IWineD3DDeviceImpl_GetCreationParameters,
7403 IWineD3DDeviceImpl_GetDeviceCaps,
7404 IWineD3DDeviceImpl_GetDirect3D,
7405 IWineD3DDeviceImpl_GetDisplayMode,
7406 IWineD3DDeviceImpl_SetDisplayMode,
7407 IWineD3DDeviceImpl_GetHWND,
7408 IWineD3DDeviceImpl_SetHWND,
7409 IWineD3DDeviceImpl_GetNumberOfSwapChains,
7410 IWineD3DDeviceImpl_GetRasterStatus,
7411 IWineD3DDeviceImpl_GetSwapChain,
7412 IWineD3DDeviceImpl_Reset,
7413 IWineD3DDeviceImpl_SetDialogBoxMode,
7414 IWineD3DDeviceImpl_SetCursorProperties,
7415 IWineD3DDeviceImpl_SetCursorPosition,
7416 IWineD3DDeviceImpl_ShowCursor,
7417 IWineD3DDeviceImpl_TestCooperativeLevel,
7418 IWineD3DDeviceImpl_EnumZBufferFormats,
7419 IWineD3DDeviceImpl_EnumTextureFormats,
7420 /*** Getters and setters **/
7421 IWineD3DDeviceImpl_SetClipPlane,
7422 IWineD3DDeviceImpl_GetClipPlane,
7423 IWineD3DDeviceImpl_SetClipStatus,
7424 IWineD3DDeviceImpl_GetClipStatus,
7425 IWineD3DDeviceImpl_SetCurrentTexturePalette,
7426 IWineD3DDeviceImpl_GetCurrentTexturePalette,
7427 IWineD3DDeviceImpl_SetDepthStencilSurface,
7428 IWineD3DDeviceImpl_GetDepthStencilSurface,
7429 IWineD3DDeviceImpl_SetFVF,
7430 IWineD3DDeviceImpl_GetFVF,
7431 IWineD3DDeviceImpl_SetGammaRamp,
7432 IWineD3DDeviceImpl_GetGammaRamp,
7433 IWineD3DDeviceImpl_SetIndices,
7434 IWineD3DDeviceImpl_GetIndices,
7435 IWineD3DDeviceImpl_SetLight,
7436 IWineD3DDeviceImpl_GetLight,
7437 IWineD3DDeviceImpl_SetLightEnable,
7438 IWineD3DDeviceImpl_GetLightEnable,
7439 IWineD3DDeviceImpl_SetMaterial,
7440 IWineD3DDeviceImpl_GetMaterial,
7441 IWineD3DDeviceImpl_SetNPatchMode,
7442 IWineD3DDeviceImpl_GetNPatchMode,
7443 IWineD3DDeviceImpl_SetPaletteEntries,
7444 IWineD3DDeviceImpl_GetPaletteEntries,
7445 IWineD3DDeviceImpl_SetPixelShader,
7446 IWineD3DDeviceImpl_GetPixelShader,
7447 IWineD3DDeviceImpl_SetPixelShaderConstant,
7448 IWineD3DDeviceImpl_GetPixelShaderConstant,
7449 IWineD3DDeviceImpl_SetPixelShaderConstantB,
7450 IWineD3DDeviceImpl_GetPixelShaderConstantB,
7451 IWineD3DDeviceImpl_SetPixelShaderConstantI,
7452 IWineD3DDeviceImpl_GetPixelShaderConstantI,
7453 IWineD3DDeviceImpl_SetPixelShaderConstantF,
7454 IWineD3DDeviceImpl_GetPixelShaderConstantF,
7455 IWineD3DDeviceImpl_SetPixelShaderConstantN,
7456 IWineD3DDeviceImpl_SetRenderState,
7457 IWineD3DDeviceImpl_GetRenderState,
7458 IWineD3DDeviceImpl_SetRenderTarget,
7459 IWineD3DDeviceImpl_GetRenderTarget,
7460 IWineD3DDeviceImpl_SetFrontBackBuffers,
7461 IWineD3DDeviceImpl_SetSamplerState,
7462 IWineD3DDeviceImpl_GetSamplerState,
7463 IWineD3DDeviceImpl_SetScissorRect,
7464 IWineD3DDeviceImpl_GetScissorRect,
7465 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
7466 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
7467 IWineD3DDeviceImpl_SetStreamSource,
7468 IWineD3DDeviceImpl_GetStreamSource,
7469 IWineD3DDeviceImpl_SetStreamSourceFreq,
7470 IWineD3DDeviceImpl_GetStreamSourceFreq,
7471 IWineD3DDeviceImpl_SetTexture,
7472 IWineD3DDeviceImpl_GetTexture,
7473 IWineD3DDeviceImpl_SetTextureStageState,
7474 IWineD3DDeviceImpl_GetTextureStageState,
7475 IWineD3DDeviceImpl_SetTransform,
7476 IWineD3DDeviceImpl_GetTransform,
7477 IWineD3DDeviceImpl_SetVertexDeclaration,
7478 IWineD3DDeviceImpl_GetVertexDeclaration,
7479 IWineD3DDeviceImpl_SetVertexShader,
7480 IWineD3DDeviceImpl_GetVertexShader,
7481 IWineD3DDeviceImpl_SetVertexShaderConstant,
7482 IWineD3DDeviceImpl_GetVertexShaderConstant,
7483 IWineD3DDeviceImpl_SetVertexShaderConstantB,
7484 IWineD3DDeviceImpl_GetVertexShaderConstantB,
7485 IWineD3DDeviceImpl_SetVertexShaderConstantI,
7486 IWineD3DDeviceImpl_GetVertexShaderConstantI,
7487 IWineD3DDeviceImpl_SetVertexShaderConstantF,
7488 IWineD3DDeviceImpl_GetVertexShaderConstantF,
7489 IWineD3DDeviceImpl_SetVertexShaderConstantN,
7490 IWineD3DDeviceImpl_SetViewport,
7491 IWineD3DDeviceImpl_GetViewport,
7492 IWineD3DDeviceImpl_MultiplyTransform,
7493 IWineD3DDeviceImpl_ValidateDevice,
7494 IWineD3DDeviceImpl_ProcessVertices,
7495 /*** State block ***/
7496 IWineD3DDeviceImpl_BeginStateBlock,
7497 IWineD3DDeviceImpl_EndStateBlock,
7498 /*** Scene management ***/
7499 IWineD3DDeviceImpl_BeginScene,
7500 IWineD3DDeviceImpl_EndScene,
7501 IWineD3DDeviceImpl_Present,
7502 IWineD3DDeviceImpl_Clear,
7503 /*** Drawing ***/
7504 IWineD3DDeviceImpl_DrawPrimitive,
7505 IWineD3DDeviceImpl_DrawIndexedPrimitive,
7506 IWineD3DDeviceImpl_DrawPrimitiveUP,
7507 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
7508 IWineD3DDeviceImpl_DrawPrimitiveStrided,
7509 IWineD3DDeviceImpl_DrawRectPatch,
7510 IWineD3DDeviceImpl_DrawTriPatch,
7511 IWineD3DDeviceImpl_DeletePatch,
7512 IWineD3DDeviceImpl_ColorFill,
7513 IWineD3DDeviceImpl_UpdateTexture,
7514 IWineD3DDeviceImpl_UpdateSurface,
7515 IWineD3DDeviceImpl_CopyRects,
7516 IWineD3DDeviceImpl_StretchRect,
7517 IWineD3DDeviceImpl_GetRenderTargetData,
7518 IWineD3DDeviceImpl_GetFrontBufferData,
7519 /*** Internal use IWineD3DDevice methods ***/
7520 IWineD3DDeviceImpl_SetupTextureStates,
7521 /*** object tracking ***/
7522 IWineD3DDeviceImpl_SwapChainReleased,
7523 IWineD3DDeviceImpl_ResourceReleased
7527 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
7528 WINED3DRS_ALPHABLENDENABLE ,
7529 WINED3DRS_ALPHAFUNC ,
7530 WINED3DRS_ALPHAREF ,
7531 WINED3DRS_ALPHATESTENABLE ,
7532 WINED3DRS_BLENDOP ,
7533 WINED3DRS_COLORWRITEENABLE ,
7534 WINED3DRS_DESTBLEND ,
7535 WINED3DRS_DITHERENABLE ,
7536 WINED3DRS_FILLMODE ,
7537 WINED3DRS_FOGDENSITY ,
7538 WINED3DRS_FOGEND ,
7539 WINED3DRS_FOGSTART ,
7540 WINED3DRS_LASTPIXEL ,
7541 WINED3DRS_SHADEMODE ,
7542 WINED3DRS_SRCBLEND ,
7543 WINED3DRS_STENCILENABLE ,
7544 WINED3DRS_STENCILFAIL ,
7545 WINED3DRS_STENCILFUNC ,
7546 WINED3DRS_STENCILMASK ,
7547 WINED3DRS_STENCILPASS ,
7548 WINED3DRS_STENCILREF ,
7549 WINED3DRS_STENCILWRITEMASK ,
7550 WINED3DRS_STENCILZFAIL ,
7551 WINED3DRS_TEXTUREFACTOR ,
7552 WINED3DRS_WRAP0 ,
7553 WINED3DRS_WRAP1 ,
7554 WINED3DRS_WRAP2 ,
7555 WINED3DRS_WRAP3 ,
7556 WINED3DRS_WRAP4 ,
7557 WINED3DRS_WRAP5 ,
7558 WINED3DRS_WRAP6 ,
7559 WINED3DRS_WRAP7 ,
7560 WINED3DRS_ZENABLE ,
7561 WINED3DRS_ZFUNC ,
7562 WINED3DRS_ZWRITEENABLE
7565 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
7566 WINED3DTSS_ADDRESSW ,
7567 WINED3DTSS_ALPHAARG0 ,
7568 WINED3DTSS_ALPHAARG1 ,
7569 WINED3DTSS_ALPHAARG2 ,
7570 WINED3DTSS_ALPHAOP ,
7571 WINED3DTSS_BUMPENVLOFFSET ,
7572 WINED3DTSS_BUMPENVLSCALE ,
7573 WINED3DTSS_BUMPENVMAT00 ,
7574 WINED3DTSS_BUMPENVMAT01 ,
7575 WINED3DTSS_BUMPENVMAT10 ,
7576 WINED3DTSS_BUMPENVMAT11 ,
7577 WINED3DTSS_COLORARG0 ,
7578 WINED3DTSS_COLORARG1 ,
7579 WINED3DTSS_COLORARG2 ,
7580 WINED3DTSS_COLOROP ,
7581 WINED3DTSS_RESULTARG ,
7582 WINED3DTSS_TEXCOORDINDEX ,
7583 WINED3DTSS_TEXTURETRANSFORMFLAGS
7586 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
7587 WINED3DSAMP_ADDRESSU ,
7588 WINED3DSAMP_ADDRESSV ,
7589 WINED3DSAMP_ADDRESSW ,
7590 WINED3DSAMP_BORDERCOLOR ,
7591 WINED3DSAMP_MAGFILTER ,
7592 WINED3DSAMP_MINFILTER ,
7593 WINED3DSAMP_MIPFILTER ,
7594 WINED3DSAMP_MIPMAPLODBIAS ,
7595 WINED3DSAMP_MAXMIPLEVEL ,
7596 WINED3DSAMP_MAXANISOTROPY ,
7597 WINED3DSAMP_SRGBTEXTURE ,
7598 WINED3DSAMP_ELEMENTINDEX
7601 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
7602 WINED3DRS_AMBIENT ,
7603 WINED3DRS_AMBIENTMATERIALSOURCE ,
7604 WINED3DRS_CLIPPING ,
7605 WINED3DRS_CLIPPLANEENABLE ,
7606 WINED3DRS_COLORVERTEX ,
7607 WINED3DRS_DIFFUSEMATERIALSOURCE ,
7608 WINED3DRS_EMISSIVEMATERIALSOURCE ,
7609 WINED3DRS_FOGDENSITY ,
7610 WINED3DRS_FOGEND ,
7611 WINED3DRS_FOGSTART ,
7612 WINED3DRS_FOGTABLEMODE ,
7613 WINED3DRS_FOGVERTEXMODE ,
7614 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
7615 WINED3DRS_LIGHTING ,
7616 WINED3DRS_LOCALVIEWER ,
7617 WINED3DRS_MULTISAMPLEANTIALIAS ,
7618 WINED3DRS_MULTISAMPLEMASK ,
7619 WINED3DRS_NORMALIZENORMALS ,
7620 WINED3DRS_PATCHEDGESTYLE ,
7621 WINED3DRS_POINTSCALE_A ,
7622 WINED3DRS_POINTSCALE_B ,
7623 WINED3DRS_POINTSCALE_C ,
7624 WINED3DRS_POINTSCALEENABLE ,
7625 WINED3DRS_POINTSIZE ,
7626 WINED3DRS_POINTSIZE_MAX ,
7627 WINED3DRS_POINTSIZE_MIN ,
7628 WINED3DRS_POINTSPRITEENABLE ,
7629 WINED3DRS_RANGEFOGENABLE ,
7630 WINED3DRS_SPECULARMATERIALSOURCE ,
7631 WINED3DRS_TWEENFACTOR ,
7632 WINED3DRS_VERTEXBLEND
7635 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
7636 WINED3DTSS_TEXCOORDINDEX ,
7637 WINED3DTSS_TEXTURETRANSFORMFLAGS
7640 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
7641 WINED3DSAMP_DMAPOFFSET