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
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 )
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;
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);
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; \
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); \
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); \
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) {
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);
141 glLoadMatrixf((float *)&This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
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");
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");
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);
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) {
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");
195 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
196 checkGLcall("glLightfv");
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");
207 case D3DLIGHT_DIRECTIONAL:
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");
218 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
221 /* Restore the modelview matrix */
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;
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));
243 VTRACE(("Activating appropriate texture state %ld\n", Sampler));
244 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
246 GLACTIVETEXTURE(Sampler);
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");
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);
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);
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,
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(...)");
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);
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);
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);
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);
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);
412 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
413 DWORD FVF, WINED3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
415 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
416 IWineD3DVertexBufferImpl *object;
417 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
418 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, WINED3DRTYPE_VERTEXBUFFER, Size)
421 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
422 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
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;
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)
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;
454 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
456 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
457 IWineD3DStateBlockImpl *object;
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 */
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));
475 memset(object->streamFreq, 1, sizeof(object->streamFreq));
478 /* Reset the ref and type after kludging it */
479 object->wineD3DDevice = This;
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;
550 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
551 if (newEl == NULL) return WINED3DERR_OUTOFVIDEOMEMORY;
552 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
554 newEl->changed = TRUE;
555 newEl->enabledChanged = TRUE;
557 object->lights = newEl;
568 FIXME("Unrecognized state block type %d\n", Type);
571 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
576 /* ************************************
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.
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
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
602 *******************************/
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
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
663 *********************************/
664 if (WINED3DFMT_UNKNOWN == Format) {
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));
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);
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;
703 object->pow2Width = pow2Width;
704 object->pow2Height = pow2Height;
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;
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 * ****************************************/
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");
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");
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");
751 FIXME("(%p) Unknown pool %d\n", This, Pool);
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 */
772 /* Nothing to do, it's set already */
776 object->lpVtbl = &IWineGDISurface_Vtbl;
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;
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 */
834 TRACE("calculating levels %d\n", object->baseTexture.levels);
835 object->baseTexture.levels++;
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 */
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) {
855 FIXME("Failed to create surface %p\n", object);
857 for (j = 0 ; j < i ; j++) {
858 IWineD3DSurface_Release(object->surfaces[j]);
860 /* heap free object */
861 HeapFree(GetProcessHeap(), 0, object);
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);
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;
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 */
912 object->baseTexture.levels++;
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 */
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);
950 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
951 UINT Width, UINT Height, UINT Depth,
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 **/
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 */
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 */
1018 object->baseTexture.levels++;
1021 tmpW = max(1, tmpW >> 1);
1022 object->baseTexture.levels++;
1024 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1027 /* Generate all the surfaces */
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) {
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;
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;
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;
1074 case WINED3DQUERYTYPE_OCCLUSION:
1075 TRACE("(%p) occlusion query\n", This);
1076 if (GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY))
1079 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
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:
1095 FIXME("(%p) Unhandled query type %d\n", This, Type);
1100 D3DCREATEOBJECTINSTANCE(object, Query)
1101 object->type = Type;
1102 /* allocated the 'extended' data based on the type of query requested */
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));
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:
1124 object->extendedData = 0;
1125 FIXME("(%p) Unhandled query type %d\n",This , Type);
1127 TRACE("(%p) : Created Query %p\n", This, object);
1131 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1132 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1134 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1135 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1136 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1139 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
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 **/
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");
1205 return WINED3DERR_NOTAVAILABLE;
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 **/
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);
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);
1265 XFree(object->visInfo);
1266 object->visInfo = NULL;
1268 if (NULL == object->glCtx) {
1269 ERR("cannot create glxContext\n");
1271 return WINED3DERR_NOTAVAILABLE;
1275 if (object->glCtx == NULL) {
1276 ERR("Error in context creation !\n");
1277 return WINED3DERR_INVALIDCALL;
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)) {
1299 /* Get info on the current display setup */
1300 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1301 bpp = GetDeviceCaps(hdc, BITSPIXEL);
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);
1319 /* For GetDisplayMode */
1320 This->ddraw_width = devmode.dmPelsWidth;
1321 This->ddraw_height = devmode.dmPelsHeight;
1322 This->ddraw_format = *(pPresentationParameters->BackBufferFormat);
1326 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1327 * then the corresponding dimension of the client area of the hDeviceWindow
1328 * (or the focus window, if hDeviceWindow is NULL) is taken.
1329 **********************/
1331 if (*(pPresentationParameters->Windowed) &&
1332 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1333 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1336 GetClientRect(object->win_handle, &Rect);
1338 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1339 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1340 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1342 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1343 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1344 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1348 /*********************
1349 * finish off parameter initialization
1350 *******************/
1352 /* Put the correct figures in the presentation parameters */
1353 TRACE("Coppying accross presentaion paraneters\n");
1354 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1355 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1356 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1357 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1358 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1359 object->presentParms.MultiSampleQuality = NULL == pPresentationParameters->MultiSampleQuality ? 0 : *(pPresentationParameters->MultiSampleQuality);
1360 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1361 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1362 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1363 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1364 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1365 object->presentParms.Flags = *(pPresentationParameters->Flags);
1366 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1367 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1370 /*********************
1371 * Create the back, front and stencil buffers
1372 *******************/
1373 TRACE("calling rendertarget CB\n");
1374 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1375 object->presentParms.BackBufferWidth,
1376 object->presentParms.BackBufferHeight,
1377 object->presentParms.BackBufferFormat,
1378 object->presentParms.MultiSampleType,
1379 object->presentParms.MultiSampleQuality,
1380 TRUE /* Lockable */,
1381 &object->frontBuffer,
1382 NULL /* pShared (always null)*/);
1383 if (object->frontBuffer != NULL)
1384 IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
1385 if(object->presentParms.BackBufferCount > 0) {
1386 TRACE("calling rendertarget CB\n");
1387 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1388 object->presentParms.BackBufferWidth,
1389 object->presentParms.BackBufferHeight,
1390 object->presentParms.BackBufferFormat,
1391 object->presentParms.MultiSampleType,
1392 object->presentParms.MultiSampleQuality,
1393 TRUE /* Lockable */,
1394 &object->backBuffer,
1395 NULL /* pShared (always null)*/);
1397 object->backBuffer = NULL;
1400 if (object->backBuffer != NULL) {
1401 IWineD3DSurface_SetContainer(object->backBuffer, (IWineD3DBase *)object);
1403 glDrawBuffer(GL_BACK);
1404 checkGLcall("glDrawBuffer(GL_BACK)");
1407 /* Single buffering - draw to front buffer */
1409 glDrawBuffer(GL_FRONT);
1410 checkGLcall("glDrawBuffer(GL_FRONT)");
1414 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1415 if (pPresentationParameters->EnableAutoDepthStencil) {
1416 TRACE("Creating depth stencil buffer\n");
1417 if (This->depthStencilBuffer == NULL ) {
1418 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1419 object->presentParms.BackBufferWidth,
1420 object->presentParms.BackBufferHeight,
1421 object->presentParms.AutoDepthStencilFormat,
1422 object->presentParms.MultiSampleType,
1423 object->presentParms.MultiSampleQuality,
1424 FALSE /* FIXME: Discard */,
1425 &This->depthStencilBuffer,
1426 NULL /* pShared (always null)*/ );
1427 if (This->depthStencilBuffer != NULL)
1428 IWineD3DSurface_SetContainer(This->depthStencilBuffer, 0);
1431 /** TODO: A check on width, height and multisample types
1432 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1433 ****************************/
1434 object->wantsDepthStencilBuffer = TRUE;
1436 object->wantsDepthStencilBuffer = FALSE;
1439 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1442 /*********************
1443 * init the default renderTarget management
1444 *******************/
1445 object->drawable = object->win;
1446 object->render_ctx = object->glCtx;
1448 if (hr == WINED3D_OK) {
1449 /*********************
1450 * Setup some defaults and clear down the buffers
1451 *******************/
1453 /** save current context and drawable **/
1454 oldContext = glXGetCurrentContext();
1455 oldDrawable = glXGetCurrentDrawable();
1457 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1458 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1459 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1461 checkGLcall("glXMakeCurrent");
1463 TRACE("Setting up the screen\n");
1464 /* Clear the screen */
1465 glClearColor(1.0, 0.0, 0.0, 0.0);
1466 checkGLcall("glClearColor");
1469 glClearStencil(0xffff);
1471 checkGLcall("glClear");
1473 glColor3f(1.0, 1.0, 1.0);
1474 checkGLcall("glColor3f");
1476 glEnable(GL_LIGHTING);
1477 checkGLcall("glEnable");
1479 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1480 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1482 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1483 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1485 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1486 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1488 /* switch back to the original context (if there was one)*/
1489 if (This->swapchains != NULL) {
1490 /** TODO: restore the context and drawable **/
1491 glXMakeCurrent(object->display, oldDrawable, oldContext);
1496 { /* Finally add the swapchain to the end of the devices' swapchain list */
1497 SwapChainList **nextSwapchain;
1498 nextSwapchain = &This->swapchains;
1499 while (*nextSwapchain != NULL) {
1500 nextSwapchain = &((*nextSwapchain)->next);
1502 (*nextSwapchain) = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->swapchains));
1503 (*nextSwapchain)->swapchain = (IWineD3DSwapChain *)object;
1505 TRACE("Set swapchain to %p\n", object);
1506 } else { /* something went wrong so clean up */
1507 IUnknown* bufferParent;
1508 if (object->frontBuffer) {
1510 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1511 IUnknown_Release(bufferParent); /* once for the get parent */
1512 if (IUnknown_Release(bufferParent) > 0) {
1513 FIXME("(%p) Something's still holding the front buffer\n",This);
1516 if (object->backBuffer) {
1517 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1518 IUnknown_Release(bufferParent); /* once for the get parent */
1519 if (IUnknown_Release(bufferParent) > 0) {
1520 FIXME("(%p) Something's still holding the back buffer\n",This);
1523 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1524 /* Clean up the context */
1525 /* check that we are the current context first (we shouldn't be though!) */
1526 if (object->glCtx != 0) {
1527 if(glXGetCurrentContext() == object->glCtx) {
1528 glXMakeCurrent(object->display, None, NULL);
1530 glXDestroyContext(object->display, object->glCtx);
1532 HeapFree(GetProcessHeap(), 0, object);
1539 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1540 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1541 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1542 unsigned int numberOfSwapChains = 0;
1543 SwapChainList *swapchain;
1545 swapchain = This->swapchains;
1546 /* itterate through the list to get a count */
1547 while (swapchain != NULL) {
1548 swapchain = swapchain->next;
1549 numberOfSwapChains++;
1552 TRACE("(%p) returning %d\n", This, numberOfSwapChains);
1553 return numberOfSwapChains;
1556 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1557 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1558 SwapChainList *swapchain;
1560 HRESULT hr = WINED3DERR_INVALIDCALL;
1561 swapchain = This->swapchains;
1562 TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1565 TRACE("(%p) Finding swapchain %d\n", This, iSwapChain);
1566 while (i > 0 && swapchain != NULL) {
1567 swapchain = swapchain->next;
1572 FIXME("(%p) Unable to find swapchain %d\n", This, iSwapChain);
1574 } else if (swapchain != NULL) {
1575 /** TODO: move off to a linkesList implementation **/
1576 *pSwapChain = swapchain->swapchain;
1577 IWineD3DSwapChain_AddRef(*pSwapChain);
1581 TRACE("(%p) returning %p\n", This, *pSwapChain);
1586 * Vertex Declaration
1588 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1589 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1590 IWineD3DVertexDeclarationImpl *object = NULL;
1591 HRESULT hr = WINED3D_OK;
1592 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1593 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1596 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1601 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1602 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pDeclaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1603 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1604 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1605 HRESULT hr = WINED3D_OK;
1606 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1607 object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins;
1609 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1611 /* If a vertex declaration has been passed, save it to the vertex shader, this affects d3d8 only. */
1612 /* Further it needs to be set before calling SetFunction as SetFunction needs the declaration. */
1613 if (pDeclaration != NULL) {
1614 IWineD3DVertexDeclaration *vertexDeclaration;
1615 hr = IWineD3DDevice_CreateVertexDeclaration(iface, pDeclaration, &vertexDeclaration ,NULL);
1616 if (WINED3D_OK == hr) {
1617 TRACE("(%p) : Setting vertex declaration to %p\n", This, vertexDeclaration);
1618 object->vertexDeclaration = vertexDeclaration;
1620 FIXME("(%p) : Failed to set the declaration, returning WINED3DERR_INVALIDCALL\n", iface);
1621 IWineD3DVertexShader_Release(*ppVertexShader);
1622 return WINED3DERR_INVALIDCALL;
1626 hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1628 if (WINED3D_OK != hr) {
1629 FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface);
1630 IWineD3DVertexShader_Release(*ppVertexShader);
1631 return WINED3DERR_INVALIDCALL;
1634 #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. */
1635 if(Usage == WINED3DUSAGE_SOFTWAREVERTEXPROCESSING) {
1646 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
1647 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1648 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1649 HRESULT hr = WINED3D_OK;
1651 D3DCREATEOBJECTINSTANCE(object, PixelShader)
1652 object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins;
1653 hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
1654 if (WINED3D_OK == hr) {
1655 TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
1657 WARN("(%p) : Failed to create pixel shader\n", This);
1663 HRESULT WINAPI IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice *iface, DWORD Flags, PALETTEENTRY *PalEnt, IWineD3DPalette **Palette, IUnknown *Parent) {
1664 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1665 IWineD3DPaletteImpl *object;
1667 TRACE("(%p)->(%lx, %p, %p, %p)\n", This, Flags, PalEnt, Palette, Parent);
1669 /* Create the new object */
1670 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DPaletteImpl));
1672 ERR("Out of memory when allocating memory for a IWineD3DPalette implementation\n");
1673 return E_OUTOFMEMORY;
1676 object->lpVtbl = &IWineD3DPalette_Vtbl;
1678 object->Flags = Flags;
1679 object->parent = Parent;
1680 object->wineD3DDevice = This;
1681 object->palNumEntries = IWineD3DPaletteImpl_Size(Flags);
1683 object->hpal = CreatePalette((const LOGPALETTE*)&(object->palVersion));
1686 HeapFree( GetProcessHeap(), 0, object);
1687 return E_OUTOFMEMORY;
1690 hr = IWineD3DPalette_SetEntries((IWineD3DPalette *) object, 0, 0, IWineD3DPaletteImpl_Size(Flags), PalEnt);
1692 IWineD3DPalette_Release((IWineD3DPalette *) object);
1696 *Palette = (IWineD3DPalette *) object;
1701 HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) {
1702 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1703 IWineD3DSwapChainImpl *swapchain;
1705 TRACE("(%p)->(%p,%p)\n", This, pPresentationParameters, D3DCB_CreateAdditionalSwapChain);
1706 if(This->d3d_initialized) return WINED3DERR_INVALIDCALL;
1708 /* TODO: Test if OpenGL is compiled in and loaded */
1710 /* Setup the implicit swapchain */
1711 TRACE("Creating implicit swapchain\n");
1712 if (D3D_OK != D3DCB_CreateAdditionalSwapChain((IUnknown *) This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain) || swapchain == NULL) {
1713 WARN("Failed to create implicit swapchain\n");
1714 return WINED3DERR_INVALIDCALL;
1717 if(swapchain->backBuffer) {
1718 TRACE("Setting rendertarget to %p\n", swapchain->backBuffer);
1719 This->renderTarget = swapchain->backBuffer;
1722 TRACE("Setting rendertarget to %p\n", swapchain->frontBuffer);
1723 This->renderTarget = swapchain->frontBuffer;
1725 IWineD3DSurface_AddRef(This->renderTarget);
1726 /* Depth Stencil support */
1727 This->stencilBufferTarget = This->depthStencilBuffer;
1728 if (NULL != This->stencilBufferTarget) {
1729 IWineD3DSurface_AddRef(This->stencilBufferTarget);
1732 /* Set up some starting GL setup */
1735 * Initialize openGL extension related variables
1736 * with Default values
1739 ((IWineD3DImpl *) This->wineD3D)->isGLInfoValid = IWineD3DImpl_FillGLCaps( &((IWineD3DImpl *) This->wineD3D)->gl_info, swapchain->display);
1740 /* Setup all the devices defaults */
1741 IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)This->stateBlock);
1743 IWineD3DImpl_CheckGraphicsMemory();
1747 { /* Set a default viewport */
1751 vp.Width = *(pPresentationParameters->BackBufferWidth);
1752 vp.Height = *(pPresentationParameters->BackBufferHeight);
1755 IWineD3DDevice_SetViewport((IWineD3DDevice *)This, &vp);
1759 /* Initialize the current view state */
1760 This->modelview_valid = 1;
1761 This->proj_valid = 0;
1762 This->view_ident = 1;
1763 This->last_was_rhw = 0;
1764 glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights);
1765 TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This, This);
1767 /* Clear the screen */
1768 IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
1770 This->d3d_initialized = TRUE;
1774 HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface) {
1775 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1777 IUnknown* stencilBufferParent;
1778 IUnknown* swapChainParent;
1779 SwapChainList *nextSwapchain;
1780 TRACE("(%p)\n", This);
1782 if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL;
1784 for(texstage = 0; texstage < GL_LIMITS(textures); texstage++) {
1785 IWineD3DDevice_SetTexture(iface, texstage, NULL);
1788 /* NOTE: You must release the parent if the object was created via a callback
1789 ** ***************************/
1790 /* Release all of the swapchains, except the implicit swapchain */
1792 /* NOTE: Don't release swapchain 0 here, it's 'special' */
1793 TRACE("Finding implicit swapchain\n");
1794 nextSwapchain = This->swapchains;
1795 if (nextSwapchain != NULL) {
1796 nextSwapchain = nextSwapchain->next;
1798 WARN("Expected to find the implicit swapchain\n");
1801 TRACE("Releasing swapchains. nextSwapchain = %p\n", nextSwapchain);
1802 /* release all the other swapchains */
1803 while (nextSwapchain != NULL) {
1804 SwapChainList *prevSwapchain = nextSwapchain;
1805 nextSwapchain = nextSwapchain->next;
1806 TRACE("Releasing swapchain %p\n", prevSwapchain->swapchain);
1807 IWineD3DSwapChain_Release(prevSwapchain->swapchain);
1808 /* NOTE: no need to free the list element, it will be done by the release callback
1809 HeapFree(GetProcessHeap(), 0, prevSwapchain); */
1811 /* Release the buffers (with sanity checks)*/
1812 TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget);
1813 if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
1814 if(This->depthStencilBuffer != This->stencilBufferTarget)
1815 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
1817 This->stencilBufferTarget = NULL;
1819 TRACE("Releasing the render target at %p\n", This->renderTarget);
1820 if(IWineD3DSurface_Release(This->renderTarget) >0){
1821 /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
1823 TRACE("Setting rendertarget to NULL\n");
1824 This->renderTarget = NULL;
1826 IWineD3DSurface_GetParent(This->depthStencilBuffer, &stencilBufferParent);
1827 IUnknown_Release(stencilBufferParent); /* once for the get parent */
1828 if(IUnknown_Release(stencilBufferParent) >0){ /* the second time for when it was created */
1829 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
1831 This->depthStencilBuffer = NULL;
1833 TRACE("Releasing the implicit swapchain\n");
1834 if (This->swapchains != NULL) {
1835 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
1836 IWineD3DSwapChain_GetParent(This->swapchains->swapchain, &swapChainParent);
1837 IUnknown_Release(swapChainParent); /* once for the get parent */
1838 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
1839 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
1842 This->swapchains = NULL;
1844 This->d3d_initialized = FALSE;
1848 HRESULT WINAPI IWineD3DDeviceImpl_EnumDisplayModes(IWineD3DDevice *iface, DWORD Flags, UINT Width, UINT Height, WINED3DFORMAT pixelformat, LPVOID context, D3DCB_ENUMDISPLAYMODESCALLBACK callback) {
1849 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1854 TRACE("(%p)->(%lx,%d,%d,%d,%p,%p)\n", This, Flags, Width, Height, pixelformat, context, callback);
1856 for (i = 0; EnumDisplaySettingsExW(NULL, i, &DevModeW, 0); i++) {
1857 /* Ignore some modes if a description was passed */
1858 if ( (Width > 0) && (Width != DevModeW.dmPelsWidth)) continue;
1859 if ( (Height > 0) && (Height != DevModeW.dmPelsHeight)) continue;
1860 if ( (pixelformat != WINED3DFMT_UNKNOWN) && ( D3DFmtGetBpp(NULL, pixelformat) != DevModeW.dmBitsPerPel) ) continue;
1862 TRACE("Enumerating %ldx%ld@%s\n", DevModeW.dmPelsWidth, DevModeW.dmPelsHeight, debug_d3dformat(pixelformat_for_depth(DevModeW.dmBitsPerPel)));
1864 if (callback((IUnknown *) This, (UINT) DevModeW.dmPelsWidth, (UINT) DevModeW.dmPelsHeight, pixelformat_for_depth(DevModeW.dmBitsPerPel), 60.0, context) == DDENUMRET_CANCEL)
1871 HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
1873 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1876 TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This, iSwapChain, pMode, pMode->Width, pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1878 /* Resize the screen even without a window:
1879 * The app could have unset it with SetCooperativeLevel, but not called
1880 * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
1881 * but we don't have any hwnd
1884 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1885 devmode.dmBitsPerPel = D3DFmtGetBpp(This, pMode->Format) * 8;
1886 if(devmode.dmBitsPerPel == 24) devmode.dmBitsPerPel = 32;
1887 devmode.dmPelsWidth = pMode->Width;
1888 devmode.dmPelsHeight = pMode->Height;
1890 devmode.dmDisplayFrequency = pMode->RefreshRate;
1891 if (pMode->RefreshRate != 0) {
1892 devmode.dmFields |= DM_DISPLAYFREQUENCY;
1895 /* Only change the mode if necessary */
1896 if( (This->ddraw_width == pMode->Width) &&
1897 (This->ddraw_height == pMode->Height) &&
1898 (This->ddraw_format == pMode->Format) &&
1899 (pMode->RefreshRate == 0) ) {
1903 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL);
1904 if (ret != DISP_CHANGE_SUCCESSFUL) {
1905 if(devmode.dmDisplayFrequency != 0) {
1906 WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
1907 devmode.dmFields &= ~DM_DISPLAYFREQUENCY;
1908 devmode.dmDisplayFrequency = 0;
1909 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL;
1911 if(ret != DISP_CHANGE_SUCCESSFUL) {
1912 return DDERR_INVALIDMODE;
1916 /* Store the new values */
1917 This->ddraw_width = pMode->Width;
1918 This->ddraw_height = pMode->Height;
1919 This->ddraw_format = pMode->Format;
1921 /* Only do this with a window of course */
1922 if(This->ddraw_window)
1923 MoveWindow(This->ddraw_window, 0, 0, pMode->Width, pMode->Height, TRUE);
1928 HRESULT WINAPI IWineD3DDeviceImpl_EnumZBufferFormats(IWineD3DDevice *iface, D3DCB_ENUMPIXELFORMATS Callback, void *Context) {
1929 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1932 WINED3DFORMAT FormatList[] = {
1939 WINED3DFMT_UNKNOWN /* Terminate the list */
1942 TRACE("(%p)->(%p,%p)\n", This, Callback, Context);
1944 while(FormatList[i] != WINED3DFMT_UNKNOWN) {
1945 TRACE("Enumerating %s\n", debug_d3dformat(FormatList[i]));
1946 ret = Callback((IUnknown *) This, FormatList[i], Context);
1947 if(ret != DDENUMRET_OK) {
1948 TRACE("Enumeration cancelled by Application\n");
1954 TRACE("End of Enumeration\n");
1959 HRESULT WINAPI IWineD3DDeviceImpl_EnumTextureFormats(IWineD3DDevice *iface, D3DCB_ENUMPIXELFORMATS Callback, void *Context) {
1960 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1965 * WINED3DFMT_A1R5G5B5 needs to be the first 16 bit format, as some dumb apps depend on this
1967 * Do not enumerate RGBA pixel formats: "some games choose the first 16 bit texture format
1968 * with alpha they find enumerated, others the last one. And both want to have the ARGB one."
1969 * But WineD3D doesn't support RGBA formats anyway...
1972 WINED3DFORMAT FormatList[] = {
1974 WINED3DFMT_A8R8G8B8,
1975 WINED3DFMT_X8R8G8B8,
1979 WINED3DFMT_A1R5G5B5,
1980 WINED3DFMT_A4R4G4B4,
1982 WINED3DFMT_X1R5G5B5,
1990 /* Terminate the list */
1994 TRACE("(%p)->(%p,%p)\n", This, Callback, Context);
1996 while(FormatList[i] != WINED3DFMT_UNKNOWN) {
1997 TRACE("Enumerating %s\n", debug_d3dformat(FormatList[i]));
1998 ret = Callback((IUnknown *) This, FormatList[i], Context);
1999 if(ret != DDENUMRET_OK) {
2000 TRACE("Enumeration cancelled by Application\n");
2006 TRACE("End of Enumeration\n");
2011 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
2012 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2013 *ppD3D= This->wineD3D;
2014 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
2015 IWineD3D_AddRef(*ppD3D);
2019 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
2020 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
2021 * Into the video ram as possible and seeing how many fit
2022 * you can also get the correct initial value from via X and ATI's driver
2023 *******************/
2024 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2025 static BOOL showfixmes = TRUE;
2027 FIXME("(%p) : stub, emulating %dMB for now, returning %dMB\n", This, (emulated_textureram/(1024*1024)),
2028 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2031 TRACE("(%p) : emulating %dMB for now, returning %dMB\n", This, (emulated_textureram/(1024*1024)),
2032 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2033 /* videomemory is simulated videomemory + AGP memory left */
2034 return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
2042 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
2043 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2044 HRESULT hr = WINED3D_OK;
2046 /* Update the current state block */
2047 This->updateStateBlock->fvf = fvf;
2048 This->updateStateBlock->changed.fvf = TRUE;
2049 This->updateStateBlock->set.fvf = TRUE;
2051 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
2054 /* clear down the vertex declaration
2055 NOTE: Axis and Allies doesn't work properly otherwise
2056 (may be a stateblock problem though!)
2058 hr = IWineD3DDevice_SetVertexDeclaration(iface, NULL);
2065 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
2066 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2067 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
2068 *pfvf = This->stateBlock->fvf;
2073 * Get / Set Stream Source
2075 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
2076 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2077 IWineD3DVertexBuffer *oldSrc;
2079 /**TODO: instance and index data, see
2080 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2082 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
2085 /* D3d9 only, but shouldn't hurt d3d8 */
2088 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2090 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2091 FIXME("stream index data not supported\n");
2093 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2094 FIXME("stream instance data not supported\n");
2098 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2100 if (StreamNumber >= MAX_STREAMS) {
2101 WARN("Stream out of range %d\n", StreamNumber);
2102 return WINED3DERR_INVALIDCALL;
2105 oldSrc = This->stateBlock->streamSource[StreamNumber];
2106 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
2108 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
2109 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
2110 This->updateStateBlock->streamStride[StreamNumber] = Stride;
2111 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
2112 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
2113 This->updateStateBlock->streamFlags[StreamNumber] = streamFlags;
2115 /* Handle recording of state blocks */
2116 if (This->isRecordingState) {
2117 TRACE("Recording... not performing anything\n");
2121 /* Not recording... */
2122 /* Need to do a getParent and pass the reffs up */
2123 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
2124 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
2125 so for now, just count internally */
2126 if (pStreamData != NULL) {
2127 IWineD3DVertexBuffer_AddRef(pStreamData);
2129 if (oldSrc != NULL) {
2130 IWineD3DVertexBuffer_Release(oldSrc);
2136 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
2137 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2140 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
2141 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
2144 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2146 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2147 FIXME("stream index data not supported\n");
2149 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2150 FIXME("stream instance data not supported\n");
2154 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2156 if (StreamNumber >= MAX_STREAMS) {
2157 WARN("Stream out of range %d\n", StreamNumber);
2158 return WINED3DERR_INVALIDCALL;
2160 *pStream = This->stateBlock->streamSource[StreamNumber];
2161 *pStride = This->stateBlock->streamStride[StreamNumber];
2162 *pOffset = This->stateBlock->streamOffset[StreamNumber];
2164 if (*pStream == NULL) {
2165 FIXME("Attempting to get an empty stream %d, returning WINED3DERR_INVALIDCALL\n", StreamNumber);
2166 return WINED3DERR_INVALIDCALL;
2169 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
2173 /*Should be quite easy, just an extension of vertexdata
2175 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2177 The divider is a bit odd though
2179 VertexOffset = StartVertex / Divider * StreamStride +
2180 VertexIndex / Divider * StreamStride + StreamOffset
2183 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
2184 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2186 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
2187 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (D3DSTREAMSOURCE_INSTANCEDATA | D3DSTREAMSOURCE_INDEXEDDATA );
2189 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
2190 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
2191 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
2193 if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
2194 FIXME("Stream indexing not fully supported\n");
2200 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
2201 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2203 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
2204 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
2206 TRACE("(%p) : returning %d\n", This, *Divider);
2212 * Get / Set & Multiply Transform
2214 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
2215 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2217 /* Most of this routine, comments included copied from ddraw tree initially: */
2218 TRACE("(%p) : Transform State=%d\n", This, d3dts);
2220 /* Handle recording of state blocks */
2221 if (This->isRecordingState) {
2222 TRACE("Recording... not performing anything\n");
2223 This->updateStateBlock->changed.transform[d3dts] = TRUE;
2224 This->updateStateBlock->set.transform[d3dts] = TRUE;
2225 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
2230 * If the new matrix is the same as the current one,
2231 * we cut off any further processing. this seems to be a reasonable
2232 * optimization because as was noticed, some apps (warcraft3 for example)
2233 * tend towards setting the same matrix repeatedly for some reason.
2235 * From here on we assume that the new matrix is different, wherever it matters.
2237 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
2238 TRACE("The app is setting the same matrix over again\n");
2241 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
2245 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2246 where ViewMat = Camera space, WorldMat = world space.
2248 In OpenGL, camera and world space is combined into GL_MODELVIEW
2249 matrix. The Projection matrix stay projection matrix.
2252 /* Capture the times we can just ignore the change for now */
2253 if (d3dts == D3DTS_WORLDMATRIX(0)) {
2254 This->modelview_valid = FALSE;
2257 } else if (d3dts == D3DTS_PROJECTION) {
2258 This->proj_valid = FALSE;
2261 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
2262 /* Indexed Vertex Blending Matrices 256 -> 511 */
2263 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
2264 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
2268 /* Now we really are going to have to change a matrix */
2271 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
2272 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
2273 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
2276 /* If we are changing the View matrix, reset the light and clipping planes to the new view
2277 * NOTE: We have to reset the positions even if the light/plane is not currently
2278 * enabled, since the call to enable it will not reset the position.
2279 * NOTE2: Apparently texture transforms do NOT need reapplying
2282 PLIGHTINFOEL *lightChain = NULL;
2283 This->modelview_valid = FALSE;
2284 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
2286 glMatrixMode(GL_MODELVIEW);
2287 checkGLcall("glMatrixMode(GL_MODELVIEW)");
2289 glLoadMatrixf((float *)lpmatrix);
2290 checkGLcall("glLoadMatrixf(...)");
2293 lightChain = This->stateBlock->lights;
2294 while (lightChain && lightChain->glIndex != -1) {
2295 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
2296 checkGLcall("glLightfv posn");
2297 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
2298 checkGLcall("glLightfv dirn");
2299 lightChain = lightChain->next;
2302 /* Reset Clipping Planes if clipping is enabled */
2303 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2304 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
2305 checkGLcall("glClipPlane");
2309 } else { /* What was requested!?? */
2310 WARN("invalid matrix specified: %i\n", d3dts);
2313 /* Release lock, all done */
2318 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
2319 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2320 TRACE("(%p) : for Transform State %d\n", This, State);
2321 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
2325 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
2326 D3DMATRIX *mat = NULL;
2329 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2330 * below means it will be recorded in a state block change, but it
2331 * works regardless where it is recorded.
2332 * If this is found to be wrong, change to StateBlock.
2334 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2335 TRACE("(%p) : For state %u\n", This, State);
2337 if (State < HIGHEST_TRANSFORMSTATE)
2339 mat = &This->updateStateBlock->transforms[State];
2341 FIXME("Unhandled transform state!!\n");
2344 multiply_matrix(&temp, mat, (D3DMATRIX *) pMatrix);
2346 /* Apply change via set transform - will reapply to eg. lights this way */
2347 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2352 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
2354 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2355 you can reference any indexes you want as long as that number max are enabled at any
2356 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2357 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2358 but when recording, just build a chain pretty much of commands to be replayed. */
2360 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2362 PLIGHTINFOEL *object, *temp;
2364 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2365 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2367 /* If recording state block, just add to end of lights chain */
2368 if (This->isRecordingState) {
2369 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2370 if (NULL == object) {
2371 return WINED3DERR_OUTOFVIDEOMEMORY;
2373 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2374 object->OriginalIndex = Index;
2375 object->glIndex = -1;
2376 object->changed = TRUE;
2378 /* Add to the END of the chain of lights changes to be replayed */
2379 if (This->updateStateBlock->lights == NULL) {
2380 This->updateStateBlock->lights = object;
2382 temp = This->updateStateBlock->lights;
2383 while (temp->next != NULL) temp=temp->next;
2384 temp->next = object;
2386 TRACE("Recording... not performing anything more\n");
2390 /* Ok, not recording any longer so do real work */
2391 object = This->stateBlock->lights;
2392 while (object != NULL && object->OriginalIndex != Index) object = object->next;
2394 /* If we didn't find it in the list of lights, time to add it */
2395 if (object == NULL) {
2396 PLIGHTINFOEL *insertAt,*prevPos;
2398 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2399 if (NULL == object) {
2400 return WINED3DERR_OUTOFVIDEOMEMORY;
2402 object->OriginalIndex = Index;
2403 object->glIndex = -1;
2405 /* Add it to the front of list with the idea that lights will be changed as needed
2406 BUT after any lights currently assigned GL indexes */
2407 insertAt = This->stateBlock->lights;
2409 while (insertAt != NULL && insertAt->glIndex != -1) {
2411 insertAt = insertAt->next;
2414 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2415 This->stateBlock->lights = object;
2416 } else if (insertAt == NULL) { /* End of list */
2417 prevPos->next = object;
2418 object->prev = prevPos;
2419 } else { /* Middle of chain */
2420 if (prevPos == NULL) {
2421 This->stateBlock->lights = object;
2423 prevPos->next = object;
2425 object->prev = prevPos;
2426 object->next = insertAt;
2427 insertAt->prev = object;
2431 /* Initialize the object */
2432 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,
2433 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2434 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2435 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2436 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2437 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2438 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2440 /* Save away the information */
2441 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2443 switch (pLight->Type) {
2444 case D3DLIGHT_POINT:
2446 object->lightPosn[0] = pLight->Position.x;
2447 object->lightPosn[1] = pLight->Position.y;
2448 object->lightPosn[2] = pLight->Position.z;
2449 object->lightPosn[3] = 1.0f;
2450 object->cutoff = 180.0f;
2454 case D3DLIGHT_DIRECTIONAL:
2456 object->lightPosn[0] = -pLight->Direction.x;
2457 object->lightPosn[1] = -pLight->Direction.y;
2458 object->lightPosn[2] = -pLight->Direction.z;
2459 object->lightPosn[3] = 0.0;
2460 object->exponent = 0.0f;
2461 object->cutoff = 180.0f;
2466 object->lightPosn[0] = pLight->Position.x;
2467 object->lightPosn[1] = pLight->Position.y;
2468 object->lightPosn[2] = pLight->Position.z;
2469 object->lightPosn[3] = 1.0;
2472 object->lightDirn[0] = pLight->Direction.x;
2473 object->lightDirn[1] = pLight->Direction.y;
2474 object->lightDirn[2] = pLight->Direction.z;
2475 object->lightDirn[3] = 1.0;
2478 * opengl-ish and d3d-ish spot lights use too different models for the
2479 * light "intensity" as a function of the angle towards the main light direction,
2480 * so we only can approximate very roughly.
2481 * however spot lights are rather rarely used in games (if ever used at all).
2482 * furthermore if still used, probably nobody pays attention to such details.
2484 if (pLight->Falloff == 0) {
2487 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2489 if (rho < 0.0001) rho = 0.0001f;
2490 object->exponent = -0.3/log(cos(rho/2));
2491 object->cutoff = pLight->Phi*90/M_PI;
2497 FIXME("Unrecognized light type %d\n", pLight->Type);
2500 /* Update the live definitions if the light is currently assigned a glIndex */
2501 if (object->glIndex != -1) {
2502 setup_light(iface, object->glIndex, object);
2507 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2508 PLIGHTINFOEL *lightInfo = NULL;
2509 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2510 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2512 /* Locate the light in the live lights */
2513 lightInfo = This->stateBlock->lights;
2514 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2516 if (lightInfo == NULL) {
2517 TRACE("Light information requested but light not defined\n");
2518 return WINED3DERR_INVALIDCALL;
2521 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
2526 * Get / Set Light Enable
2527 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2529 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2530 PLIGHTINFOEL *lightInfo = NULL;
2531 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2532 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2534 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2535 if (This->isRecordingState) {
2536 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2537 if (NULL == lightInfo) {
2538 return WINED3DERR_OUTOFVIDEOMEMORY;
2540 lightInfo->OriginalIndex = Index;
2541 lightInfo->glIndex = -1;
2542 lightInfo->enabledChanged = TRUE;
2544 /* Add to the END of the chain of lights changes to be replayed */
2545 if (This->updateStateBlock->lights == NULL) {
2546 This->updateStateBlock->lights = lightInfo;
2548 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2549 while (temp->next != NULL) temp=temp->next;
2550 temp->next = lightInfo;
2552 TRACE("Recording... not performing anything more\n");
2556 /* Not recording... So, locate the light in the live lights */
2557 lightInfo = This->stateBlock->lights;
2558 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2560 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2561 if (lightInfo == NULL) {
2562 D3DLIGHT9 lightParms;
2563 /* Warning - untested code :-) Prob safe to change fixme to a trace but
2564 wait until someone confirms it seems to work! */
2565 TRACE("Light enabled requested but light not defined, so defining one!\n");
2566 lightParms.Type = D3DLIGHT_DIRECTIONAL;
2567 lightParms.Diffuse.r = 1.0;
2568 lightParms.Diffuse.g = 1.0;
2569 lightParms.Diffuse.b = 1.0;
2570 lightParms.Diffuse.a = 0.0;
2571 lightParms.Specular.r = 0.0;
2572 lightParms.Specular.g = 0.0;
2573 lightParms.Specular.b = 0.0;
2574 lightParms.Specular.a = 0.0;
2575 lightParms.Ambient.r = 0.0;
2576 lightParms.Ambient.g = 0.0;
2577 lightParms.Ambient.b = 0.0;
2578 lightParms.Ambient.a = 0.0;
2579 lightParms.Position.x = 0.0;
2580 lightParms.Position.y = 0.0;
2581 lightParms.Position.z = 0.0;
2582 lightParms.Direction.x = 0.0;
2583 lightParms.Direction.y = 0.0;
2584 lightParms.Direction.z = 1.0;
2585 lightParms.Range = 0.0;
2586 lightParms.Falloff = 0.0;
2587 lightParms.Attenuation0 = 0.0;
2588 lightParms.Attenuation1 = 0.0;
2589 lightParms.Attenuation2 = 0.0;
2590 lightParms.Theta = 0.0;
2591 lightParms.Phi = 0.0;
2592 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
2594 /* Search for it again! Should be fairly quick as near head of list */
2595 lightInfo = This->stateBlock->lights;
2596 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2597 if (lightInfo == NULL) {
2598 FIXME("Adding default lights has failed dismally\n");
2599 return WINED3DERR_INVALIDCALL;
2603 /* OK, we now have a light... */
2604 if (Enable == FALSE) {
2606 /* If we are disabling it, check it was enabled, and
2607 still only do something if it has assigned a glIndex (which it should have!) */
2608 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2609 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2611 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2612 checkGLcall("glDisable GL_LIGHT0+Index");
2615 TRACE("Nothing to do as light was not enabled\n");
2617 lightInfo->lightEnabled = FALSE;
2620 /* We are enabling it. If it is enabled, it's really simple */
2621 if (lightInfo->lightEnabled) {
2623 TRACE("Nothing to do as light was enabled\n");
2625 /* If it already has a glIndex, it's still simple */
2626 } else if (lightInfo->glIndex != -1) {
2627 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2628 lightInfo->lightEnabled = TRUE;
2630 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2631 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2634 /* Otherwise got to find space - lights are ordered gl indexes first */
2636 PLIGHTINFOEL *bsf = NULL;
2637 PLIGHTINFOEL *pos = This->stateBlock->lights;
2638 PLIGHTINFOEL *prev = NULL;
2642 /* Try to minimize changes as much as possible */
2643 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2645 /* Try to remember which index can be replaced if necessary */
2646 if (bsf==NULL && pos->lightEnabled == FALSE) {
2647 /* Found a light we can replace, save as best replacement */
2651 /* Step to next space */
2657 /* If we have too many active lights, fail the call */
2658 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2659 FIXME("Program requests too many concurrent lights\n");
2660 return WINED3DERR_INVALIDCALL;
2662 /* If we have allocated all lights, but not all are enabled,
2663 reuse one which is not enabled */
2664 } else if (Index == This->maxConcurrentLights) {
2665 /* use bsf - Simply swap the new light and the BSF one */
2666 PLIGHTINFOEL *bsfNext = bsf->next;
2667 PLIGHTINFOEL *bsfPrev = bsf->prev;
2670 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2671 if (bsf->prev != NULL) {
2672 bsf->prev->next = lightInfo;
2674 This->stateBlock->lights = lightInfo;
2677 /* If not side by side, lots of chains to update */
2678 if (bsf->next != lightInfo) {
2679 lightInfo->prev->next = bsf;
2680 bsf->next->prev = lightInfo;
2681 bsf->next = lightInfo->next;
2682 bsf->prev = lightInfo->prev;
2683 lightInfo->next = bsfNext;
2684 lightInfo->prev = bsfPrev;
2688 bsf->prev = lightInfo;
2689 bsf->next = lightInfo->next;
2690 lightInfo->next = bsf;
2691 lightInfo->prev = bsfPrev;
2696 glIndex = bsf->glIndex;
2698 lightInfo->glIndex = glIndex;
2699 lightInfo->lightEnabled = TRUE;
2701 /* Finally set up the light in gl itself */
2702 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2704 setup_light(iface, glIndex, lightInfo);
2705 glEnable(GL_LIGHT0 + glIndex);
2706 checkGLcall("glEnable GL_LIGHT0 new setup");
2709 /* If we reached the end of the allocated lights, with space in the
2710 gl lights, setup a new light */
2711 } else if (pos->glIndex == -1) {
2713 /* We reached the end of the allocated gl lights, so already
2714 know the index of the next one! */
2716 lightInfo->glIndex = glIndex;
2717 lightInfo->lightEnabled = TRUE;
2719 /* In an ideal world, it's already in the right place */
2720 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2721 /* No need to move it */
2723 /* Remove this light from the list */
2724 lightInfo->prev->next = lightInfo->next;
2725 if (lightInfo->next != NULL) {
2726 lightInfo->next->prev = lightInfo->prev;
2729 /* Add in at appropriate place (inbetween prev and pos) */
2730 lightInfo->prev = prev;
2731 lightInfo->next = pos;
2733 This->stateBlock->lights = lightInfo;
2735 prev->next = lightInfo;
2738 pos->prev = lightInfo;
2742 /* Finally set up the light in gl itself */
2743 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2745 setup_light(iface, glIndex, lightInfo);
2746 glEnable(GL_LIGHT0 + glIndex);
2747 checkGLcall("glEnable GL_LIGHT0 new setup");
2756 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2758 PLIGHTINFOEL *lightInfo = NULL;
2759 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2760 TRACE("(%p) : for idx(%ld)\n", This, Index);
2762 /* Locate the light in the live lights */
2763 lightInfo = This->stateBlock->lights;
2764 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2766 if (lightInfo == NULL) {
2767 TRACE("Light enabled state requested but light not defined\n");
2768 return WINED3DERR_INVALIDCALL;
2770 *pEnable = lightInfo->lightEnabled;
2775 * Get / Set Clip Planes
2777 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2778 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2779 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2781 /* Validate Index */
2782 if (Index >= GL_LIMITS(clipplanes)) {
2783 TRACE("Application has requested clipplane this device doesn't support\n");
2784 return WINED3DERR_INVALIDCALL;
2787 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2788 This->updateStateBlock->set.clipplane[Index] = TRUE;
2789 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2790 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2791 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2792 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2794 /* Handle recording of state blocks */
2795 if (This->isRecordingState) {
2796 TRACE("Recording... not performing anything\n");
2804 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2805 glMatrixMode(GL_MODELVIEW);
2807 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2809 TRACE("Clipplane [%f,%f,%f,%f]\n",
2810 This->updateStateBlock->clipplane[Index][0],
2811 This->updateStateBlock->clipplane[Index][1],
2812 This->updateStateBlock->clipplane[Index][2],
2813 This->updateStateBlock->clipplane[Index][3]);
2814 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2815 checkGLcall("glClipPlane");
2823 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2824 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2825 TRACE("(%p) : for idx %ld\n", This, Index);
2827 /* Validate Index */
2828 if (Index >= GL_LIMITS(clipplanes)) {
2829 TRACE("Application has requested clipplane this device doesn't support\n");
2830 return WINED3DERR_INVALIDCALL;
2833 pPlane[0] = This->stateBlock->clipplane[Index][0];
2834 pPlane[1] = This->stateBlock->clipplane[Index][1];
2835 pPlane[2] = This->stateBlock->clipplane[Index][2];
2836 pPlane[3] = This->stateBlock->clipplane[Index][3];
2841 * Get / Set Clip Plane Status
2842 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2844 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2845 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2846 FIXME("(%p) : stub\n", This);
2847 if (NULL == pClipStatus) {
2848 return WINED3DERR_INVALIDCALL;
2850 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2851 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2855 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2856 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2857 FIXME("(%p) : stub\n", This);
2858 if (NULL == pClipStatus) {
2859 return WINED3DERR_INVALIDCALL;
2861 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2862 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2867 * Get / Set Material
2868 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2870 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2871 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2873 This->updateStateBlock->changed.material = TRUE;
2874 This->updateStateBlock->set.material = TRUE;
2875 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2877 /* Handle recording of state blocks */
2878 if (This->isRecordingState) {
2879 TRACE("Recording... not performing anything\n");
2884 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2885 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2886 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2887 pMaterial->Ambient.b, pMaterial->Ambient.a);
2888 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2889 pMaterial->Specular.b, pMaterial->Specular.a);
2890 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2891 pMaterial->Emissive.b, pMaterial->Emissive.a);
2892 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2894 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2895 checkGLcall("glMaterialfv(GL_AMBIENT)");
2896 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2897 checkGLcall("glMaterialfv(GL_DIFFUSE)");
2899 /* Only change material color if specular is enabled, otherwise it is set to black */
2900 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2901 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2902 checkGLcall("glMaterialfv(GL_SPECULAR");
2904 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2905 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2906 checkGLcall("glMaterialfv(GL_SPECULAR");
2908 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2909 checkGLcall("glMaterialfv(GL_EMISSION)");
2910 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2911 checkGLcall("glMaterialf(GL_SHININESS");
2917 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2918 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2919 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2920 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2921 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2922 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2923 pMaterial->Ambient.b, pMaterial->Ambient.a);
2924 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2925 pMaterial->Specular.b, pMaterial->Specular.a);
2926 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2927 pMaterial->Emissive.b, pMaterial->Emissive.a);
2928 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2936 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2937 UINT BaseVertexIndex) {
2938 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2939 IWineD3DIndexBuffer *oldIdxs;
2941 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2942 oldIdxs = This->updateStateBlock->pIndexData;
2944 This->updateStateBlock->changed.indices = TRUE;
2945 This->updateStateBlock->set.indices = TRUE;
2946 This->updateStateBlock->pIndexData = pIndexData;
2947 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2949 /* Handle recording of state blocks */
2950 if (This->isRecordingState) {
2951 TRACE("Recording... not performing anything\n");
2955 if (NULL != pIndexData) {
2956 IWineD3DIndexBuffer_AddRef(pIndexData);
2958 if (NULL != oldIdxs) {
2959 IWineD3DIndexBuffer_Release(oldIdxs);
2964 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2965 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2967 *ppIndexData = This->stateBlock->pIndexData;
2969 /* up ref count on ppindexdata */
2971 IWineD3DIndexBuffer_AddRef(*ppIndexData);
2972 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2973 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
2975 TRACE("(%p) No index data set\n", This);
2977 TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
2983 * Get / Set Viewports
2985 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2986 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2988 TRACE("(%p)\n", This);
2989 This->updateStateBlock->changed.viewport = TRUE;
2990 This->updateStateBlock->set.viewport = TRUE;
2991 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2993 /* Handle recording of state blocks */
2994 if (This->isRecordingState) {
2995 TRACE("Recording... not performing anything\n");
2998 This->viewport_changed = TRUE;
3002 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
3003 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
3005 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
3006 checkGLcall("glDepthRange");
3007 /* Note: GL requires lower left, DirectX supplies upper left */
3008 /* TODO: replace usage of renderTarget with context management */
3009 glViewport(pViewport->X,
3010 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
3011 pViewport->Width, pViewport->Height);
3013 checkGLcall("glViewport");
3021 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
3022 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3023 TRACE("(%p)\n", This);
3024 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
3029 * Get / Set Render States
3030 * TODO: Verify against dx9 definitions
3032 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
3034 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3035 DWORD OldValue = This->stateBlock->renderState[State];
3037 /* Simple way of referring to either a DWORD or a 4 byte float */
3043 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
3044 This->updateStateBlock->changed.renderState[State] = TRUE;
3045 This->updateStateBlock->set.renderState[State] = TRUE;
3046 This->updateStateBlock->renderState[State] = Value;
3048 /* Handle recording of state blocks */
3049 if (This->isRecordingState) {
3050 TRACE("Recording... not performing anything\n");
3057 case WINED3DRS_FILLMODE :
3058 switch ((D3DFILLMODE) Value) {
3059 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
3060 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
3061 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
3063 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
3065 checkGLcall("glPolygonMode (fillmode)");
3068 case WINED3DRS_LIGHTING :
3070 glEnable(GL_LIGHTING);
3071 checkGLcall("glEnable GL_LIGHTING");
3073 glDisable(GL_LIGHTING);
3074 checkGLcall("glDisable GL_LIGHTING");
3078 case WINED3DRS_ZENABLE :
3079 switch ((D3DZBUFFERTYPE) Value) {
3081 glDisable(GL_DEPTH_TEST);
3082 checkGLcall("glDisable GL_DEPTH_TEST");
3085 glEnable(GL_DEPTH_TEST);
3086 checkGLcall("glEnable GL_DEPTH_TEST");
3089 glEnable(GL_DEPTH_TEST);
3090 checkGLcall("glEnable GL_DEPTH_TEST");
3091 FIXME("W buffer is not well handled\n");
3094 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
3098 case WINED3DRS_CULLMODE :
3100 /* If we are culling "back faces with clockwise vertices" then
3101 set front faces to be counter clockwise and enable culling
3103 switch ((D3DCULL) Value) {
3105 glDisable(GL_CULL_FACE);
3106 checkGLcall("glDisable GL_CULL_FACE");
3109 glEnable(GL_CULL_FACE);
3110 checkGLcall("glEnable GL_CULL_FACE");
3111 if (This->renderUpsideDown) {
3113 checkGLcall("glFrontFace GL_CW");
3115 glFrontFace(GL_CCW);
3116 checkGLcall("glFrontFace GL_CCW");
3118 glCullFace(GL_BACK);
3121 glEnable(GL_CULL_FACE);
3122 checkGLcall("glEnable GL_CULL_FACE");
3123 if (This->renderUpsideDown) {
3124 glFrontFace(GL_CCW);
3125 checkGLcall("glFrontFace GL_CCW");
3128 checkGLcall("glFrontFace GL_CW");
3130 glCullFace(GL_BACK);
3133 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
3137 case WINED3DRS_SHADEMODE :
3138 switch ((D3DSHADEMODE) Value) {
3140 glShadeModel(GL_FLAT);
3141 checkGLcall("glShadeModel");
3143 case D3DSHADE_GOURAUD:
3144 glShadeModel(GL_SMOOTH);
3145 checkGLcall("glShadeModel");
3147 case D3DSHADE_PHONG:
3148 FIXME("D3DSHADE_PHONG isn't supported?\n");
3151 return WINED3DERR_INVALIDCALL;
3153 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
3157 case WINED3DRS_DITHERENABLE :
3159 glEnable(GL_DITHER);
3160 checkGLcall("glEnable GL_DITHER");
3162 glDisable(GL_DITHER);
3163 checkGLcall("glDisable GL_DITHER");
3167 case WINED3DRS_ZWRITEENABLE :
3170 checkGLcall("glDepthMask");
3173 checkGLcall("glDepthMask");
3177 case WINED3DRS_ZFUNC :
3179 int glParm = GL_LESS;
3181 switch ((D3DCMPFUNC) Value) {
3182 case D3DCMP_NEVER: glParm=GL_NEVER; break;
3183 case D3DCMP_LESS: glParm=GL_LESS; break;
3184 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
3185 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
3186 case D3DCMP_GREATER: glParm=GL_GREATER; break;
3187 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
3188 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
3189 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
3191 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3193 glDepthFunc(glParm);
3194 checkGLcall("glDepthFunc");
3198 case WINED3DRS_AMBIENT :
3201 D3DCOLORTOGLFLOAT4(Value, col);
3202 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
3203 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
3204 checkGLcall("glLightModel for MODEL_AMBIENT");
3209 case WINED3DRS_ALPHABLENDENABLE :
3212 checkGLcall("glEnable GL_BLEND");
3214 glDisable(GL_BLEND);
3215 checkGLcall("glDisable GL_BLEND");
3219 case WINED3DRS_SRCBLEND :
3220 case WINED3DRS_DESTBLEND :
3222 int newVal = GL_ZERO;
3224 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
3225 case D3DBLEND_ONE : newVal = GL_ONE; break;
3226 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
3227 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
3228 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
3229 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
3230 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
3231 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
3232 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
3233 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
3234 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
3236 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
3237 This->srcBlend = newVal;
3238 This->dstBlend = newVal;
3241 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
3242 This->srcBlend = newVal;
3243 This->dstBlend = newVal;
3246 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
3249 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
3250 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
3251 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
3252 glBlendFunc(This->srcBlend, This->dstBlend);
3254 checkGLcall("glBlendFunc");
3258 case WINED3DRS_ALPHATESTENABLE :
3260 glEnable(GL_ALPHA_TEST);
3261 checkGLcall("glEnable GL_ALPHA_TEST");
3263 glDisable(GL_ALPHA_TEST);
3264 checkGLcall("glDisable GL_ALPHA_TEST");
3268 case WINED3DRS_ALPHAFUNC :
3270 int glParm = GL_LESS;
3271 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
3273 switch ((D3DCMPFUNC) Value) {
3274 case D3DCMP_NEVER: glParm = GL_NEVER; break;
3275 case D3DCMP_LESS: glParm = GL_LESS; break;
3276 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
3277 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
3278 case D3DCMP_GREATER: glParm = GL_GREATER; break;
3279 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
3280 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
3281 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
3283 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3285 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
3286 glAlphaFunc(glParm, ref);
3287 This->alphafunc = glParm;
3288 checkGLcall("glAlphaFunc");
3292 case WINED3DRS_ALPHAREF :
3294 int glParm = This->alphafunc;
3297 ref = ((float) Value) / 255.0f;
3298 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
3299 glAlphaFunc(glParm, ref);
3300 checkGLcall("glAlphaFunc");
3304 case WINED3DRS_CLIPPLANEENABLE :
3305 case WINED3DRS_CLIPPING :
3307 /* Ensure we only do the changed clip planes */
3308 DWORD enable = 0xFFFFFFFF;
3309 DWORD disable = 0x00000000;
3311 /* If enabling / disabling all */
3312 if (State == WINED3DRS_CLIPPING) {
3314 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3317 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3321 enable = Value & ~OldValue;
3322 disable = ~Value & OldValue;
3325 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
3326 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
3327 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
3328 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
3329 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
3330 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
3332 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
3333 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
3334 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
3335 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
3336 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
3337 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
3339 /** update clipping status */
3341 This->stateBlock->clip_status.ClipUnion = 0;
3342 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
3344 This->stateBlock->clip_status.ClipUnion = 0;
3345 This->stateBlock->clip_status.ClipIntersection = 0;
3350 case WINED3DRS_BLENDOP :
3352 int glParm = GL_FUNC_ADD;
3354 switch ((D3DBLENDOP) Value) {
3355 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
3356 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
3357 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3358 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
3359 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
3361 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
3363 TRACE("glBlendEquation(%x)\n", glParm);
3364 glBlendEquation(glParm);
3365 checkGLcall("glBlendEquation");
3369 case WINED3DRS_TEXTUREFACTOR :
3373 /* Note the texture color applies to all textures whereas
3374 GL_TEXTURE_ENV_COLOR applies to active only */
3376 D3DCOLORTOGLFLOAT4(Value, col);
3377 /* Set the default alpha blend color */
3378 glBlendColor(col[0], col[1], col[2], col[3]);
3379 checkGLcall("glBlendColor");
3381 /* And now the default texture color as well */
3382 for (i = 0; i < GL_LIMITS(textures); i++) {
3384 /* Note the D3DRS value applies to all textures, but GL has one
3385 per texture, so apply it now ready to be used! */
3386 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3389 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3392 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3393 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3398 case WINED3DRS_SPECULARENABLE :
3400 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3401 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3402 specular color. This is wrong:
3403 Separate specular color means the specular colour is maintained separately, whereas
3404 single color means it is merged in. However in both cases they are being used to
3406 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3407 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3411 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3412 checkGLcall("glMaterialfv");
3413 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3414 glEnable(GL_COLOR_SUM_EXT);
3416 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3418 checkGLcall("glEnable(GL_COLOR_SUM)");
3420 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3422 /* for the case of enabled lighting: */
3423 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3424 checkGLcall("glMaterialfv");
3426 /* for the case of disabled lighting: */
3427 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3428 glDisable(GL_COLOR_SUM_EXT);
3430 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3432 checkGLcall("glDisable(GL_COLOR_SUM)");
3437 case WINED3DRS_STENCILENABLE :
3439 glEnable(GL_STENCIL_TEST);
3440 checkGLcall("glEnable GL_STENCIL_TEST");
3442 glDisable(GL_STENCIL_TEST);
3443 checkGLcall("glDisable GL_STENCIL_TEST");
3447 case WINED3DRS_STENCILFUNC :
3450 GLint ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3451 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3454 switch ((D3DCMPFUNC)Value) {
3455 case D3DCMP_NEVER: func = GL_NEVER; break;
3456 case D3DCMP_LESS: func = GL_LESS; break;
3457 case D3DCMP_EQUAL: func = GL_EQUAL; break;
3458 case D3DCMP_LESSEQUAL: func = GL_LEQUAL; break;
3459 case D3DCMP_GREATER: func = GL_GREATER; break;
3460 case D3DCMP_NOTEQUAL: func = GL_NOTEQUAL; break;
3461 case D3DCMP_GREATEREQUAL: func = GL_GEQUAL; break;
3462 case D3DCMP_ALWAYS: func = GL_ALWAYS; break;
3464 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3466 This->stencilfunc = func;
3467 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3468 #if 0 /* Don't use OpenGL 2.0 calls for now */
3469 if(GL_EXTCALL(glStencilFuncSeparate)) {
3470 GL_EXTCALL(glStencilFuncSeparate(GL_FRONT, func, ref, mask));
3471 checkGLcall("glStencilFuncSeparate(GL_FRONT,...)");
3475 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3476 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3477 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3478 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
3479 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
3480 glStencilFunc(func, ref, mask);
3481 checkGLcall("glStencilFunc(...)");
3483 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3484 GL_EXTCALL(glStencilFuncSeparateATI(GL_FRONT, func, ref, mask));
3485 checkGLcall("glStencilFuncSeparateATI(GL_FRONT,...)");
3487 TRACE("Separate stencil function not supported on this version of opengl");
3488 glStencilFunc(func, ref, mask);
3489 checkGLcall("glStencilFunc(...)");
3492 glStencilFunc(func, ref, mask);
3493 checkGLcall("glStencilFunc(...)");
3497 case WINED3DRS_STENCILREF :
3499 int glParm = This->stencilfunc;
3501 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3504 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3505 glStencilFunc(glParm, ref, mask);
3506 checkGLcall("glStencilFunc");
3510 case WINED3DRS_STENCILMASK :
3512 int glParm = This->stencilfunc;
3513 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3514 GLuint mask = Value;
3516 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3517 glStencilFunc(glParm, ref, mask);
3518 checkGLcall("glStencilFunc");
3522 case WINED3DRS_STENCILFAIL :
3523 case WINED3DRS_STENCILZFAIL :
3524 case WINED3DRS_STENCILPASS :
3530 GLint action = StencilOp(Value);
3532 glGetIntegerv(GL_STENCIL_FAIL, &stencilFail);
3533 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &depthFail);
3534 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &stencilPass);
3536 if(WINED3DRS_STENCILFAIL == State) {
3537 stencilFail = action;
3539 else if(WINED3DRS_STENCILZFAIL == State) {
3542 else if(WINED3DRS_STENCILPASS == State) {
3543 stencilPass = action;
3546 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3547 #if 0 /* Don't use OpenGL 2.0 calls for now */
3548 if(GL_EXTCALL(glStencilOpSeparate)) {
3549 GL_EXTCALL(glStencilOpSeparate(GL_FRONT, stencilFail, depthFail, stencilPass));
3550 checkGLcall("glStencilOpSeparate(GL_FRONT,...)");
3554 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3555 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3556 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3557 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
3558 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
3559 glStencilOp(stencilFail, depthFail, stencilPass);
3560 checkGLcall("glStencilOp(...)");
3562 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3563 GL_EXTCALL(glStencilOpSeparateATI(GL_FRONT, stencilFail, depthFail, stencilPass));
3564 checkGLcall("glStencilOpSeparateATI(GL_FRONT,...)");
3566 TRACE("Separate stencil operation not supported on this version of opengl");
3567 glStencilOp(stencilFail, depthFail, stencilPass);
3568 checkGLcall("glStencilOp(...)");
3571 glStencilOp(stencilFail, depthFail, stencilPass);
3572 checkGLcall("glStencilOp(...)");
3576 case WINED3DRS_STENCILWRITEMASK :
3578 glStencilMask(Value);
3579 TRACE("glStencilMask(%lu)\n", Value);
3580 checkGLcall("glStencilMask");
3584 case WINED3DRS_FOGENABLE :
3586 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
3588 checkGLcall("glEnable GL_FOG");
3591 checkGLcall("glDisable GL_FOG");
3596 case WINED3DRS_RANGEFOGENABLE :
3599 TRACE("Enabled RANGEFOG");
3601 TRACE("Disabled RANGEFOG");
3606 case WINED3DRS_FOGCOLOR :
3609 D3DCOLORTOGLFLOAT4(Value, col);
3610 /* Set the default alpha blend color */
3611 glFogfv(GL_FOG_COLOR, &col[0]);
3612 checkGLcall("glFog GL_FOG_COLOR");
3616 case WINED3DRS_FOGTABLEMODE :
3618 glHint(GL_FOG_HINT, GL_NICEST);
3620 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3621 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3622 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3623 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3625 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3627 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3628 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3633 case WINED3DRS_FOGVERTEXMODE :
3635 glHint(GL_FOG_HINT, GL_FASTEST);
3637 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3638 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3639 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3640 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3642 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3644 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3645 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
3650 case WINED3DRS_FOGSTART :
3653 glFogfv(GL_FOG_START, &tmpvalue.f);
3654 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3655 TRACE("Fog Start == %f\n", tmpvalue.f);
3659 case WINED3DRS_FOGEND :
3662 glFogfv(GL_FOG_END, &tmpvalue.f);
3663 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3664 TRACE("Fog End == %f\n", tmpvalue.f);
3668 case WINED3DRS_FOGDENSITY :
3671 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3672 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3676 case WINED3DRS_VERTEXBLEND :
3678 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3679 TRACE("Vertex Blending state to %ld\n", Value);
3683 case WINED3DRS_TWEENFACTOR :
3686 This->updateStateBlock->tween_factor = tmpvalue.f;
3687 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3691 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
3693 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3697 case WINED3DRS_COLORVERTEX :
3698 case WINED3DRS_DIFFUSEMATERIALSOURCE :
3699 case WINED3DRS_SPECULARMATERIALSOURCE :
3700 case WINED3DRS_AMBIENTMATERIALSOURCE :
3701 case WINED3DRS_EMISSIVEMATERIALSOURCE :
3703 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3705 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3706 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3707 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3708 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3709 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3710 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3712 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3713 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3714 Parm = GL_AMBIENT_AND_DIFFUSE;
3718 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3720 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3722 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3729 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3731 This->tracking_color = NEEDS_TRACKING;
3732 This->tracking_parm = Parm;
3736 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3741 case WINED3DRS_LINEPATTERN :
3747 tmppattern.d = Value;
3749 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3751 if (tmppattern.lp.wRepeatFactor) {
3752 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3753 checkGLcall("glLineStipple(repeat, linepattern)");
3754 glEnable(GL_LINE_STIPPLE);
3755 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3757 glDisable(GL_LINE_STIPPLE);
3758 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3763 case WINED3DRS_ZBIAS : /* D3D8 only */
3767 TRACE("ZBias value %f\n", tmpvalue.f);
3768 glPolygonOffset(0, -tmpvalue.f);
3769 checkGLcall("glPolygonOffset(0, -Value)");
3770 glEnable(GL_POLYGON_OFFSET_FILL);
3771 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3772 glEnable(GL_POLYGON_OFFSET_LINE);
3773 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3774 glEnable(GL_POLYGON_OFFSET_POINT);
3775 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3777 glDisable(GL_POLYGON_OFFSET_FILL);
3778 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3779 glDisable(GL_POLYGON_OFFSET_LINE);
3780 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3781 glDisable(GL_POLYGON_OFFSET_POINT);
3782 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3787 case WINED3DRS_NORMALIZENORMALS :
3789 glEnable(GL_NORMALIZE);
3790 checkGLcall("glEnable(GL_NORMALIZE);");
3792 glDisable(GL_NORMALIZE);
3793 checkGLcall("glDisable(GL_NORMALIZE);");
3797 case WINED3DRS_POINTSIZE :
3798 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
3800 TRACE("Set point size to %f\n", tmpvalue.f);
3801 glPointSize(tmpvalue.f);
3802 checkGLcall("glPointSize(...);");
3805 case WINED3DRS_POINTSIZE_MIN :
3806 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3808 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3809 checkGLcall("glPointParameterfEXT(...);");
3811 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3815 case WINED3DRS_POINTSIZE_MAX :
3816 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3818 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3819 checkGLcall("glPointParameterfEXT(...);");
3821 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3825 case WINED3DRS_POINTSCALE_A :
3826 case WINED3DRS_POINTSCALE_B :
3827 case WINED3DRS_POINTSCALE_C :
3828 case WINED3DRS_POINTSCALEENABLE :
3831 * POINTSCALEENABLE controls how point size value is treated. If set to
3832 * true, the point size is scaled with respect to height of viewport.
3833 * When set to false point size is in pixels.
3835 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
3838 /* Default values */
3839 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3842 * Minimum valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
3843 * This means that OpenGL will clamp really small point sizes to 1.0f.
3844 * To correct for this we need to multiply by the scale factor when sizes
3845 * are less than 1.0f. scale_factor = 1.0f / point_size.
3847 GLfloat pointSize = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSIZE]);
3848 if(pointSize > 0.0f) {
3849 GLfloat scaleFactor;
3851 if(pointSize < 1.0f) {
3852 scaleFactor = pointSize * pointSize;
3857 if(This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3858 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]) /
3859 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3860 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]) /
3861 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3862 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) /
3863 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3867 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
3868 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
3869 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
3871 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3872 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3873 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
3875 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
3879 case WINED3DRS_COLORWRITEENABLE :
3881 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3882 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3883 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3884 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3885 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3886 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3887 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3888 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3889 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3890 checkGLcall("glColorMask(...)");
3894 case WINED3DRS_LOCALVIEWER :
3896 GLint state = (Value) ? 1 : 0;
3897 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3898 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3902 case WINED3DRS_LASTPIXEL :
3905 TRACE("Last Pixel Drawing Enabled\n");
3907 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3912 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3915 TRACE("Software Processing Enabled\n");
3917 TRACE("Software Processing Disabled\n");
3922 /** not supported */
3923 case WINED3DRS_ZVISIBLE :
3926 return WINED3DERR_INVALIDCALL;
3928 case WINED3DRS_POINTSPRITEENABLE :
3930 /* TODO: NV_POINT_SPRITE */
3931 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
3932 TRACE("Point sprites not supported\n");
3937 * Point sprites are always enabled. Value controls texture coordinate
3938 * replacement mode. Must be set true for point sprites to use
3941 glEnable(GL_POINT_SPRITE_ARB);
3942 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
3945 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
3946 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, TRUE)");
3948 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, FALSE);
3949 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, FALSE)");
3953 case WINED3DRS_EDGEANTIALIAS :
3956 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3958 checkGLcall("glEnable(GL_BLEND)");
3959 glEnable(GL_LINE_SMOOTH);
3960 checkGLcall("glEnable(GL_LINE_SMOOTH)");
3962 glDisable(GL_BLEND);
3963 checkGLcall("glDisable(GL_BLEND)");
3964 glDisable(GL_LINE_SMOOTH);
3965 checkGLcall("glDisable(GL_LINE_SMOOTH)");
3969 case WINED3DRS_WRAP0 :
3970 case WINED3DRS_WRAP1 :
3971 case WINED3DRS_WRAP2 :
3972 case WINED3DRS_WRAP3 :
3973 case WINED3DRS_WRAP4 :
3974 case WINED3DRS_WRAP5 :
3975 case WINED3DRS_WRAP6 :
3976 case WINED3DRS_WRAP7 :
3977 case WINED3DRS_WRAP8 :
3978 case WINED3DRS_WRAP9 :
3979 case WINED3DRS_WRAP10 :
3980 case WINED3DRS_WRAP11 :
3981 case WINED3DRS_WRAP12 :
3982 case WINED3DRS_WRAP13 :
3983 case WINED3DRS_WRAP14 :
3984 case WINED3DRS_WRAP15 :
3986 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
3987 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
3988 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
3989 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
3990 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
3992 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
3994 TRACE("(%p)->(%s,%ld) Texture wraping not yet supported\n",This, debug_d3drenderstate(State), Value);
3996 case WINED3DRS_MULTISAMPLEANTIALIAS :
3998 if (!GL_SUPPORT(ARB_MULTISAMPLE)) {
3999 TRACE("Multisample antialiasing not supported\n");
4004 glEnable(GL_MULTISAMPLE_ARB);
4005 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
4007 glDisable(GL_MULTISAMPLE_ARB);
4008 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
4012 case WINED3DRS_SCISSORTESTENABLE :
4015 glEnable(GL_SCISSOR_TEST);
4016 checkGLcall("glEnable(GL_SCISSOR_TEST)");
4018 glDisable(GL_SCISSOR_TEST);
4019 checkGLcall("glDisable(GL_SCISSOR_TEST)");
4023 case WINED3DRS_SLOPESCALEDEPTHBIAS :
4027 glEnable(GL_POLYGON_OFFSET_FILL);
4028 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4029 glPolygonOffset(tmpvalue.f, *((float*)&This->stateBlock->renderState[WINED3DRS_DEPTHBIAS]));
4030 checkGLcall("glPolygonOffset(...)");
4032 glDisable(GL_POLYGON_OFFSET_FILL);
4033 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4037 case WINED3DRS_ANTIALIASEDLINEENABLE :
4040 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4042 checkGLcall("glEnable(GL_BLEND)");
4043 glEnable(GL_LINE_SMOOTH);
4044 checkGLcall("glEnable(GL_LINE_SMOOTH)");
4046 glDisable(GL_BLEND);
4047 checkGLcall("glDisable(GL_BLEND)");
4048 glDisable(GL_LINE_SMOOTH);
4049 checkGLcall("glDisable(GL_LINE_SMOOTH)");
4053 case WINED3DRS_TWOSIDEDSTENCILMODE :
4056 TRACE("Two-sided stencil mode enabled\n");
4058 TRACE("Two-sided stencil mode disabled\n");
4062 case WINED3DRS_CCW_STENCILFAIL :
4063 case WINED3DRS_CCW_STENCILZFAIL :
4064 case WINED3DRS_CCW_STENCILPASS :
4070 GLint action = StencilOp(Value);
4072 glGetIntegerv(GL_STENCIL_BACK_FAIL, &stencilFail);
4073 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &depthFail);
4074 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS, &stencilPass);
4076 if(WINED3DRS_CCW_STENCILFAIL == State) {
4077 stencilFail = action;
4079 else if(WINED3DRS_CCW_STENCILZFAIL == State) {
4082 else if(WINED3DRS_CCW_STENCILPASS == State) {
4083 stencilPass = action;
4086 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
4087 #if 0 /* Don't use OpenGL 2.0 calls for now */
4088 if(GL_EXTCALL(glStencilOpSeparate)) {
4089 GL_EXTCALL(glStencilOpSeparate(GL_BACK, stencilFail, depthFail, stencilPass));
4090 checkGLcall("glStencilOpSeparate(GL_BACK,...)");
4094 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
4095 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
4096 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
4097 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
4098 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
4099 glStencilOp(stencilFail, depthFail, stencilPass);
4100 checkGLcall("glStencilOp(...)");
4102 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
4103 GL_EXTCALL(glStencilOpSeparateATI(GL_BACK, stencilFail, depthFail, stencilPass));
4104 checkGLcall("glStencilOpSeparateATI(GL_BACK,...)");
4106 TRACE("Separate stencil operation not supported on this version of opengl");
4107 glStencilOp(stencilFail, depthFail, stencilPass);
4108 checkGLcall("glStencilOp(...)");
4111 glStencilOp(stencilFail, depthFail, stencilPass);
4112 checkGLcall("glStencilOp(...)");
4116 case WINED3DRS_CCW_STENCILFUNC :
4119 GLint ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
4120 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
4123 switch ((D3DCMPFUNC)Value) {
4124 case D3DCMP_NEVER: func = GL_NEVER; break;
4125 case D3DCMP_LESS: func = GL_LESS; break;
4126 case D3DCMP_EQUAL: func = GL_EQUAL; break;
4127 case D3DCMP_LESSEQUAL: func = GL_LEQUAL; break;
4128 case D3DCMP_GREATER: func = GL_GREATER; break;
4129 case D3DCMP_NOTEQUAL: func = GL_NOTEQUAL; break;
4130 case D3DCMP_GREATEREQUAL: func = GL_GEQUAL; break;
4131 case D3DCMP_ALWAYS: func = GL_ALWAYS; break;
4133 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
4135 This->stencilfunc = func;
4136 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
4137 #if 0 /* Don't use OpenGL 2.0 calls for now */
4138 if(GL_EXTCALL(glStencilFuncSeparate)) {
4139 GL_EXTCALL(glStencilFuncSeparate(GL_BACK, func, ref, mask));
4140 checkGLcall("glStencilFuncSeparate(GL_BACK,...)");
4144 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
4145 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
4146 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
4147 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
4148 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
4149 glStencilFunc(func, ref, mask);
4150 checkGLcall("glStencilFunc(...)");
4152 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
4153 GL_EXTCALL(glStencilFuncSeparateATI(GL_BACK, func, ref, mask));
4154 checkGLcall("glStencilFuncSeparateATI(GL_BACK,...)");
4156 TRACE("Separate stencil function not supported on this version of opengl");
4157 glStencilFunc(func, ref, mask);
4158 checkGLcall("glStencilFunc(...)");
4161 glStencilFunc(func, ref, mask);
4162 checkGLcall("glStencilFunc(...)");
4166 case WINED3DRS_DEPTHBIAS :
4170 glEnable(GL_POLYGON_OFFSET_FILL);
4171 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4172 glPolygonOffset(*((float*)&This->stateBlock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS]), tmpvalue.f);
4173 checkGLcall("glPolygonOffset(...)");
4175 glDisable(GL_POLYGON_OFFSET_FILL);
4176 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4181 case WINED3DRS_TEXTUREPERSPECTIVE :
4184 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
4186 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
4190 case WINED3DRS_STIPPLEDALPHA :
4193 ERR(" Stippled Alpha not supported yet.\n");
4196 case WINED3DRS_ANTIALIAS :
4199 ERR(" Antialias not supported yet.\n");
4203 FIXME("(%p)->(%s,%ld) not handled yet\n", This, debug_d3drenderstate(State), Value);
4211 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
4212 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4213 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
4214 *pValue = This->stateBlock->renderState[State];
4219 * Get / Set Sampler States
4220 * TODO: Verify against dx9 definitions
4223 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
4224 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4226 * SetSampler is designed to allow for more than the standard up to 8 textures
4227 * and Geforce has stopped supporting more than 6 standard textures in openGL.
4228 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
4230 * http://developer.nvidia.com/object/General_FAQ.html#t6
4232 * There are two new settings for GForce
4234 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
4235 * and the texture one:
4236 * GL_MAX_TEXTURE_COORDS_ARB.
4237 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
4239 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
4240 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
4242 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
4243 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE, Sampler, Type);
4244 return WINED3DERR_INVALIDCALL;
4246 TRACE("Setting sampler %ld %d to %ld\n", Sampler, Type, Value);
4247 This->updateStateBlock->samplerState[Sampler][Type] = Value;
4248 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
4249 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
4251 /* Handle recording of state blocks */
4252 if (This->isRecordingState) {
4253 TRACE("Recording... not performing anything\n");
4260 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
4261 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4262 /** TODO: check that sampler is in range **/
4263 *Value = This->updateStateBlock->samplerState[Sampler][Type];
4264 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
4269 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
4270 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4273 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4274 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4275 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
4281 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
4282 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4283 GLint scissorBox[4];
4286 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4287 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
4288 pRect->left = scissorBox[1];
4289 pRect->top = scissorBox[2];
4290 pRect->right = scissorBox[1] + scissorBox[3];
4291 pRect->bottom = scissorBox[2] + scissorBox[4];
4292 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4297 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
4298 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4299 IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
4301 TRACE("(%p) : pDecl=%p\n", This, pDecl);
4303 This->updateStateBlock->vertexDecl = pDecl;
4304 This->updateStateBlock->changed.vertexDecl = TRUE;
4305 This->updateStateBlock->set.vertexDecl = TRUE;
4307 if (This->isRecordingState) {
4308 TRACE("Recording... not performing anything\n");
4311 if (NULL != pDecl) {
4312 IWineD3DVertexDeclaration_AddRef(pDecl);
4314 if (NULL != oldDecl) {
4315 IWineD3DVertexDeclaration_Release(oldDecl);
4320 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
4321 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4323 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
4325 *ppDecl = This->stateBlock->vertexDecl;
4326 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
4330 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
4331 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4332 IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
4334 This->updateStateBlock->vertexShader = pShader;
4335 This->updateStateBlock->changed.vertexShader = TRUE;
4336 This->updateStateBlock->set.vertexShader = TRUE;
4338 if (This->isRecordingState) {
4339 TRACE("Recording... not performing anything\n");
4342 if (NULL != pShader) {
4343 IWineD3DVertexShader_AddRef(pShader);
4345 if (NULL != oldShader) {
4346 IWineD3DVertexShader_Release(oldShader);
4349 if (pShader != NULL && ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration != NULL) {
4350 TRACE("(%p) : setting vertexDeclaration(%p)\n", This, ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration);
4351 IWineD3DDevice_SetVertexDeclaration(iface, ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration);
4354 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4356 * TODO: merge HAL shaders context switching from prototype
4361 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
4362 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4364 if (NULL == ppShader) {
4365 return WINED3DERR_INVALIDCALL;
4367 *ppShader = This->stateBlock->vertexShader;
4368 if( NULL != *ppShader)
4369 IWineD3DVertexShader_AddRef(*ppShader);
4371 TRACE("(%p) : returning %p\n", This, *ppShader);
4375 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4376 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4379 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4381 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4382 iface, dstData, srcData, type, start, count, registersize);
4384 if (type != WINESHADERCNST_NONE) {
4385 if (srcData == NULL || cnt < 0) {
4386 return WINED3DERR_INVALIDCALL;
4389 CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
4392 for (i = start; i < cnt + start; ++i) {
4393 This->updateStateBlock->changed.vertexShaderConstants[i] = TRUE;
4394 This->updateStateBlock->set.vertexShaderConstants[i] = TRUE;
4395 This->updateStateBlock->vertexShaderConstantT[i] = type;
4401 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4402 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4405 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4407 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4408 iface, dstData, srcData, type, start, count, registersize);
4410 /* Verify that the requested shader constant was populated with the correct type */
4411 for (i = start; i < cnt + start; ++i) {
4412 if (This->updateStateBlock->vertexShaderConstantT[i] != type) {
4413 TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning WINED3DERR_INVALIDCALL\n",
4414 This, type, This->updateStateBlock->vertexShaderConstantT[i]);
4415 return WINED3DERR_INVALIDCALL;
4419 if (dstData == NULL || cnt < 0) {
4420 return WINED3DERR_INVALIDCALL;
4423 CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
4428 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
4429 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4431 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4432 This->updateStateBlock->vertexShaderConstantB,
4434 WINESHADERCNST_BOOL,
4437 sizeof(*pConstantData));
4440 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
4441 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4443 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4445 This->updateStateBlock->vertexShaderConstantB,
4446 WINESHADERCNST_BOOL,
4449 sizeof(*pConstantData));
4452 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
4453 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4455 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4456 This->updateStateBlock->vertexShaderConstantI,
4458 WINESHADERCNST_INTEGER,
4461 4 * sizeof(*pConstantData));
4464 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
4465 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4467 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4469 This->updateStateBlock->vertexShaderConstantI,
4470 WINESHADERCNST_INTEGER,
4473 4 * sizeof(*pConstantData));
4477 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
4478 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4480 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4481 This->updateStateBlock->vertexShaderConstantF,
4483 WINESHADERCNST_FLOAT,
4486 4 * sizeof(*pConstantData));
4489 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
4490 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4492 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4494 This->updateStateBlock->vertexShaderConstantF,
4495 WINESHADERCNST_FLOAT,
4498 4 * sizeof(*pConstantData));
4501 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
4502 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4505 WINESHADERCNST_NONE,
4511 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
4512 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4513 IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader;
4514 This->updateStateBlock->pixelShader = pShader;
4515 This->updateStateBlock->changed.pixelShader = TRUE;
4516 This->updateStateBlock->set.pixelShader = TRUE;
4518 /* Handle recording of state blocks */
4519 if (This->isRecordingState) {
4520 TRACE("Recording... not performing anything\n");
4523 if (NULL != pShader) {
4524 IWineD3DPixelShader_AddRef(pShader);
4526 if (NULL != oldShader) {
4527 IWineD3DPixelShader_Release(oldShader);
4530 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4532 * TODO: merge HAL shaders context switching from prototype
4537 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
4538 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4540 if (NULL == ppShader) {
4541 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
4542 return WINED3DERR_INVALIDCALL;
4545 *ppShader = This->stateBlock->pixelShader;
4546 if (NULL != *ppShader) {
4547 IWineD3DPixelShader_AddRef(*ppShader);
4549 TRACE("(%p) : returning %p\n", This, *ppShader);
4553 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4554 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4557 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4559 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4560 iface, dstData, srcData, type, start, count, registersize);
4562 if (type != WINESHADERCNST_NONE) {
4563 if (srcData == NULL || cnt < 0) {
4564 return WINED3DERR_INVALIDCALL;
4567 CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
4570 for (i = start; i < cnt + start; ++i) {
4571 This->updateStateBlock->changed.pixelShaderConstants[i] = TRUE;
4572 This->updateStateBlock->set.pixelShaderConstants[i] = TRUE;
4573 This->updateStateBlock->pixelShaderConstantT[i] = type;
4579 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4580 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4583 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4585 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4586 iface, dstData, srcData, type, start, count, registersize);
4588 /* Verify that the requested shader constant was populated with the correct type */
4589 for (i = start; i < cnt + start; ++i) {
4590 if (This->updateStateBlock->pixelShaderConstantT[i] != type) {
4591 TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning WINED3DERR_INVALIDCALL\n",
4592 This, type, This->updateStateBlock->pixelShaderConstantT[i]);
4593 return WINED3DERR_INVALIDCALL;
4597 if (dstData == NULL || cnt < 0) {
4598 return WINED3DERR_INVALIDCALL;
4601 CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
4606 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
4607 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4609 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4610 This->updateStateBlock->pixelShaderConstantB,
4612 WINESHADERCNST_BOOL,
4615 sizeof(*pConstantData));
4618 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
4619 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4621 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4623 This->updateStateBlock->pixelShaderConstantB,
4624 WINESHADERCNST_BOOL,
4627 sizeof(*pConstantData));
4630 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
4631 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4633 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4634 This->updateStateBlock->pixelShaderConstantI,
4636 WINESHADERCNST_INTEGER,
4639 4 * sizeof(*pConstantData));
4642 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
4643 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4645 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4647 This->updateStateBlock->pixelShaderConstantI,
4648 WINESHADERCNST_INTEGER,
4651 4 * sizeof(*pConstantData));
4654 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
4655 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4657 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4658 This->updateStateBlock->pixelShaderConstantF,
4660 WINESHADERCNST_FLOAT,
4663 4 * sizeof(*pConstantData));
4666 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
4667 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4669 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4671 This->updateStateBlock->pixelShaderConstantF,
4672 WINESHADERCNST_FLOAT,
4675 4 * sizeof(*pConstantData));
4678 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
4679 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4682 WINESHADERCNST_NONE,
4688 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
4690 process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, WineDirect3DVertexStridedData *lpStrideData, DWORD SrcFVF, IWineD3DVertexBufferImpl *dest, DWORD dwFlags) {
4693 DWORD DestFVF = dest->fvf;
4695 D3DMATRIX mat, proj_mat, view_mat, world_mat;
4699 if (SrcFVF & D3DFVF_NORMAL) {
4700 WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
4703 if ( (SrcFVF & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
4704 ERR("Source has no position mask\n");
4705 return WINED3DERR_INVALIDCALL;
4708 if (dest->resource.allocatedMemory == NULL) {
4709 ERR("Destination buffer has no memory allocated\n");
4710 return WINED3DERR_INVALIDCALL;
4714 * a) D3DRS_CLIPPING is enabled
4715 * b) WINED3DVOP_CLIP is passed
4717 if(This->stateBlock->renderState[WINED3DRS_CLIPPING] == TRUE) {
4718 static BOOL warned = FALSE;
4720 * The clipping code is not quite correct. Some things need
4721 * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
4722 * so disable clipping for now.
4723 * (The graphics in Half-Life are broken, and my processvertices
4724 * test crashes with IDirect3DDevice3)
4730 FIXME("Clipping is broken and disabled for now\n");
4732 } else doClip = FALSE;
4733 dest_ptr = ((char *) dest->resource.allocatedMemory) + dwDestIndex * get_flexible_vertex_size(DestFVF);
4735 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
4738 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
4741 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
4742 D3DTS_WORLDMATRIX(0),
4745 TRACE("View mat: \n");
4746 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); \
4747 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); \
4748 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); \
4749 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); \
4751 TRACE("Proj mat: \n");
4752 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); \
4753 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); \
4754 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); \
4755 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); \
4757 TRACE("World mat: \n");
4758 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); \
4759 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); \
4760 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); \
4761 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); \
4763 /* Get the viewport */
4764 IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
4765 TRACE("Viewport: X=%ld, Y=%ld, Width=%ld, Height=%ld, MinZ=%f, MaxZ=%f\n",
4766 vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
4768 multiply_matrix(&mat,&view_mat,&world_mat);
4769 multiply_matrix(&mat,&proj_mat,&mat);
4771 numTextures = (DestFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
4773 for (i = 0; i < dwCount; i+= 1) {
4774 unsigned int tex_index;
4776 if ( ((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZ ) ||
4777 ((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW ) ) {
4778 /* The position first */
4780 (float *) (((char *) lpStrideData->u.s.position.lpData) + i * lpStrideData->u.s.position.dwStride);
4782 TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
4784 /* Multiplication with world, view and projection matrix */
4785 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);
4786 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);
4787 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);
4788 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);
4790 TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
4792 /* WARNING: The following things are taken from d3d7 and were not yet checked
4793 * against d3d8 or d3d9!
4796 /* Clipping conditions: From
4797 * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp
4799 * A vertex is clipped if it does not match the following requirements
4803 * 0 < rhw ( Not in d3d7, but tested in d3d7)
4805 * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
4806 * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
4810 if( doClip == FALSE ||
4811 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
4812 (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) &&
4815 /* "Normal" viewport transformation (not clipped)
4816 * 1) The values are divided trough rhw
4817 * 2) The y axis is negative, so multiply it with -1
4818 * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
4819 * -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
4820 * 4) Multiply x with Width/2 and add Width/2
4821 * 5) The same for the height
4822 * 6) Add the viewpoint X and Y to the 2D coordinates and
4823 * The minimum Z value to z
4824 * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
4826 * Well, basically it's simply a linear transformation into viewport
4838 z *= vp.MaxZ - vp.MinZ;
4840 x += vp.Width / 2 + vp.X;
4841 y += vp.Height / 2 + vp.Y;
4846 /* That vertex got clipped
4847 * Contrary to OpenGL it is not dropped completely, it just
4848 * undergoes a different calculation.
4850 TRACE("Vertex got clipped\n");
4857 /* Msdn mentiones that Direct3D9 keeps a list of clipped vertices
4858 * outside of the main vertex buffer memory. That needs some more
4863 TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
4866 ( (float *) dest_ptr)[0] = x;
4867 ( (float *) dest_ptr)[1] = y;
4868 ( (float *) dest_ptr)[2] = z;
4869 ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
4871 dest_ptr += 3 * sizeof(float);
4873 if((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
4874 dest_ptr += sizeof(float);
4877 if (DestFVF & D3DFVF_PSIZE) {
4878 dest_ptr += sizeof(DWORD);
4880 if (DestFVF & D3DFVF_NORMAL) {
4882 (float *) (((float *) lpStrideData->u.s.normal.lpData) + i * lpStrideData->u.s.normal.dwStride);
4883 /* AFAIK this should go into the lighting information */
4884 FIXME("Didn't expect the destination to have a normal\n");
4885 copy_and_next(dest_ptr, normal, 3 * sizeof(float));
4888 if (DestFVF & D3DFVF_DIFFUSE) {
4890 (DWORD *) (((char *) lpStrideData->u.s.diffuse.lpData) + i * lpStrideData->u.s.diffuse.dwStride);
4892 static BOOL warned = FALSE;
4894 if(warned == FALSE) {
4895 ERR("No diffuse color in source, but destination has one\n");
4899 *( (DWORD *) dest_ptr) = 0xffffffff;
4900 dest_ptr += sizeof(DWORD);
4903 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
4906 if (DestFVF & D3DFVF_SPECULAR) {
4907 /* What's the color value in the feedback buffer? */
4909 (DWORD *) (((char *) lpStrideData->u.s.specular.lpData) + i * lpStrideData->u.s.specular.dwStride);
4911 static BOOL warned = FALSE;
4913 if(warned == FALSE) {
4914 ERR("No specular color in source, but destination has one\n");
4918 *( (DWORD *) dest_ptr) = 0xFF000000;
4919 dest_ptr += sizeof(DWORD);
4922 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
4926 for (tex_index = 0; tex_index < numTextures; tex_index++) {
4928 (float *) (((char *) lpStrideData->u.s.texCoords[tex_index].lpData) +
4929 i * lpStrideData->u.s.texCoords[tex_index].dwStride);
4931 ERR("No source texture, but destination requests one\n");
4932 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
4935 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
4942 #undef copy_and_next
4944 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
4945 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4946 IWineD3DVertexBufferImpl *SrcImpl = (IWineD3DVertexBufferImpl *) pVertexDecl;
4947 WineDirect3DVertexStridedData strided;
4949 TRACE("(%p)->(%d,%d,%d,%p,%p,%ld\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
4951 hr = IWineD3DDevice_SetFVF(iface, SrcImpl->fvf);
4952 hr = IWineD3DDevice_SetStreamSource(iface, 0, pVertexDecl, get_flexible_vertex_size(SrcImpl->fvf) * SrcStartIndex, get_flexible_vertex_size(SrcImpl->fvf));
4954 memset(&strided, 0, sizeof(strided));
4955 primitiveConvertToStridedData(iface, &strided, 0);
4957 return process_vertices_strided(This, DestIndex, VertexCount, &strided, SrcImpl->fvf, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags);
4961 * Apply / Get / Set Texture Stage States
4962 * TODO: Verify against dx9 definitions
4965 /* 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 */
4966 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
4967 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4968 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
4969 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4971 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4973 /* Check that the stage is within limits */
4974 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4975 TRACE("Attempt to access invalid texture rejected\n");
4982 case WINED3DTSS_ALPHAOP :
4983 case WINED3DTSS_COLOROP :
4984 /* nothing to do as moved to drawprim for now */
4986 case WINED3DTSS_ADDRESSW :
4987 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
4988 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
4989 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
4992 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
4993 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
4994 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
4995 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
4998 case WINED3DTSS_TEXCOORDINDEX :
5000 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
5002 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
5003 one flag, you can still specify an index value, which the system uses to
5004 determine the texture wrapping mode.
5005 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
5006 means use the vertex position (camera-space) as the input texture coordinates
5007 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
5008 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
5009 to the TEXCOORDINDEX value */
5012 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
5014 switch (Value & 0xFFFF0000) {
5015 case D3DTSS_TCI_PASSTHRU:
5016 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
5017 glDisable(GL_TEXTURE_GEN_S);
5018 glDisable(GL_TEXTURE_GEN_T);
5019 glDisable(GL_TEXTURE_GEN_R);
5020 glDisable(GL_TEXTURE_GEN_Q);
5021 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
5024 case D3DTSS_TCI_CAMERASPACEPOSITION:
5025 /* CameraSpacePosition means use the vertex position, transformed to camera space,
5026 as the input texture coordinates for this stage's texture transformation. This
5027 equates roughly to EYE_LINEAR */
5029 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5030 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5031 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5032 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5033 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
5035 glMatrixMode(GL_MODELVIEW);
5038 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5039 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5040 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5041 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5044 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
5045 glEnable(GL_TEXTURE_GEN_S);
5046 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5047 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5048 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5049 glEnable(GL_TEXTURE_GEN_T);
5050 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5051 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5052 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5053 glEnable(GL_TEXTURE_GEN_R);
5054 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5055 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5056 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5060 case D3DTSS_TCI_CAMERASPACENORMAL:
5062 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5063 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5064 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5065 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5066 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5067 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
5069 glMatrixMode(GL_MODELVIEW);
5072 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5073 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5074 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5075 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5078 glEnable(GL_TEXTURE_GEN_S);
5079 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5080 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5081 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5082 glEnable(GL_TEXTURE_GEN_T);
5083 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5084 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5085 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5086 glEnable(GL_TEXTURE_GEN_R);
5087 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5088 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5089 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5094 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
5096 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5097 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5098 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5099 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5100 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5101 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
5103 glMatrixMode(GL_MODELVIEW);
5106 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5107 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5108 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5109 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5112 glEnable(GL_TEXTURE_GEN_S);
5113 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5114 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5115 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5116 glEnable(GL_TEXTURE_GEN_T);
5117 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5118 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5119 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5120 glEnable(GL_TEXTURE_GEN_R);
5121 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5122 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5123 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5128 /* Unhandled types: */
5131 /* ? disable GL_TEXTURE_GEN_n ? */
5132 glDisable(GL_TEXTURE_GEN_S);
5133 glDisable(GL_TEXTURE_GEN_T);
5134 glDisable(GL_TEXTURE_GEN_R);
5135 glDisable(GL_TEXTURE_GEN_Q);
5136 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
5143 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
5144 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);
5147 case WINED3DTSS_BUMPENVMAT00 :
5148 case WINED3DTSS_BUMPENVMAT01 :
5149 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
5151 case WINED3DTSS_BUMPENVMAT10 :
5152 case WINED3DTSS_BUMPENVMAT11 :
5153 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
5156 case WINED3DTSS_BUMPENVLSCALE :
5157 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5160 case WINED3DTSS_BUMPENVLOFFSET :
5161 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5164 case WINED3DTSS_RESULTARG :
5165 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5169 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
5170 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5179 * Get / Set Texture Stage States
5180 * TODO: Verify against dx9 definitions
5182 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
5183 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5185 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5187 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
5189 /* Reject invalid texture units */
5190 if (Stage >= GL_LIMITS(textures)) {
5191 TRACE("Attempt to access invalid texture rejected\n");
5192 return WINED3DERR_INVALIDCALL;
5195 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
5196 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
5197 This->updateStateBlock->textureState[Stage][Type] = Value;
5202 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
5203 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5204 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
5205 *pValue = This->updateStateBlock->textureState[Stage][Type];
5212 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
5214 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5215 IWineD3DBaseTexture *oldTexture;
5217 oldTexture = This->updateStateBlock->textures[Stage];
5218 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
5220 #if 0 /* TODO: check so vertex textures */
5221 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
5222 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
5227 /* Reject invalid texture units */
5228 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
5229 WARN("Attempt to access invalid texture rejected\n");
5230 return WINED3DERR_INVALIDCALL;
5233 if(pTexture != NULL) {
5234 /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH; The same is
5235 * the case for WINED3DPOOL_SYSTEMMEM textures unless WINED3DDEVCAPS_TEXTURESYSTEMMORY is set.
5236 * We don't check the caps as GetDeviceCaps is inefficient and we don't set the cap anyway.
5238 if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH || ((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SYSTEMMEM) {
5239 WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
5240 return WINED3DERR_INVALIDCALL;
5244 oldTexture = This->updateStateBlock->textures[Stage];
5245 TRACE("GL_LIMITS %d\n",GL_LIMITS(textures));
5246 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
5248 This->updateStateBlock->set.textures[Stage] = TRUE;
5249 This->updateStateBlock->changed.textures[Stage] = TRUE;
5250 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
5251 This->updateStateBlock->textures[Stage] = pTexture;
5253 /* Handle recording of state blocks */
5254 if (This->isRecordingState) {
5255 TRACE("Recording... not performing anything\n");
5259 /** NOTE: MSDN says that setTexture increases the reference count,
5260 * and the the application nust set the texture back to null (or have a leaky application),
5261 * This means we should pass the refcount up to the parent
5262 *******************************/
5263 if (NULL != This->updateStateBlock->textures[Stage]) {
5264 IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
5267 if (NULL != oldTexture) {
5268 IWineD3DBaseTexture_Release(oldTexture);
5274 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
5275 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5276 TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
5278 /* Reject invalid texture units */
5279 if (Stage >= GL_LIMITS(textures)) {
5280 TRACE("Attempt to access invalid texture rejected\n");
5281 return WINED3DERR_INVALIDCALL;
5283 *ppTexture=This->updateStateBlock->textures[Stage];
5285 IWineD3DBaseTexture_AddRef(*ppTexture);
5287 return WINED3DERR_INVALIDCALL;
5294 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
5295 IWineD3DSurface **ppBackBuffer) {
5296 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5297 IWineD3DSwapChain *swapChain;
5300 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
5302 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
5303 if (hr == WINED3D_OK) {
5304 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
5305 IWineD3DSwapChain_Release(swapChain);
5307 *ppBackBuffer = NULL;
5312 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
5313 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5314 WARN("(%p) : stub, calling idirect3d for now\n", This);
5315 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
5318 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
5319 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5320 IWineD3DSwapChain *swapChain;
5323 if(iSwapChain > 0) {
5324 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5325 if (hr == WINED3D_OK) {
5326 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
5327 IWineD3DSwapChain_Release(swapChain);
5329 FIXME("(%p) Error getting display mode\n", This);
5332 /* Don't read the real display mode,
5333 but return the stored mode instead. X11 can't change the color
5334 depth, and some apps are pretty angry if they SetDisplayMode from
5335 24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
5337 Also don't relay to the swapchain because with ddraw it's possible
5338 that there isn't a swapchain at all */
5339 pMode->Width = This->ddraw_width;
5340 pMode->Height = This->ddraw_height;
5341 pMode->Format = This->ddraw_format;
5342 pMode->RefreshRate = 0;
5349 HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
5350 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5351 TRACE("(%p)->(%p)\n", This, hWnd);
5353 This->ddraw_window = hWnd;
5357 HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
5358 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5359 TRACE("(%p)->(%p)\n", This, hWnd);
5361 *hWnd = This->ddraw_window;
5366 * Stateblock related functions
5369 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
5370 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5371 IWineD3DStateBlockImpl *object;
5372 TRACE("(%p)", This);
5374 if (This->isRecordingState) {
5375 return WINED3DERR_INVALIDCALL;
5378 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
5379 if (NULL == object ) {
5380 FIXME("(%p)Error allocating memory for stateblock\n", This);
5381 return E_OUTOFMEMORY;
5383 TRACE("(%p) creted object %p\n", This, object);
5384 object->wineD3DDevice= This;
5385 /** FIXME: object->parent = parent; **/
5386 object->parent = NULL;
5387 object->blockType = WINED3DSBT_ALL;
5389 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
5391 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
5392 This->updateStateBlock = object;
5393 This->isRecordingState = TRUE;
5395 TRACE("(%p) recording stateblock %p\n",This , object);
5399 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
5400 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5402 if (!This->isRecordingState) {
5403 FIXME("(%p) not recording! returning error\n", This);
5404 *ppStateBlock = NULL;
5405 return WINED3DERR_INVALIDCALL;
5408 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
5409 This->isRecordingState = FALSE;
5410 This->updateStateBlock = This->stateBlock;
5411 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
5412 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
5413 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
5418 * Scene related functions
5420 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
5421 /* At the moment we have no need for any functionality at the beginning
5423 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5424 TRACE("(%p) : stub\n", This);
5428 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
5429 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5430 TRACE("(%p)\n", This);
5432 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
5434 checkGLcall("glFlush");
5436 TRACE("End Scene\n");
5437 if(This->renderTarget != NULL) {
5439 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
5440 IUnknown *targetContainer = NULL;
5441 if (WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
5442 || WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
5443 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
5444 /** always dirtify for now. we must find a better way to see that surface have been modified
5445 (Modifications should will only occur via draw-primitive, but we do need better locking
5446 switching to render-to-texture should remove the overhead though.
5448 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
5449 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
5450 IWineD3DSurface_PreLoad(This->renderTarget);
5451 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
5452 IUnknown_Release(targetContainer);
5455 This->sceneEnded = TRUE;
5460 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
5461 CONST RECT* pSourceRect, CONST RECT* pDestRect,
5462 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
5463 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5464 IWineD3DSwapChain *swapChain = NULL;
5466 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
5468 TRACE("(%p) Presenting the frame\n", This);
5470 for(i = 0 ; i < swapchains ; i ++) {
5472 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
5473 TRACE("presentinng chain %d, %p\n", i, swapChain);
5474 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
5475 IWineD3DSwapChain_Release(swapChain);
5481 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
5482 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
5483 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5485 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
5486 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
5487 when the depth-buffer format does not contain stencil buffer information, this method fails. */
5488 GLbitfield glMask = 0;
5489 GLboolean old_ztest;
5490 GLfloat old_z_clear_value;
5491 GLint old_stencil_clear_value;
5492 GLfloat old_color_clear_value[4];
5494 CONST D3DRECT* curRect;
5496 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
5497 Count, pRects, Flags, Z, Stencil);
5501 glEnable(GL_SCISSOR_TEST);
5502 checkGLcall("glEnable GL_SCISSOR_TEST");
5504 if (Count > 0 && pRects) {
5510 /* Only set the values up once, as they are not changing */
5511 if (Flags & D3DCLEAR_STENCIL) {
5512 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
5513 glClearStencil(Stencil);
5514 checkGLcall("glClearStencil");
5515 glMask = glMask | GL_STENCIL_BUFFER_BIT;
5516 glStencilMask(0xFFFFFFFF);
5519 if (Flags & D3DCLEAR_ZBUFFER) {
5520 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
5521 glDepthMask(GL_TRUE);
5522 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
5524 checkGLcall("glClearDepth");
5525 glMask = glMask | GL_DEPTH_BUFFER_BIT;
5528 if (Flags & D3DCLEAR_TARGET) {
5529 TRACE("Clearing screen with glClear to color %lx\n", Color);
5530 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
5531 glClearColor(D3DCOLOR_R(Color),
5535 checkGLcall("glClearColor");
5537 /* Clear ALL colors! */
5538 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5539 glMask = glMask | GL_COLOR_BUFFER_BIT;
5542 /* Now process each rect in turn */
5543 for (i = 0; i < Count || i == 0; i++) {
5546 /* Note gl uses lower left, width/height */
5547 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
5548 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
5549 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
5550 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
5551 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
5552 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
5553 checkGLcall("glScissor");
5555 glScissor(This->stateBlock->viewport.X,
5556 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
5557 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
5558 This->stateBlock->viewport.Width,
5559 This->stateBlock->viewport.Height);
5560 checkGLcall("glScissor");
5563 /* Clear the selected rectangle (or full screen) */
5565 checkGLcall("glClear");
5567 /* Step to the next rectangle */
5568 if (curRect) curRect = curRect + sizeof(D3DRECT);
5571 /* Restore the old values (why..?) */
5572 if (Flags & D3DCLEAR_STENCIL) {
5573 glClearStencil(old_stencil_clear_value);
5574 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
5576 if (Flags & D3DCLEAR_ZBUFFER) {
5577 glDepthMask(old_ztest);
5578 glClearDepth(old_z_clear_value);
5580 if (Flags & D3DCLEAR_TARGET) {
5581 glClearColor(old_color_clear_value[0],
5582 old_color_clear_value[1],
5583 old_color_clear_value[2],
5584 old_color_clear_value[3]);
5585 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
5586 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
5587 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
5588 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
5591 glDisable(GL_SCISSOR_TEST);
5592 checkGLcall("glDisable");
5601 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
5602 UINT PrimitiveCount) {
5604 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5605 This->stateBlock->streamIsUP = FALSE;
5607 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
5608 debug_d3dprimitivetype(PrimitiveType),
5609 StartVertex, PrimitiveCount);
5610 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
5611 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */, NULL);
5617 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
5618 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
5619 D3DPRIMITIVETYPE PrimitiveType,
5620 INT baseVIndex, UINT minIndex,
5621 UINT NumVertices, UINT startIndex, UINT primCount) {
5623 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5625 IWineD3DIndexBuffer *pIB;
5626 WINED3DINDEXBUFFER_DESC IdxBufDsc;
5628 pIB = This->stateBlock->pIndexData;
5629 This->stateBlock->streamIsUP = FALSE;
5631 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
5632 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5633 minIndex, NumVertices, startIndex, baseVIndex, primCount);
5635 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
5636 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
5642 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
5643 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex, NULL);
5648 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
5649 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
5650 UINT VertexStreamZeroStride) {
5651 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5653 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
5654 debug_d3dprimitivetype(PrimitiveType),
5655 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
5657 /* release the stream source */
5658 if (This->stateBlock->streamSource[0] != NULL) {
5659 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5662 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5663 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5664 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5665 This->stateBlock->streamIsUP = TRUE;
5667 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
5668 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */, NULL);
5670 /* MSDN specifies stream zero settings must be set to NULL */
5671 This->stateBlock->streamStride[0] = 0;
5672 This->stateBlock->streamSource[0] = NULL;
5674 /*stream zero settings set to null at end, as per the msdn */
5678 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
5679 UINT MinVertexIndex, UINT NumVertices,
5680 UINT PrimitiveCount, CONST void* pIndexData,
5681 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
5682 UINT VertexStreamZeroStride) {
5684 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5686 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
5687 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5688 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
5689 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
5691 if (IndexDataFormat == WINED3DFMT_INDEX16) {
5697 /* release the stream and index data */
5698 if (This->stateBlock->streamSource[0] != NULL) {
5699 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5701 if (This->stateBlock->pIndexData) {
5702 IWineD3DIndexBuffer_Release(This->stateBlock->pIndexData);
5705 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5706 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5707 This->stateBlock->streamIsUP = TRUE;
5708 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5710 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex, NULL);
5712 /* MSDN specifies stream zero settings and index buffer must be set to NULL */
5713 This->stateBlock->streamSource[0] = NULL;
5714 This->stateBlock->streamStride[0] = 0;
5715 This->stateBlock->pIndexData = NULL;
5720 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
5722 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0, DrawPrimStrideData);
5725 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
5726 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
5727 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5728 HRESULT hr = WINED3D_OK;
5729 WINED3DRESOURCETYPE sourceType;
5730 WINED3DRESOURCETYPE destinationType;
5733 /* TODO: think about moving the code into IWineD3DBaseTexture */
5735 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
5737 /* verify that the source and destination textures aren't NULL */
5738 if (NULL == pSourceTexture || NULL == pDestinationTexture) {
5739 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
5740 This, pSourceTexture, pDestinationTexture);
5741 hr = WINED3DERR_INVALIDCALL;
5744 if (pSourceTexture == pDestinationTexture) {
5745 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
5746 This, pSourceTexture, pDestinationTexture);
5747 hr = WINED3DERR_INVALIDCALL;
5749 /* Verify that the source and destination textures are the same type */
5750 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
5751 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
5753 if (sourceType != destinationType) {
5754 WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
5756 hr = WINED3DERR_INVALIDCALL;
5759 /* check that both textures have the identical numbers of levels */
5760 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
5761 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
5762 hr = WINED3DERR_INVALIDCALL;
5765 if (WINED3D_OK == hr) {
5767 /* Make sure that the destination texture is loaded */
5768 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
5770 /* Update every surface level of the texture */
5771 levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
5773 switch (sourceType) {
5774 case WINED3DRTYPE_TEXTURE:
5776 IWineD3DSurface *srcSurface;
5777 IWineD3DSurface *destSurface;
5779 for (i = 0 ; i < levels ; ++i) {
5780 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture, i, &srcSurface);
5781 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
5782 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5783 IWineD3DSurface_Release(srcSurface);
5784 IWineD3DSurface_Release(destSurface);
5785 if (WINED3D_OK != hr) {
5786 WARN("(%p) : Call to update surface failed\n", This);
5792 case WINED3DRTYPE_CUBETEXTURE:
5794 IWineD3DSurface *srcSurface;
5795 IWineD3DSurface *destSurface;
5796 WINED3DCUBEMAP_FACES faceType;
5798 for (i = 0 ; i < levels ; ++i) {
5799 /* Update each cube face */
5800 for (faceType = D3DCUBEMAP_FACE_POSITIVE_X; faceType <= D3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
5801 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture, faceType, i, &srcSurface);
5802 if (WINED3D_OK != hr) {
5803 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5805 TRACE("Got srcSurface %p\n", srcSurface);
5807 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
5808 if (WINED3D_OK != hr) {
5809 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5811 TRACE("Got desrSurface %p\n", destSurface);
5813 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5814 IWineD3DSurface_Release(srcSurface);
5815 IWineD3DSurface_Release(destSurface);
5816 if (WINED3D_OK != hr) {
5817 WARN("(%p) : Call to update surface failed\n", This);
5824 #if 0 /* TODO: Add support for volume textures */
5825 case WINED3DRTYPE_VOLUMETEXTURE:
5827 IWineD3DVolume srcVolume = NULL;
5828 IWineD3DSurface destVolume = NULL;
5830 for (i = 0 ; i < levels ; ++i) {
5831 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture, i, &srcVolume);
5832 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
5833 hr = IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
5834 IWineD3DVolume_Release(srcSurface);
5835 IWineD3DVolume_Release(destSurface);
5836 if (WINED3D_OK != hr) {
5837 WARN("(%p) : Call to update volume failed\n", This);
5845 FIXME("(%p) : Unsupported source and destination type\n", This);
5846 hr = WINED3DERR_INVALIDCALL;
5853 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
5854 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
5855 CONST RECT* pDestRect, WINED3DTEXTUREFILTERTYPE Filter) {
5856 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5858 TRACE("(%p) : stub\n", This);
5861 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
5862 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5863 /** TODO: remove remove casts to IWineD3DSurfaceImpl *
5864 * NOTE It may be best to move the code into surface to occomplish this
5865 ****************************************/
5867 WINED3DSURFACE_DESC surfaceDesc;
5868 unsigned int surfaceWidth, surfaceHeight;
5869 glDescriptor *targetGlDescription = NULL;
5870 glDescriptor *surfaceGlDescription = NULL;
5871 IWineD3DSwapChainImpl *container = NULL;
5873 IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
5874 IWineD3DSurface_GetGlDesc(pSurface, &surfaceGlDescription);
5875 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5877 surfaceDesc.Width = &surfaceWidth;
5878 surfaceDesc.Height = &surfaceHeight;
5879 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5880 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
5882 /* Ok, I may need to setup some kind of active swapchain reference on the device */
5883 IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
5885 /* TODO: opengl Context switching for swapchains etc... */
5886 if (NULL != container || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
5887 if (NULL != container && (pRenderTarget == container->backBuffer)) {
5888 glReadBuffer(GL_BACK);
5889 vcheckGLcall("glReadBuffer(GL_BACK)");
5890 } else if ((NULL != container && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
5891 glReadBuffer(GL_FRONT);
5892 vcheckGLcall("glReadBuffer(GL_FRONT)");
5893 } else if (pRenderTarget == This->depthStencilBuffer) {
5894 FIXME("Reading of depthstencil not yet supported\n");
5897 glReadPixels(surfaceGlDescription->target,
5898 surfaceGlDescription->level,
5901 surfaceGlDescription->glFormat,
5902 surfaceGlDescription->glType,
5903 (void *)IWineD3DSurface_GetData(pSurface));
5904 vcheckGLcall("glReadPixels(...)");
5905 if(NULL != container ){
5906 IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
5909 IWineD3DBaseTexture *container;
5910 GLenum textureDimensions = GL_TEXTURE_2D;
5912 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
5913 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
5914 IWineD3DBaseTexture_Release(container);
5916 /* TODO: 2D -> Cube surface coppies etc.. */
5917 if (surfaceGlDescription->target != textureDimensions) {
5918 FIXME("(%p) : Texture dimension mismatch\n", This);
5920 glEnable(textureDimensions);
5921 vcheckGLcall("glEnable(GL_TEXTURE_...)");
5922 /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
5923 glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
5924 vcheckGLcall("glBindTexture");
5925 glGetTexImage(surfaceGlDescription->target,
5926 surfaceGlDescription->level,
5927 surfaceGlDescription->glFormat,
5928 surfaceGlDescription->glType,
5929 (void *)IWineD3DSurface_GetData(pSurface));
5930 glDisable(textureDimensions);
5931 vcheckGLcall("glDisable(GL_TEXTURE_...)");
5938 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
5939 IWineD3DSwapChain *swapChain;
5941 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5942 if(hr == WINED3D_OK) {
5943 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
5944 IWineD3DSwapChain_Release(swapChain);
5949 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5950 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5951 /* return a sensible default */
5953 /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
5954 FIXME("(%p) : stub\n", This);
5958 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5959 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5961 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5962 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5963 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5964 return WINED3DERR_INVALIDCALL;
5966 for (j = 0; j < 256; ++j) {
5967 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
5968 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5969 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
5970 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5972 TRACE("(%p) : returning\n", This);
5976 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5977 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5979 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5980 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5981 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5982 return WINED3DERR_INVALIDCALL;
5984 for (j = 0; j < 256; ++j) {
5985 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
5986 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5987 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
5988 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5990 TRACE("(%p) : returning\n", This);
5994 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5995 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5996 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5997 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5998 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5999 return WINED3DERR_INVALIDCALL;
6001 /*TODO: stateblocks */
6002 This->currentPalette = PaletteNumber;
6003 TRACE("(%p) : returning\n", This);
6007 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
6008 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6009 if (PaletteNumber == NULL) {
6010 WARN("(%p) : returning Invalid Call\n", This);
6011 return WINED3DERR_INVALIDCALL;
6013 /*TODO: stateblocks */
6014 *PaletteNumber = This->currentPalette;
6015 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
6019 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
6020 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6021 static BOOL showFixmes = TRUE;
6023 FIXME("(%p) : stub\n", This);
6027 This->softwareVertexProcessing = bSoftware;
6032 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
6033 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6034 static BOOL showFixmes = TRUE;
6036 FIXME("(%p) : stub\n", This);
6039 return This->softwareVertexProcessing;
6043 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
6044 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6045 IWineD3DSwapChain *swapChain;
6048 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
6050 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
6051 if(hr == WINED3D_OK){
6052 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
6053 IWineD3DSwapChain_Release(swapChain);
6055 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
6061 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
6062 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6063 static BOOL showfixmes = TRUE;
6064 if(nSegments != 0.0f) {
6066 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
6073 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
6074 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6075 static BOOL showfixmes = TRUE;
6077 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
6083 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
6084 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6085 /** TODO: remove casts to IWineD3DSurfaceImpl
6086 * NOTE: move code to surface to accomplish this
6087 ****************************************/
6088 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
6089 int srcWidth, srcHeight;
6090 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
6091 WINED3DFORMAT destFormat, srcFormat;
6093 int destLeft, destTop;
6094 WINED3DPOOL srcPool, destPool;
6096 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
6097 glDescriptor *glDescription = NULL;
6098 GLenum textureDimensions = GL_TEXTURE_2D;
6099 IWineD3DBaseTexture *baseTexture;
6101 WINED3DSURFACE_DESC winedesc;
6103 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
6104 memset(&winedesc, 0, sizeof(winedesc));
6105 winedesc.Width = &srcSurfaceWidth;
6106 winedesc.Height = &srcSurfaceHeight;
6107 winedesc.Pool = &srcPool;
6108 winedesc.Format = &srcFormat;
6110 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
6112 winedesc.Width = &destSurfaceWidth;
6113 winedesc.Height = &destSurfaceHeight;
6114 winedesc.Pool = &destPool;
6115 winedesc.Format = &destFormat;
6116 winedesc.Size = &destSize;
6118 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6120 if(srcPool != WINED3DPOOL_SYSTEMMEM || destPool != WINED3DPOOL_DEFAULT){
6121 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
6122 return WINED3DERR_INVALIDCALL;
6125 if (destFormat == WINED3DFMT_UNKNOWN) {
6126 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
6127 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
6129 /* Get the update surface description */
6130 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6133 /* Make sure the surface is loaded and up to date */
6134 IWineD3DSurface_PreLoad(pDestinationSurface);
6136 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
6140 /* this needs to be done in lines if the sourceRect != the sourceWidth */
6141 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
6142 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
6143 destLeft = pDestPoint ? pDestPoint->x : 0;
6144 destTop = pDestPoint ? pDestPoint->y : 0;
6147 /* This function doesn't support compressed textures
6148 the pitch is just bytesPerPixel * width */
6149 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
6150 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
6151 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
6152 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
6154 /* TODO DXT formats */
6156 if(pSourceRect != NULL && pSourceRect->top != 0){
6157 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
6159 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
6161 ,glDescription->level
6166 ,glDescription->glFormat
6167 ,glDescription->glType
6168 ,IWineD3DSurface_GetData(pSourceSurface)
6172 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
6174 /* need to lock the surface to get the data */
6175 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
6178 /* TODO: Cube and volume support */
6180 /* not a whole row so we have to do it a line at a time */
6183 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
6184 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
6186 for(j = destTop ; j < (srcHeight + destTop) ; j++){
6188 glTexSubImage2D(glDescription->target
6189 ,glDescription->level
6194 ,glDescription->glFormat
6195 ,glDescription->glType
6196 ,data /* could be quicker using */
6201 } else { /* Full width, so just write out the whole texture */
6203 if (WINED3DFMT_DXT1 == destFormat ||
6204 WINED3DFMT_DXT2 == destFormat ||
6205 WINED3DFMT_DXT3 == destFormat ||
6206 WINED3DFMT_DXT4 == destFormat ||
6207 WINED3DFMT_DXT5 == destFormat) {
6208 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
6209 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
6210 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
6211 FIXME("Updating part of a compressed texture is not supported at the moment\n");
6212 } if (destFormat != srcFormat) {
6213 FIXME("Updating mixed format compressed texture is not curretly support\n");
6215 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
6216 glDescription->level,
6217 glDescription->glFormatInternal,
6222 IWineD3DSurface_GetData(pSourceSurface));
6225 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
6230 if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
6232 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
6233 to repack the data from pow2Width/Height to expected Width,Height, this makes the
6234 data returned by GetData non-power2 width/height with hardware non-power2
6235 pow2Width/height are set to surface width height, repacking isn't needed so it
6236 doesn't matter which function gets called. */
6237 glTexSubImage2D(glDescription->target
6238 ,glDescription->level
6243 ,glDescription->glFormat
6244 ,glDescription->glType
6245 ,IWineD3DSurface_GetData(pSourceSurface)
6249 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
6250 glTexSubImage2D(glDescription->target
6251 ,glDescription->level
6254 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
6255 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
6256 ,glDescription->glFormat
6257 ,glDescription->glType
6258 ,IWineD3DSurface_GetData(pSourceSurface)
6264 checkGLcall("glTexSubImage2D");
6266 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
6267 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
6268 * surface bigger than it needs to be hmm.. */
6269 if (WINED3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
6270 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
6271 IWineD3DBaseTexture_Release(baseTexture);
6274 glDisable(textureDimensions); /* This needs to be managed better.... */
6280 /* Used by DirectX 8 */
6281 HRESULT WINAPI IWineD3DDeviceImpl_CopyRects(IWineD3DDevice *iface,
6282 IWineD3DSurface* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
6283 IWineD3DSurface* pDestinationSurface, CONST POINT* pDestPointsArray) {
6285 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6286 HRESULT hr = WINED3D_OK;
6287 WINED3DFORMAT srcFormat, destFormat;
6288 UINT srcWidth, destWidth;
6289 UINT srcHeight, destHeight;
6291 WINED3DSURFACE_DESC winedesc;
6293 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
6294 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
6297 /* Check that the source texture is in WINED3DPOOL_SYSTEMMEM and the destination texture is in WINED3DPOOL_DEFAULT */
6298 memset(&winedesc, 0, sizeof(winedesc));
6300 winedesc.Format = &srcFormat;
6301 winedesc.Width = &srcWidth;
6302 winedesc.Height = &srcHeight;
6303 winedesc.Size = &srcSize;
6304 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
6306 winedesc.Format = &destFormat;
6307 winedesc.Width = &destWidth;
6308 winedesc.Height = &destHeight;
6309 winedesc.Size = NULL;
6310 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6312 /* Check that the source and destination formats match */
6313 if (srcFormat != destFormat && WINED3DFMT_UNKNOWN != destFormat) {
6314 WARN("(%p) source %p format must match the dest %p format, returning WINED3DERR_INVALIDCALL\n", This, pSourceSurface, pDestinationSurface);
6315 return WINED3DERR_INVALIDCALL;
6316 } else if (WINED3DFMT_UNKNOWN == destFormat) {
6317 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
6318 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
6319 destFormat = srcFormat;
6322 /* Quick if complete copy ... */
6323 if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
6325 if (srcWidth == destWidth && srcHeight == destHeight) {
6326 WINED3DLOCKED_RECT lrSrc;
6327 WINED3DLOCKED_RECT lrDst;
6328 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, NULL, WINED3DLOCK_READONLY);
6329 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, NULL, 0L);
6330 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", srcWidth, srcHeight);
6332 memcpy(lrDst.pBits, lrSrc.pBits, srcSize);
6334 IWineD3DSurface_UnlockRect(pSourceSurface);
6335 IWineD3DSurface_UnlockRect(pDestinationSurface);
6336 TRACE("Unlocked src and dst\n");
6340 FIXME("Wanted to copy all surfaces but size not compatible, returning WINED3DERR_INVALIDCALL\n");
6341 hr = WINED3DERR_INVALIDCALL;
6346 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
6348 int bytesPerPixel = ((IWineD3DSurfaceImpl *) pSourceSurface)->bytesPerPixel;
6351 /* Copy rect by rect */
6352 for (i = 0; i < cRects; ++i) {
6353 CONST RECT* r = &pSourceRectsArray[i];
6354 CONST POINT* p = &pDestPointsArray[i];
6357 WINED3DLOCKED_RECT lrSrc;
6358 WINED3DLOCKED_RECT lrDst;
6361 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
6362 if (srcFormat == WINED3DFMT_DXT1) {
6363 copyperline = ((r->right - r->left) * bytesPerPixel) / 2; /* DXT1 is half byte per pixel */
6365 copyperline = ((r->right - r->left) * bytesPerPixel);
6368 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, r, WINED3DLOCK_READONLY);
6369 dest_rect.left = p->x;
6370 dest_rect.top = p->y;
6371 dest_rect.right = p->x + (r->right - r->left);
6372 dest_rect.bottom= p->y + (r->bottom - r->top);
6373 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, &dest_rect, 0L);
6374 TRACE("Locked src and dst\n");
6376 /* Find where to start */
6377 for (j = 0; j < (r->bottom - r->top - 1); ++j) {
6378 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
6380 IWineD3DSurface_UnlockRect(pSourceSurface);
6381 IWineD3DSurface_UnlockRect(pDestinationSurface);
6382 TRACE("Unlocked src and dst\n");
6385 FIXME("Wanted to copy partial surfaces not implemented, returning WINED3DERR_INVALIDCALL\n");
6386 hr = WINED3DERR_INVALIDCALL;
6393 /* Implementation details at http://developer.nvidia.com/attach/6494
6395 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
6396 hmm.. no longer supported use
6397 OpenGL evaluators or tessellate surfaces within your application.
6400 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
6401 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
6402 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6403 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
6404 FIXME("(%p) : Stub\n", This);
6409 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
6410 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
6411 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6412 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
6413 FIXME("(%p) : Stub\n", This);
6417 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
6418 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6419 TRACE("(%p) Handle(%d)\n", This, Handle);
6420 FIXME("(%p) : Stub\n", This);
6424 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
6425 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
6426 fill a surface with a block of color! */
6427 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6428 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
6429 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
6430 IWineD3DSwapChainImpl *container = NULL;
6431 BOOL isRenderTarget = FALSE;
6432 unsigned int width, height;
6433 unsigned int top, left;
6436 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
6438 if (surface->resource.pool != WINED3DPOOL_DEFAULT) {
6439 FIXME("call to colorfill with non WINED3DPOOL_DEFAULT surface\n");
6440 return WINED3DERR_INVALIDCALL;
6443 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
6444 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
6445 if (WINED3DUSAGE_RENDERTARGET & surface->resource.usage) {
6446 /* TODO: make sure we set everything back to the way it was, and context management!
6447 glGetIntegerv(GL_READ_BUFFER, &prev_read);
6448 vcheckGLcall("glIntegerv");
6449 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
6450 vcheckGLcall("glIntegerv");
6452 TRACE("Color fill to render targets may cause some graphics issues\n");
6453 if (pSurface == container->frontBuffer) {
6454 glDrawBuffer(GL_FRONT);
6456 glDrawBuffer(GL_BACK);
6459 if (WINED3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
6460 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld\n", surface, surface->resource.usage);
6462 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
6464 if (container != NULL) {
6465 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
6467 /* we can use GL_STENCIL_INDEX etc...*/
6470 if (container != NULL) {
6471 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
6473 isRenderTarget = TRUE;
6475 /* TODO: drawing to GL_FRONT and GL_BACK */
6476 /* TODO: see if things can be speeded up by using the correct
6477 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
6478 if (pRect == NULL) {
6481 width = surface->currentDesc.Width;
6482 height = surface->currentDesc.Height;
6486 width = pRect->x2 - left;
6487 height = pRect->y2 - top;
6490 data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
6491 /* Create a 'line' of color color, in the correct format for the surface */
6492 for (u = 0 ; u < width ; u ++) {
6497 if (isRenderTarget == FALSE) {
6498 glDescriptor *glDesc;
6499 IWineD3DSurface_PreLoad(pSurface);
6501 /* draw a block of the coloured line on the sufrace */
6502 IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
6503 for (v = 0 ; v< height;v++) {
6504 glTexSubImage2D(glDesc->target
6505 ,glDesc->level /* level */
6515 checkGLcall("glTexSubImage2D");
6517 glDisable(glDesc->target);
6519 /** FIXME: Using GLClear may be faster **/
6520 glRasterPos2i(left, top);
6521 glPixelZoom((float)width ,(float)height);
6522 glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
6523 checkGLcall("glDrawPixels");
6525 HeapFree(GetProcessHeap(), 0, data);
6531 /* rendertarget and deptth stencil functions */
6532 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
6533 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6535 /* FIXME: Implelent RenderTargetIndex >0 */
6536 if(RenderTargetIndex > 0)
6537 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
6539 *ppRenderTarget = This->renderTarget;
6540 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
6541 /* Note inc ref on returned surface */
6542 if(*ppRenderTarget != NULL)
6543 IWineD3DSurface_AddRef(*ppRenderTarget);
6547 HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
6548 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6549 IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
6550 IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
6551 IWineD3DSwapChainImpl *Swapchain;
6554 TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
6556 hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
6557 if(hr != WINED3D_OK) {
6558 ERR("Can't get the swapchain\n");
6562 /* Make sure to release the swapchain */
6563 IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
6565 if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
6566 ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6567 return WINED3DERR_INVALIDCALL;
6569 else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
6570 ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6571 return WINED3DERR_INVALIDCALL;
6574 if(Swapchain->frontBuffer != Front) {
6575 TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
6577 if(Swapchain->frontBuffer)
6578 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
6579 Swapchain->frontBuffer = Front;
6581 if(Swapchain->frontBuffer) {
6582 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
6585 if(Swapchain->backBuffer != Back) {
6586 TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
6588 if(!Swapchain->backBuffer) {
6589 /* GL was told to draw to the front buffer at creation,
6592 glDrawBuffer(GL_BACK);
6593 checkGLcall("glDrawBuffer(GL_BACK)");
6595 /* That makes problems - disable for now */
6596 /* glDrawBuffer(GL_FRONT); */
6597 checkGLcall("glDrawBuffer(GL_FRONT)");
6601 if(Swapchain->backBuffer)
6602 IWineD3DSurface_SetContainer(Swapchain->backBuffer, NULL);
6603 Swapchain->backBuffer = Back;
6605 if(Swapchain->backBuffer) {
6606 IWineD3DSurface_SetContainer(Swapchain->backBuffer, (IWineD3DBase *) Swapchain);
6614 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
6615 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6616 *ppZStencilSurface = This->depthStencilBuffer;
6617 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
6619 if(*ppZStencilSurface != NULL) {
6620 /* Note inc ref on returned surface */
6621 IWineD3DSurface_AddRef(*ppZStencilSurface);
6626 /* internal static helper functions */
6627 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
6628 IWineD3DSurface *RenderSurface);
6630 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
6631 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6632 HRESULT hr = WINED3D_OK;
6633 WINED3DVIEWPORT viewport;
6635 TRACE("(%p) Swapping rendertarget\n",This);
6636 if (RenderTargetIndex > 0) {
6637 FIXME("(%p) Render targets other than the first are not supported\n",This);
6638 RenderTargetIndex = 0;
6641 /* MSDN says that null disables the render target
6642 but a device must always be associated with a render target
6643 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
6645 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
6648 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
6649 FIXME("Trying to set render target 0 to NULL\n");
6650 return WINED3DERR_INVALIDCALL;
6652 /* TODO: replace Impl* usage with interface usage */
6653 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
6654 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);
6655 return WINED3DERR_INVALIDCALL;
6657 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
6658 * builds, but I think wine counts as a 'debug' build for now.
6659 ******************************/
6660 /* If we are trying to set what we already have, don't bother */
6661 if (pRenderTarget == This->renderTarget) {
6662 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6664 /* Otherwise, set the render target up */
6666 if (FALSE == This->sceneEnded) {
6667 IWineD3DDevice_EndScene(iface);
6669 TRACE("clearing renderer\n");
6670 /* IWineD3DDeviceImpl_CleanRender(iface); */
6671 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6672 depending on the renter target implementation being used.
6673 A shared context implementation will share all buffers between all rendertargets (including swapchains),
6674 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6675 stencil buffer and incure an extra memory overhead */
6676 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
6679 if (SUCCEEDED(hr)) {
6680 /* Finally, reset the viewport as the MSDN states. */
6681 /* TODO: Replace impl usage */
6682 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
6683 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
6686 viewport.MaxZ = 1.0f;
6687 viewport.MinZ = 0.0f;
6688 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
6690 FIXME("Unknown error setting the render target\n");
6692 This->sceneEnded = FALSE;
6696 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
6697 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6698 HRESULT hr = WINED3D_OK;
6699 IWineD3DSurface *tmp;
6701 TRACE("(%p) Swapping z-buffer\n",This);
6703 if (pNewZStencil == This->stencilBufferTarget) {
6704 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6706 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6707 * depending on the renter target implementation being used.
6708 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
6709 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6710 * stencil buffer and incure an extra memory overhead
6711 ******************************************************/
6714 tmp = This->stencilBufferTarget;
6715 This->stencilBufferTarget = pNewZStencil;
6716 /* should we be calling the parent or the wined3d surface? */
6717 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
6718 if (NULL != tmp) IWineD3DSurface_Release(tmp);
6720 /** TODO: glEnable/glDisable on depth/stencil depending on
6721 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
6722 **********************************************************/
6729 #ifdef GL_VERSION_1_3
6730 /* Internal functions not in DirectX */
6731 /** TODO: move this off to the opengl context manager
6732 *(the swapchain doesn't need to know anything about offscreen rendering!)
6733 ****************************************************/
6735 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
6737 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6739 TRACE("(%p), %p\n", This, swapchain);
6741 if (swapchain->win != swapchain->drawable) {
6742 /* Set everything back the way it ws */
6743 swapchain->render_ctx = swapchain->glCtx;
6744 swapchain->drawable = swapchain->win;
6749 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
6750 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
6751 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6754 unsigned int height;
6755 WINED3DFORMAT format;
6756 WINED3DSURFACE_DESC surfaceDesc;
6757 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
6758 surfaceDesc.Width = &width;
6759 surfaceDesc.Height = &height;
6760 surfaceDesc.Format = &format;
6761 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
6763 /* I need a get width/height function (and should do something with the format) */
6764 for (i = 0; i < CONTEXT_CACHE; ++i) {
6765 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
6766 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
6767 the pSurface can be set to 0 allowing it to be reused from cache **/
6768 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
6769 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
6770 *context = &This->contextCache[i];
6773 if (This->contextCache[i].Width == 0) {
6774 This->contextCache[i].pSurface = pSurface;
6775 This->contextCache[i].Width = width;
6776 This->contextCache[i].Height = height;
6777 *context = &This->contextCache[i];
6781 if (i == CONTEXT_CACHE) {
6782 int minUsage = 0x7FFFFFFF; /* MAX_INT */
6783 glContext *dropContext = 0;
6784 for (i = 0; i < CONTEXT_CACHE; i++) {
6785 if (This->contextCache[i].usedcount < minUsage) {
6786 dropContext = &This->contextCache[i];
6787 minUsage = This->contextCache[i].usedcount;
6790 /* clean up the context (this doesn't work for ATI at the moment */
6792 glXDestroyContext(swapchain->display, dropContext->context);
6793 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
6796 dropContext->Width = 0;
6797 dropContext->pSurface = pSurface;
6798 *context = dropContext;
6800 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
6801 for (i = 0; i < CONTEXT_CACHE; i++) {
6802 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
6806 if (*context != NULL)
6809 return E_OUTOFMEMORY;
6813 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
6814 * the functionality needs splitting up so that we don't do more than we should do.
6815 * this only seems to impact performance a little.
6816 ******************************/
6817 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
6818 IWineD3DSurface *RenderSurface) {
6819 HRESULT ret = WINED3DERR_INVALIDCALL;
6822 * Currently only active for GLX >= 1.3
6823 * for others versions we'll have to use GLXPixmaps
6825 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
6826 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
6827 * so only check OpenGL version
6828 * ..........................
6829 * I don't believe that it is a problem with NVidia headers,
6830 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
6831 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
6833 * Your application will report GLX version 1.2 on glXQueryVersion.
6834 * However, it is safe to call the GLX 1.3 functions as described below.
6836 #if defined(GL_VERSION_1_3)
6838 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6839 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
6840 IWineD3DSurface *tmp;
6841 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
6842 GLXFBConfig* cfgs = NULL;
6846 IWineD3DSwapChain *currentSwapchain;
6847 IWineD3DSwapChainImpl *swapchain;
6848 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
6849 * but switch them off if the StencilSurface is set to NULL
6850 ** *********************************************************/
6851 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
6852 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
6855 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
6856 it StencilSurface != NULL && zBufferTarget == NULL switch it on
6859 #define PUSH1(att) attribs[nAttribs++] = (att);
6860 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
6862 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
6864 /** TODO: remove the reff to Impl (context manager should fix this!) **/
6865 IWineD3DSwapChainImpl *impSwapChain;
6866 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
6867 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
6868 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
6873 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
6874 PUSH2(GLX_X_RENDERABLE, TRUE);
6875 PUSH2(GLX_DOUBLEBUFFER, TRUE);
6876 TRACE("calling makeglcfg\n");
6877 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
6880 TRACE("calling chooseFGConfig\n");
6881 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
6884 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
6885 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
6886 why we failed and only show this message once! */
6887 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"); /**/
6889 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
6890 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
6891 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
6892 PUSH2(GLX_DOUBLEBUFFER, FALSE);
6893 TRACE("calling makeglcfg\n");
6894 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
6896 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
6903 for (i = 0; i < nCfgs; ++i) {
6904 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
6905 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
6906 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
6909 if (NULL != This->renderTarget) {
6911 vcheckGLcall("glFlush");
6912 /** This is only useful if the old render target was a swapchain,
6913 * we need to supercede this with a function that displays
6914 * the current buffer on the screen. This is easy to do in glx1.3 but
6915 * we need to do copy-write pixels in glx 1.2.
6916 ************************************************/
6917 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
6919 printf("Hit Enter to get next frame ...\n");
6925 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain) != WINED3D_OK) {
6926 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
6927 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
6931 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
6932 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
6933 **********************************************************************/
6934 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == WINED3D_OK) {
6935 /* We also need to make sure that the lights &co are also in the context of the swapchains */
6936 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
6937 TRACE("making swapchain active\n");
6938 if (RenderSurface != This->renderTarget) {
6939 if (RenderSurface == swapchain->backBuffer) {
6941 /* This could be flagged so that some operations work directly with the front buffer */
6942 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
6944 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
6946 TRACE("Error in setting current context: context %p drawable %ld !\n",
6947 impSwapChain->glCtx, impSwapChain->win);
6950 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
6952 checkGLcall("glXMakeContextCurrent");
6954 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
6956 else if (pbuffer_support == TRUE && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
6958 /** ********************************************************************
6959 * This is a quickly hacked out implementation of offscreen textures.
6960 * It will work in most cases but there may be problems if the client
6961 * modifies the texture directly, or expects the contents of the rendertarget
6964 * There are some real speed vs compatibility issues here:
6965 * we should really use a new context for every texture, but that eats ram.
6966 * we should also be restoring the texture to the pbuffer but that eats CPU
6967 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
6968 * but if this means reusing the display backbuffer then we need to make sure that
6969 * states are correctly preserved.
6970 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
6971 * and gain a good performance increase at the cost of compatibility.
6972 * I would suggest that, when this is the case, a user configurable flag be made
6973 * available, allowing the user to choose the best emulated experience for them.
6974 *********************************************************************/
6976 XVisualInfo *visinfo;
6977 glContext *newContext;
6979 /* Here were using a shared context model */
6980 if (WINED3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
6981 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6984 /* If the context doesn't exist then create a new one */
6985 /* TODO: This should really be part of findGlContext */
6986 if (NULL == newContext->context) {
6988 TRACE("making new buffer\n");
6990 PUSH2(GLX_PBUFFER_WIDTH, newContext->Width);
6991 PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
6994 newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
6996 /** ****************************************
6997 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
6999 * In future releases, we may provide the calls glXCreateNewContext,
7000 * glXQueryDrawable and glXMakeContextCurrent.
7001 * so until then we have to use glXGetVisualFromFBConfig &co..
7002 ********************************************/
7005 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
7007 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
7009 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
7013 if (NULL == newContext || NULL == newContext->context) {
7014 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
7016 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
7017 if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
7018 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
7021 /* Clean up the old context */
7022 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
7023 /* Set the current context of the swapchain to the new context */
7024 impSwapChain->drawable = newContext->drawable;
7025 impSwapChain->render_ctx = newContext->context;
7029 #if 1 /* Apply the stateblock to the new context
7030 FIXME: This is a bit of a hack, each context should know it's own state,
7031 the directX current directX state should then be applied to the context */
7034 IWineD3DStateBlockImpl *oldUpdateStateBlock;
7035 oldUpdateStateBlock = This->updateStateBlock;
7036 oldRecording= This->isRecordingState;
7037 This->isRecordingState = FALSE;
7038 This->updateStateBlock = This->stateBlock;
7039 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
7041 This->isRecordingState = oldRecording;
7042 This->updateStateBlock = oldUpdateStateBlock;
7047 /* clean up the current rendertargets swapchain (if it belonged to one) */
7048 if (currentSwapchain != NULL) {
7049 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
7052 /* Were done with the opengl context management, setup the rendertargets */
7054 tmp = This->renderTarget;
7055 This->renderTarget = RenderSurface;
7056 IWineD3DSurface_AddRef(This->renderTarget);
7057 IWineD3DSurface_Release(tmp);
7063 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
7064 /* Check that the container is not a swapchain member */
7066 IWineD3DSwapChain *tmpSwapChain;
7067 if (WINED3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
7068 This->renderUpsideDown = TRUE;
7070 This->renderUpsideDown = FALSE;
7071 IWineD3DSwapChain_Release(tmpSwapChain);
7073 /* Force updating the cull mode */
7074 TRACE("setting render state\n");
7075 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
7076 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
7078 /* Force updating projection matrix */
7079 This->last_was_rhw = FALSE;
7080 This->proj_valid = FALSE;
7088 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
7089 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
7094 if ( NULL != impSwapChain) {
7095 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
7103 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
7104 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
7105 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7106 /* TODO: the use of Impl is deprecated. */
7107 /* some basic validation checks */
7108 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
7110 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
7112 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
7113 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
7114 return WINED3DERR_INVALIDCALL;
7116 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
7117 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
7118 return WINED3DERR_INVALIDCALL;
7120 /* TODO: make the cursor 'real' */
7122 This->xHotSpot = XHotSpot;
7123 This->yHotSpot = YHotSpot;
7128 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
7129 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7130 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
7132 This->xScreenSpace = XScreenSpace;
7133 This->yScreenSpace = YScreenSpace;
7139 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
7140 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7141 TRACE("(%p) : visible(%d)\n", This, bShow);
7143 This->bCursorVisible = bShow;
7148 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
7149 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7150 TRACE("(%p) : state (%lu)\n", This, This->state);
7151 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
7152 switch (This->state) {
7155 case WINED3DERR_DEVICELOST:
7157 ResourceList *resourceList = This->resources;
7158 while (NULL != resourceList) {
7159 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
7160 return WINED3DERR_DEVICENOTRESET;
7161 resourceList = resourceList->next;
7163 return WINED3DERR_DEVICELOST;
7165 case WINED3DERR_DRIVERINTERNALERROR:
7166 return WINED3DERR_DRIVERINTERNALERROR;
7170 return WINED3DERR_DRIVERINTERNALERROR;
7174 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
7175 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7176 /** FIXME: Resource tracking needs to be done,
7177 * The closes we can do to this is set the priorities of all managed textures low
7178 * and then reset them.
7179 ***********************************************************/
7180 FIXME("(%p) : stub\n", This);
7184 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
7185 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7186 /** FIXME: Resource trascking needs to be done.
7187 * in effect this pulls all non only default
7188 * textures out of video memory and deletes all glTextures (glDeleteTextures)
7189 * and should clear down the context and set it up according to pPresentationParameters
7190 ***********************************************************/
7191 FIXME("(%p) : stub\n", This);
7195 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
7196 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7197 /** FIXME: always true at the moment **/
7198 if(bEnableDialogs == FALSE) {
7199 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
7205 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
7206 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7207 TRACE("(%p) : pParameters %p\n", This, pParameters);
7209 *pParameters = This->createParms;
7213 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
7214 IWineD3DSwapChain *swapchain;
7215 HRESULT hrc = WINED3D_OK;
7217 TRACE("Relaying to swapchain\n");
7219 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7220 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
7221 IWineD3DSwapChain_Release(swapchain);
7226 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
7227 IWineD3DSwapChain *swapchain;
7228 HRESULT hrc = WINED3D_OK;
7230 TRACE("Relaying to swapchain\n");
7232 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7233 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
7234 IWineD3DSwapChain_Release(swapchain);
7240 /** ********************************************************
7241 * Notification functions
7242 ** ********************************************************/
7243 /** This function must be called in the release of a resource when ref == 0,
7244 * the contents of resource must still be correct,
7245 * any handels to other resource held by the caller must be closed
7246 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
7247 *****************************************************/
7248 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7249 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7250 ResourceList* resourceList;
7252 TRACE("(%p) : resource %p\n", This, resource);
7254 EnterCriticalSection(&resourceStoreCriticalSection);
7256 /* add a new texture to the frot of the linked list */
7257 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
7258 resourceList->resource = resource;
7260 /* Get the old head */
7261 resourceList->next = This->resources;
7263 This->resources = resourceList;
7264 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
7267 LeaveCriticalSection(&resourceStoreCriticalSection);
7272 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7273 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7274 ResourceList* resourceList = NULL;
7275 ResourceList* previousResourceList = NULL;
7277 TRACE("(%p) : resource %p\n", This, resource);
7280 EnterCriticalSection(&resourceStoreCriticalSection);
7282 resourceList = This->resources;
7284 while (resourceList != NULL) {
7285 if(resourceList->resource == resource) break;
7286 previousResourceList = resourceList;
7287 resourceList = resourceList->next;
7290 if (resourceList == NULL) {
7291 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
7293 LeaveCriticalSection(&resourceStoreCriticalSection);
7297 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
7299 /* make sure we don't leave a hole in the list */
7300 if (previousResourceList != NULL) {
7301 previousResourceList->next = resourceList->next;
7303 This->resources = resourceList->next;
7307 LeaveCriticalSection(&resourceStoreCriticalSection);
7313 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
7314 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7317 TRACE("(%p) : resource %p\n", This, resource);
7318 switch(IWineD3DResource_GetType(resource)){
7319 case WINED3DRTYPE_SURFACE:
7320 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
7322 case WINED3DRTYPE_TEXTURE:
7323 case WINED3DRTYPE_CUBETEXTURE:
7324 case WINED3DRTYPE_VOLUMETEXTURE:
7325 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
7326 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7327 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7328 This->stateBlock->textures[counter] = NULL;
7330 if (This->updateStateBlock != This->stateBlock ){
7331 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7332 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7333 This->updateStateBlock->textures[counter] = NULL;
7338 case WINED3DRTYPE_VOLUME:
7339 /* TODO: nothing really? */
7341 case WINED3DRTYPE_VERTEXBUFFER:
7342 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
7345 TRACE("Cleaning up stream pointers\n");
7347 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
7348 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
7349 FINDOUT: should changes.streamSource[StreamNumber] be set ?
7351 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7352 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
7353 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
7354 This->updateStateBlock->streamSource[streamNumber] = 0;
7355 /* Set changed flag? */
7358 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) */
7359 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
7360 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
7361 This->stateBlock->streamSource[streamNumber] = 0;
7364 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
7365 else { /* This shouldn't happen */
7366 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
7373 case WINED3DRTYPE_INDEXBUFFER:
7374 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
7375 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7376 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7377 This->updateStateBlock->pIndexData = NULL;
7380 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
7381 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7382 This->stateBlock->pIndexData = NULL;
7388 FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
7393 /* Remove the resoruce from the resourceStore */
7394 IWineD3DDeviceImpl_RemoveResource(iface, resource);
7396 TRACE("Resource released\n");
7401 /** This function is to be called by the swapchain when it is released and it's ref = 0
7402 *****************************************************/
7403 void WINAPI IWineD3DDeviceImpl_SwapChainReleased(IWineD3DDevice *iface, IWineD3DSwapChain *swapChain){
7404 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7405 SwapChainList **nextSwapchain;
7406 nextSwapchain = &This->swapchains;
7408 /* Check to see if the swapchian is being used as the render target */
7409 if (This->renderTarget != NULL) {
7410 IWineD3DSurface *swapchainBackBuffer;
7412 IWineD3DSwapChain_GetBackBuffer(swapChain, 0 ,( D3DBACKBUFFER_TYPE) 0, &swapchainBackBuffer);
7413 if (This->renderTarget == swapchainBackBuffer) {
7414 /* Don't know what to do, so warn and carry on as usual (which in this case leaves the renderterget in limbo) */
7415 FIXME("Atempting to release a swapchain that is currently beuing used as a render target, behaviour is undefined\n");
7419 /* Go through the swapchain list and try to find the swapchain being released */
7420 while(*nextSwapchain != NULL && (*nextSwapchain)->swapchain != swapChain) {
7421 nextSwapchain = &(*nextSwapchain)->next;
7424 /* Check to see if we found the swapchain */
7425 if (NULL != *nextSwapchain) {
7426 /* We found the swapchain so remove it from the list */
7427 TRACE("(%p) releasing swapchain(%p)\n", iface, swapChain);
7428 HeapFree(GetProcessHeap(), 0 , *nextSwapchain);
7429 *nextSwapchain = (*nextSwapchain)->next;
7431 /* We didn't find the swapchain on the list, this can only heppen because of a programming error in wined3d */
7432 FIXME("(%p) Attempting to release a swapchain (%p) that hasn't been stored\n", iface, swapChain);
7435 TRACE("swapchain (%p) released\n", swapChain);
7439 /**********************************************************
7440 * IWineD3DDevice VTbl follows
7441 **********************************************************/
7443 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
7445 /*** IUnknown methods ***/
7446 IWineD3DDeviceImpl_QueryInterface,
7447 IWineD3DDeviceImpl_AddRef,
7448 IWineD3DDeviceImpl_Release,
7449 /*** IWineD3DDevice methods ***/
7450 IWineD3DDeviceImpl_GetParent,
7451 /*** Creation methods**/
7452 IWineD3DDeviceImpl_CreateVertexBuffer,
7453 IWineD3DDeviceImpl_CreateIndexBuffer,
7454 IWineD3DDeviceImpl_CreateStateBlock,
7455 IWineD3DDeviceImpl_CreateSurface,
7456 IWineD3DDeviceImpl_CreateTexture,
7457 IWineD3DDeviceImpl_CreateVolumeTexture,
7458 IWineD3DDeviceImpl_CreateVolume,
7459 IWineD3DDeviceImpl_CreateCubeTexture,
7460 IWineD3DDeviceImpl_CreateQuery,
7461 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
7462 IWineD3DDeviceImpl_CreateVertexDeclaration,
7463 IWineD3DDeviceImpl_CreateVertexShader,
7464 IWineD3DDeviceImpl_CreatePixelShader,
7465 IWineD3DDeviceImpl_CreatePalette,
7466 /*** Odd functions **/
7467 IWineD3DDeviceImpl_Init3D,
7468 IWineD3DDeviceImpl_Uninit3D,
7469 IWineD3DDeviceImpl_EnumDisplayModes,
7470 IWineD3DDeviceImpl_EvictManagedResources,
7471 IWineD3DDeviceImpl_GetAvailableTextureMem,
7472 IWineD3DDeviceImpl_GetBackBuffer,
7473 IWineD3DDeviceImpl_GetCreationParameters,
7474 IWineD3DDeviceImpl_GetDeviceCaps,
7475 IWineD3DDeviceImpl_GetDirect3D,
7476 IWineD3DDeviceImpl_GetDisplayMode,
7477 IWineD3DDeviceImpl_SetDisplayMode,
7478 IWineD3DDeviceImpl_GetHWND,
7479 IWineD3DDeviceImpl_SetHWND,
7480 IWineD3DDeviceImpl_GetNumberOfSwapChains,
7481 IWineD3DDeviceImpl_GetRasterStatus,
7482 IWineD3DDeviceImpl_GetSwapChain,
7483 IWineD3DDeviceImpl_Reset,
7484 IWineD3DDeviceImpl_SetDialogBoxMode,
7485 IWineD3DDeviceImpl_SetCursorProperties,
7486 IWineD3DDeviceImpl_SetCursorPosition,
7487 IWineD3DDeviceImpl_ShowCursor,
7488 IWineD3DDeviceImpl_TestCooperativeLevel,
7489 IWineD3DDeviceImpl_EnumZBufferFormats,
7490 IWineD3DDeviceImpl_EnumTextureFormats,
7491 /*** Getters and setters **/
7492 IWineD3DDeviceImpl_SetClipPlane,
7493 IWineD3DDeviceImpl_GetClipPlane,
7494 IWineD3DDeviceImpl_SetClipStatus,
7495 IWineD3DDeviceImpl_GetClipStatus,
7496 IWineD3DDeviceImpl_SetCurrentTexturePalette,
7497 IWineD3DDeviceImpl_GetCurrentTexturePalette,
7498 IWineD3DDeviceImpl_SetDepthStencilSurface,
7499 IWineD3DDeviceImpl_GetDepthStencilSurface,
7500 IWineD3DDeviceImpl_SetFVF,
7501 IWineD3DDeviceImpl_GetFVF,
7502 IWineD3DDeviceImpl_SetGammaRamp,
7503 IWineD3DDeviceImpl_GetGammaRamp,
7504 IWineD3DDeviceImpl_SetIndices,
7505 IWineD3DDeviceImpl_GetIndices,
7506 IWineD3DDeviceImpl_SetLight,
7507 IWineD3DDeviceImpl_GetLight,
7508 IWineD3DDeviceImpl_SetLightEnable,
7509 IWineD3DDeviceImpl_GetLightEnable,
7510 IWineD3DDeviceImpl_SetMaterial,
7511 IWineD3DDeviceImpl_GetMaterial,
7512 IWineD3DDeviceImpl_SetNPatchMode,
7513 IWineD3DDeviceImpl_GetNPatchMode,
7514 IWineD3DDeviceImpl_SetPaletteEntries,
7515 IWineD3DDeviceImpl_GetPaletteEntries,
7516 IWineD3DDeviceImpl_SetPixelShader,
7517 IWineD3DDeviceImpl_GetPixelShader,
7518 IWineD3DDeviceImpl_SetPixelShaderConstant,
7519 IWineD3DDeviceImpl_GetPixelShaderConstant,
7520 IWineD3DDeviceImpl_SetPixelShaderConstantB,
7521 IWineD3DDeviceImpl_GetPixelShaderConstantB,
7522 IWineD3DDeviceImpl_SetPixelShaderConstantI,
7523 IWineD3DDeviceImpl_GetPixelShaderConstantI,
7524 IWineD3DDeviceImpl_SetPixelShaderConstantF,
7525 IWineD3DDeviceImpl_GetPixelShaderConstantF,
7526 IWineD3DDeviceImpl_SetPixelShaderConstantN,
7527 IWineD3DDeviceImpl_SetRenderState,
7528 IWineD3DDeviceImpl_GetRenderState,
7529 IWineD3DDeviceImpl_SetRenderTarget,
7530 IWineD3DDeviceImpl_GetRenderTarget,
7531 IWineD3DDeviceImpl_SetFrontBackBuffers,
7532 IWineD3DDeviceImpl_SetSamplerState,
7533 IWineD3DDeviceImpl_GetSamplerState,
7534 IWineD3DDeviceImpl_SetScissorRect,
7535 IWineD3DDeviceImpl_GetScissorRect,
7536 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
7537 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
7538 IWineD3DDeviceImpl_SetStreamSource,
7539 IWineD3DDeviceImpl_GetStreamSource,
7540 IWineD3DDeviceImpl_SetStreamSourceFreq,
7541 IWineD3DDeviceImpl_GetStreamSourceFreq,
7542 IWineD3DDeviceImpl_SetTexture,
7543 IWineD3DDeviceImpl_GetTexture,
7544 IWineD3DDeviceImpl_SetTextureStageState,
7545 IWineD3DDeviceImpl_GetTextureStageState,
7546 IWineD3DDeviceImpl_SetTransform,
7547 IWineD3DDeviceImpl_GetTransform,
7548 IWineD3DDeviceImpl_SetVertexDeclaration,
7549 IWineD3DDeviceImpl_GetVertexDeclaration,
7550 IWineD3DDeviceImpl_SetVertexShader,
7551 IWineD3DDeviceImpl_GetVertexShader,
7552 IWineD3DDeviceImpl_SetVertexShaderConstant,
7553 IWineD3DDeviceImpl_GetVertexShaderConstant,
7554 IWineD3DDeviceImpl_SetVertexShaderConstantB,
7555 IWineD3DDeviceImpl_GetVertexShaderConstantB,
7556 IWineD3DDeviceImpl_SetVertexShaderConstantI,
7557 IWineD3DDeviceImpl_GetVertexShaderConstantI,
7558 IWineD3DDeviceImpl_SetVertexShaderConstantF,
7559 IWineD3DDeviceImpl_GetVertexShaderConstantF,
7560 IWineD3DDeviceImpl_SetVertexShaderConstantN,
7561 IWineD3DDeviceImpl_SetViewport,
7562 IWineD3DDeviceImpl_GetViewport,
7563 IWineD3DDeviceImpl_MultiplyTransform,
7564 IWineD3DDeviceImpl_ValidateDevice,
7565 IWineD3DDeviceImpl_ProcessVertices,
7566 /*** State block ***/
7567 IWineD3DDeviceImpl_BeginStateBlock,
7568 IWineD3DDeviceImpl_EndStateBlock,
7569 /*** Scene management ***/
7570 IWineD3DDeviceImpl_BeginScene,
7571 IWineD3DDeviceImpl_EndScene,
7572 IWineD3DDeviceImpl_Present,
7573 IWineD3DDeviceImpl_Clear,
7575 IWineD3DDeviceImpl_DrawPrimitive,
7576 IWineD3DDeviceImpl_DrawIndexedPrimitive,
7577 IWineD3DDeviceImpl_DrawPrimitiveUP,
7578 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
7579 IWineD3DDeviceImpl_DrawPrimitiveStrided,
7580 IWineD3DDeviceImpl_DrawRectPatch,
7581 IWineD3DDeviceImpl_DrawTriPatch,
7582 IWineD3DDeviceImpl_DeletePatch,
7583 IWineD3DDeviceImpl_ColorFill,
7584 IWineD3DDeviceImpl_UpdateTexture,
7585 IWineD3DDeviceImpl_UpdateSurface,
7586 IWineD3DDeviceImpl_CopyRects,
7587 IWineD3DDeviceImpl_StretchRect,
7588 IWineD3DDeviceImpl_GetRenderTargetData,
7589 IWineD3DDeviceImpl_GetFrontBufferData,
7590 /*** Internal use IWineD3DDevice methods ***/
7591 IWineD3DDeviceImpl_SetupTextureStates,
7592 /*** object tracking ***/
7593 IWineD3DDeviceImpl_SwapChainReleased,
7594 IWineD3DDeviceImpl_ResourceReleased
7598 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
7599 WINED3DRS_ALPHABLENDENABLE ,
7600 WINED3DRS_ALPHAFUNC ,
7601 WINED3DRS_ALPHAREF ,
7602 WINED3DRS_ALPHATESTENABLE ,
7604 WINED3DRS_COLORWRITEENABLE ,
7605 WINED3DRS_DESTBLEND ,
7606 WINED3DRS_DITHERENABLE ,
7607 WINED3DRS_FILLMODE ,
7608 WINED3DRS_FOGDENSITY ,
7610 WINED3DRS_FOGSTART ,
7611 WINED3DRS_LASTPIXEL ,
7612 WINED3DRS_SHADEMODE ,
7613 WINED3DRS_SRCBLEND ,
7614 WINED3DRS_STENCILENABLE ,
7615 WINED3DRS_STENCILFAIL ,
7616 WINED3DRS_STENCILFUNC ,
7617 WINED3DRS_STENCILMASK ,
7618 WINED3DRS_STENCILPASS ,
7619 WINED3DRS_STENCILREF ,
7620 WINED3DRS_STENCILWRITEMASK ,
7621 WINED3DRS_STENCILZFAIL ,
7622 WINED3DRS_TEXTUREFACTOR ,
7633 WINED3DRS_ZWRITEENABLE
7636 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
7637 WINED3DTSS_ADDRESSW ,
7638 WINED3DTSS_ALPHAARG0 ,
7639 WINED3DTSS_ALPHAARG1 ,
7640 WINED3DTSS_ALPHAARG2 ,
7641 WINED3DTSS_ALPHAOP ,
7642 WINED3DTSS_BUMPENVLOFFSET ,
7643 WINED3DTSS_BUMPENVLSCALE ,
7644 WINED3DTSS_BUMPENVMAT00 ,
7645 WINED3DTSS_BUMPENVMAT01 ,
7646 WINED3DTSS_BUMPENVMAT10 ,
7647 WINED3DTSS_BUMPENVMAT11 ,
7648 WINED3DTSS_COLORARG0 ,
7649 WINED3DTSS_COLORARG1 ,
7650 WINED3DTSS_COLORARG2 ,
7651 WINED3DTSS_COLOROP ,
7652 WINED3DTSS_RESULTARG ,
7653 WINED3DTSS_TEXCOORDINDEX ,
7654 WINED3DTSS_TEXTURETRANSFORMFLAGS
7657 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
7658 WINED3DSAMP_ADDRESSU ,
7659 WINED3DSAMP_ADDRESSV ,
7660 WINED3DSAMP_ADDRESSW ,
7661 WINED3DSAMP_BORDERCOLOR ,
7662 WINED3DSAMP_MAGFILTER ,
7663 WINED3DSAMP_MINFILTER ,
7664 WINED3DSAMP_MIPFILTER ,
7665 WINED3DSAMP_MIPMAPLODBIAS ,
7666 WINED3DSAMP_MAXMIPLEVEL ,
7667 WINED3DSAMP_MAXANISOTROPY ,
7668 WINED3DSAMP_SRGBTEXTURE ,
7669 WINED3DSAMP_ELEMENTINDEX
7672 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
7674 WINED3DRS_AMBIENTMATERIALSOURCE ,
7675 WINED3DRS_CLIPPING ,
7676 WINED3DRS_CLIPPLANEENABLE ,
7677 WINED3DRS_COLORVERTEX ,
7678 WINED3DRS_DIFFUSEMATERIALSOURCE ,
7679 WINED3DRS_EMISSIVEMATERIALSOURCE ,
7680 WINED3DRS_FOGDENSITY ,
7682 WINED3DRS_FOGSTART ,
7683 WINED3DRS_FOGTABLEMODE ,
7684 WINED3DRS_FOGVERTEXMODE ,
7685 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
7686 WINED3DRS_LIGHTING ,
7687 WINED3DRS_LOCALVIEWER ,
7688 WINED3DRS_MULTISAMPLEANTIALIAS ,
7689 WINED3DRS_MULTISAMPLEMASK ,
7690 WINED3DRS_NORMALIZENORMALS ,
7691 WINED3DRS_PATCHEDGESTYLE ,
7692 WINED3DRS_POINTSCALE_A ,
7693 WINED3DRS_POINTSCALE_B ,
7694 WINED3DRS_POINTSCALE_C ,
7695 WINED3DRS_POINTSCALEENABLE ,
7696 WINED3DRS_POINTSIZE ,
7697 WINED3DRS_POINTSIZE_MAX ,
7698 WINED3DRS_POINTSIZE_MIN ,
7699 WINED3DRS_POINTSPRITEENABLE ,
7700 WINED3DRS_RANGEFOGENABLE ,
7701 WINED3DRS_SPECULARMATERIALSOURCE ,
7702 WINED3DRS_TWEENFACTOR ,
7703 WINED3DRS_VERTEXBLEND
7706 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
7707 WINED3DTSS_TEXCOORDINDEX ,
7708 WINED3DTSS_TEXTURETRANSFORMFLAGS
7711 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
7712 WINED3DSAMP_DMAPOFFSET