2 * IWineD3DDevice implementation
4 * Copyright 2002-2005 Jason Edmeades
5 * Copyright 2003-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "wined3d_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
28 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
29 WINE_DECLARE_DEBUG_CHANNEL(d3d_fps);
30 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
31 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
33 /* x11drv GDI escapes */
34 #define X11DRV_ESCAPE 6789
35 enum x11drv_escape_codes
37 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
38 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
39 X11DRV_GET_FONT, /* get current X font for a DC */
42 /* retrieve the X display to use on a given DC */
43 inline static Display *get_display( HDC hdc )
46 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
48 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
49 sizeof(display), (LPSTR)&display )) display = NULL;
53 /* Memory tracking and object counting */
54 static unsigned int emulated_textureram = 64*1024*1024;
56 /* TODO: setup some flags in the regestry to enable, disable pbuffer support */
57 /* enable pbuffer support for offscreen textures */
58 BOOL pbuffer_support = FALSE;
59 /* allocate one pbuffer per surface */
60 BOOL pbuffer_per_surface = FALSE;
62 /* static function declarations */
63 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
65 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type);
68 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return D3DERR_OUTOFVIDEOMEMORY;}
70 #define D3DCREATEOBJECTINSTANCE(object, type) { \
71 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
72 D3DMEMCHECK(object, pp##type); \
73 object->lpVtbl = &IWineD3D##type##_Vtbl; \
74 object->wineD3DDevice = This; \
75 object->parent = parent; \
77 *pp##type = (IWineD3D##type *) object; \
80 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
81 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
82 D3DMEMCHECK(object, pp##type); \
83 object->lpVtbl = &IWineD3D##type##_Vtbl; \
84 object->resource.wineD3DDevice = This; \
85 object->resource.parent = parent; \
86 object->resource.resourceType = d3dtype; \
87 object->resource.ref = 1; \
88 object->resource.pool = Pool; \
89 object->resource.format = Format; \
90 object->resource.usage = Usage; \
91 object->resource.size = _size; \
92 /* Check that we have enough video ram left */ \
93 if (Pool == D3DPOOL_DEFAULT) { \
94 if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
95 WARN("Out of 'bogus' video memory\n"); \
96 HeapFree(GetProcessHeap(), 0, object); \
98 return D3DERR_OUTOFVIDEOMEMORY; \
100 globalChangeGlRam(_size); \
102 object->resource.allocatedMemory = (0 == _size ? NULL : Pool == D3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
103 if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != D3DPOOL_DEFAULT) { \
104 FIXME("Out of memory!\n"); \
105 HeapFree(GetProcessHeap(), 0, object); \
107 return D3DERR_OUTOFVIDEOMEMORY; \
109 *pp##type = (IWineD3D##type *) object; \
110 IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
111 TRACE("(%p) : Created resource %p\n", This, object); \
114 #define D3DINITILIZEBASETEXTURE(_basetexture) { \
115 _basetexture.levels = Levels; \
116 _basetexture.filterType = (Usage & D3DUSAGE_AUTOGENMIPMAP) ? D3DTEXF_LINEAR : D3DTEXF_NONE; \
117 _basetexture.LOD = 0; \
118 _basetexture.dirty = TRUE; \
121 /**********************************************************
122 * Global variable / Constants follow
123 **********************************************************/
124 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
126 /**********************************************************
127 * Utility functions follow
128 **********************************************************/
129 /* Convert the D3DLIGHT properties into equivalent gl lights */
130 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
133 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
134 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
136 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
137 glMatrixMode(GL_MODELVIEW);
139 glLoadMatrixf((float *)&This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
142 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
143 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
144 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
145 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
146 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
147 checkGLcall("glLightfv");
150 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
151 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
152 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
153 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
154 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
155 checkGLcall("glLightfv");
158 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
159 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
160 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
161 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
162 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
163 checkGLcall("glLightfv");
165 /* Attenuation - Are these right? guessing... */
166 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
167 checkGLcall("glLightf");
168 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
169 checkGLcall("glLightf");
171 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) != 0) {
172 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
174 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
177 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
178 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
179 checkGLcall("glLightf");
181 switch (lightInfo->OriginalParms.Type) {
184 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
185 checkGLcall("glLightfv");
186 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
187 checkGLcall("glLightf");
193 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
194 checkGLcall("glLightfv");
196 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
197 checkGLcall("glLightfv");
198 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
199 checkGLcall("glLightf");
200 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
201 checkGLcall("glLightf");
205 case D3DLIGHT_DIRECTIONAL:
207 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
208 checkGLcall("glLightfv");
209 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
210 checkGLcall("glLightf");
211 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
212 checkGLcall("glLightf");
216 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
219 /* Restore the modelview matrix */
223 /* Apply the current values to the specified texture stage */
224 void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Sampler, DWORD Flags) {
225 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
233 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
234 clamping, MIPLOD, etc. This will work for up to 16 samplers.
237 if (Sampler >= GL_LIMITS(samplers)) {
238 FIXME("Trying to set the state of more samplers %ld than are supported %d by this openGL implementation\n", Sampler, GL_LIMITS(samplers));
241 VTRACE(("Activating appropriate texture state %ld\n", Sampler));
242 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
244 GLACTIVETEXTURE(Sampler);
246 /* Could we use bindTexture and then apply the states instead of GLACTIVETEXTURE */
247 } else if (Sampler > 0) {
248 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
252 /* TODO: change this to a lookup table
253 LOOKUP_TEXTURE_STATES lists all texture states that should be applied.
254 LOOKUP_CONTEXT_SATES list all context applicable states that can be applied
255 etc.... it's a lot cleaner, quicker and possibly easier to maintain than running a switch and setting a skip flag...
256 especially when there are a number of groups of states. */
258 TRACE("-----------------------> Updating the texture at Sampler %ld to have new texture state information\n", Sampler);
260 /* 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 */
261 #define APPLY_STATE(_state) IWineD3DDeviceImpl_ApplyTextureUnitState(iface, Sampler, _state)
262 /* these are the only two supported states that need to be applied */
263 APPLY_STATE(WINED3DTSS_TEXCOORDINDEX);
264 APPLY_STATE(WINED3DTSS_TEXTURETRANSFORMFLAGS);
265 #if 0 /* not supported at the moment */
266 APPLY_STATE(WINED3DTSS_BUMPENVMAT00);
267 APPLY_STATE(WINED3DTSS_BUMPENVMAT01);
268 APPLY_STATE(WINED3DTSS_BUMPENVMAT10);
269 APPLY_STATE(WINED3DTSS_BUMPENVMAT11);
270 APPLY_STATE(WINED3DTSS_BUMPENVLSCALE);
271 APPLY_STATE(WINED3DTSS_BUMPENVLOFFSET);
272 APPLY_STATE(WINED3DTSS_RESULTARG);
273 APPLY_STATE(WINED3DTSS_CONSTANT);
275 /* a quick sanity check in case someone forgot to update this function */
276 if (WINED3D_HIGHEST_TEXTURE_STATE > WINED3DTSS_CONSTANT) {
277 FIXME("(%p) : There are more texture states than expected, update device.c to match\n", This);
281 /* apply any sampler states that always need applying */
282 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
283 tmpvalue.d = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPMAPLODBIAS];
284 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
285 GL_TEXTURE_LOD_BIAS_EXT,
287 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
290 /* Note the D3DRS value applies to all textures, but GL has one
291 * per texture, so apply it now ready to be used!
293 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
294 /* Set the default alpha blend color */
295 glBlendColor(col[0], col[1], col[2], col[3]);
296 checkGLcall("glBlendColor");
298 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
299 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
300 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
302 /* TODO: NV_POINT_SPRITE */
303 if (GL_SUPPORT(ARB_POINT_SPRITE)) {
304 if (This->stateBlock->renderState[WINED3DRS_POINTSPRITEENABLE] != FALSE) {
305 /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
306 glDisable(GL_POINT_SMOOTH);
308 /* Centre the texture on the vertex */
309 VTRACE("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
310 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
312 VTRACE("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
313 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
314 checkGLcall("glTexEnvf(...)");
315 VTRACE("glEnable( GL_POINT_SPRITE_ARB )\n");
316 glEnable( GL_POINT_SPRITE_ARB );
317 checkGLcall("glEnable(...)");
319 VTRACE("glDisable( GL_POINT_SPRITE_ARB )\n");
320 glDisable( GL_POINT_SPRITE_ARB );
321 checkGLcall("glEnable(...)");
325 TRACE("-----------------------> Updated the texture at Sampler %ld to have new texture state information\n", Sampler);
328 /**********************************************************
329 * IUnknown parts follows
330 **********************************************************/
332 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
334 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
335 /* FIXME: This needs to extend an IWineD3DBaseObject */
337 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
338 if (IsEqualGUID(riid, &IID_IUnknown)
339 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
340 IUnknown_AddRef(iface);
345 return E_NOINTERFACE;
348 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
349 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
350 ULONG refCount = InterlockedIncrement(&This->ref);
352 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
356 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
357 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
358 ULONG refCount = InterlockedDecrement(&This->ref);
360 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
363 /* TODO: Clean up all the surfaces and textures! */
364 /* FIXME: Create targets and state blocks in d3d8 */
365 if (((IWineD3DImpl *)This->wineD3D)->dxVersion > 8) { /*We don't create a state block in d3d8 yet*/
366 /* NOTE: You must release the parent if the object was created via a callback
367 ** ***************************/
368 IUnknown* swapChainParent;
370 /* NOTE: Don't release swapchain 0 here, it's 'special' */
371 SwapChainList *nextSwapchain = This->swapchains;
372 if (nextSwapchain != NULL) {
373 nextSwapchain = nextSwapchain->next;
375 WARN("Expected to find the implicit swapchain\n");
378 /* release all the other swapchains */
379 while (nextSwapchain != NULL) {
380 SwapChainList *prevSwapchain = nextSwapchain;
381 nextSwapchain = nextSwapchain->next;
382 IWineD3DSwapChain_Release(prevSwapchain->swapchain);
383 /* NOTE: no need to free the list element, it will be done by the release callback
384 HeapFree(GetProcessHeap(), 0, prevSwapchain); */
387 if (This->stateBlock != NULL) {
388 IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->stateBlock);
391 if (This->swapchains != NULL) {
392 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
393 IWineD3DSwapChain_GetParent(This->swapchains->swapchain, &swapChainParent);
394 IUnknown_Release(swapChainParent); /* once for the get parent */
395 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
396 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
401 IWineD3D_Release(This->wineD3D);
402 HeapFree(GetProcessHeap(), 0, This);
407 /**********************************************************
408 * IWineD3DDevice implementation follows
409 **********************************************************/
410 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
411 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
412 *pParent = This->parent;
413 IUnknown_AddRef(This->parent);
417 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
418 DWORD FVF, D3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
420 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
421 IWineD3DVertexBufferImpl *object;
422 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
423 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, D3DRTYPE_VERTEXBUFFER, Size)
426 if (Pool == D3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
427 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
431 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
432 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
437 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
438 WINED3DFORMAT Format, D3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
439 HANDLE *sharedHandle, IUnknown *parent) {
440 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
441 IWineD3DIndexBufferImpl *object;
442 TRACE("(%p) Creating index buffer\n", This);
444 /* Allocate the storage for the device */
445 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,D3DRTYPE_INDEXBUFFER, Length)
448 if (Pool == D3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
449 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
452 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
453 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
454 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
459 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
461 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
462 IWineD3DStateBlockImpl *object;
465 D3DCREATEOBJECTINSTANCE(object, StateBlock)
466 object->blockType = Type;
468 /* Special case - Used during initialization to produce a placeholder stateblock
469 so other functions called can update a state block */
470 if (Type == WINED3DSBT_INIT) {
471 /* Don't bother increasing the reference count otherwise a device will never
472 be freed due to circular dependencies */
476 /* Otherwise, might as well set the whole state block to the appropriate values */
477 if ( This->stateBlock != NULL) {
478 memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
480 memset(object->streamFreq, 1, sizeof(object->streamFreq));
483 /* Reset the ref and type after kludging it */
484 object->wineD3DDevice = This;
486 object->blockType = Type;
488 TRACE("Updating changed flags appropriate for type %d\n", Type);
490 if (Type == WINED3DSBT_ALL) {
492 TRACE("ALL => Pretend everything has changed\n");
493 memset(&object->changed, TRUE, sizeof(This->stateBlock->changed));
494 } else if (Type == WINED3DSBT_PIXELSTATE) {
496 TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
497 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
498 /* TODO: Pixel Shader Constants */
499 object->changed.pixelShader = TRUE;
500 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
501 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
504 } else if (Type == WINED3DSBT_VERTEXSTATE) {
506 TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
507 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
508 /* TODO: Vertex Shader Constants */
509 object->changed.vertexShader = TRUE;
510 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
511 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
514 /* Duplicate light chain */
516 PLIGHTINFOEL *src = NULL;
517 PLIGHTINFOEL *dst = NULL;
518 PLIGHTINFOEL *newEl = NULL;
519 src = This->stateBlock->lights;
520 object->lights = NULL;
524 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
525 if (newEl == NULL) return D3DERR_OUTOFVIDEOMEMORY;
526 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
528 newEl->changed = TRUE;
529 newEl->enabledChanged = TRUE;
531 object->lights = newEl;
542 FIXME("Unrecognized state block type %d\n", Type);
545 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
550 /* ************************************
552 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
555 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
557 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.
559 ******************************** */
561 HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height, WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **ppSurface,D3DRESOURCETYPE Type, DWORD Usage, D3DPOOL Pool, D3DMULTISAMPLE_TYPE MultiSample ,DWORD MultisampleQuality, HANDLE* pSharedHandle, IUnknown *parent) {
562 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
563 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
564 unsigned int pow2Width, pow2Height;
565 unsigned int Size = 1;
566 TRACE("(%p) Create surface\n",This);
568 /** FIXME: Check ranges on the inputs are valid
571 * [in] Quality level. The valid range is between zero and one less than the level
572 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
573 * Passing a larger value returns the error D3DERR_INVALIDCALL. The MultisampleQuality
574 * values of paired render targets, depth stencil surfaces, and the MultiSample type
576 *******************************/
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
584 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
585 * with a different depth surface.
587 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
588 ***************************/
590 if(MultisampleQuality < 0) {
591 FIXME("Invalid multisample level %ld \n", MultisampleQuality);
592 return D3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
595 if(MultisampleQuality > 0) {
596 FIXME("MultisampleQuality set to %ld, substituting 0 \n" , MultisampleQuality);
597 MultisampleQuality=0;
600 /** FIXME: Check that the format is supported
602 *******************************/
603 /* TODO: add support for dxt2 and dxt4 formats */
604 if (Format == D3DFMT_DXT2 || Format == D3DFMT_DXT4) return D3DERR_NOTAVAILABLE;
606 /* Non-power2 support */
608 /* Find the nearest pow2 match */
609 pow2Width = pow2Height = 1;
610 while (pow2Width < Width) pow2Width <<= 1;
611 while (pow2Height < Height) pow2Height <<= 1;
613 if (pow2Width > Width || pow2Height > Height) {
614 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
615 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
616 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
617 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d) \n",
618 This, Width, Height);
619 return D3DERR_NOTAVAILABLE;
623 /** Check against the maximum texture sizes supported by the video card **/
624 if (pow2Width > GL_LIMITS(texture_size) || pow2Height > GL_LIMITS(texture_size)) {
625 /* one of three options
626 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)
627 2: Set the texture to the maxium size (bad idea)
628 3: WARN and return D3DERR_NOTAVAILABLE;
630 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));
631 return D3DERR_NOTAVAILABLE;
636 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
637 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
639 *********************************/
640 if (Format == WINED3DFMT_DXT1) {
641 /* DXT1 is half byte per pixel */
642 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4)) >> 1;
644 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
645 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
646 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4));
648 Size = (pow2Width * D3DFmtGetBpp(This, Format)) * pow2Height;
651 /** Create the and initilise surface resource **/
652 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,D3DRTYPE_SURFACE, Size)
653 object->container = (IUnknown*) This;
655 object->currentDesc.Width = Width;
656 object->currentDesc.Height = Height;
657 object->currentDesc.MultiSampleType = MultiSample;
658 object->currentDesc.MultiSampleQuality = MultisampleQuality;
660 /* Setup some glformat defaults */
661 object->glDescription.glFormat = D3DFmt2GLFmt(This, object->resource.format);
662 object->glDescription.glFormatInternal = D3DFmt2GLIntFmt(This, object->resource.format);
663 object->glDescription.glType = D3DFmt2GLType(This, object->resource.format);
664 object->glDescription.textureName = 0;
665 object->glDescription.level = Level;
666 object->glDescription.target = GL_TEXTURE_2D;
669 object->pow2Width = pow2Width;
670 object->pow2Height = pow2Height;
671 object->nonpow2 = (pow2Width != Width || pow2Height != Height) ? TRUE : FALSE;
672 object->discard = Discard;
673 object->activeLock = FALSE;
674 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
675 object->pow2Size = (pow2Width * object->bytesPerPixel) * pow2Height;
677 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
679 TRACE("Pool %d %d %d %d",Pool, D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM);
681 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
682 * this function is too deap to need to care about things like this.
683 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
684 * ****************************************/
686 case D3DPOOL_SCRATCH:
687 if(Lockable == FALSE)
688 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
689 which are mutually exclusive, setting lockable to true\n");
692 case D3DPOOL_SYSTEMMEM:
693 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
694 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
695 case D3DPOOL_MANAGED:
696 if(Usage == D3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
697 Usage of DYNAMIC which are mutually exclusive, not doing \
698 anything just telling you.\n");
700 case D3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
701 if(!(Usage & D3DUSAGE_DYNAMIC) && !(Usage & D3DUSAGE_RENDERTARGET)
702 && !(Usage && D3DUSAGE_DEPTHSTENCIL ) && Lockable == TRUE)
703 FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
706 FIXME("(%p) Unknown pool %d\n", This, Pool);
710 if (Usage & D3DUSAGE_RENDERTARGET && Pool != D3DPOOL_DEFAULT) {
711 FIXME("Trying to create a render target that isn't in the default pool\n");
715 object->locked = FALSE;
716 object->lockable = (WINED3DFMT_D16_LOCKABLE == Format) ? TRUE : Lockable;
718 /* mark the texture as dirty so that it get's loaded first time around*/
719 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
720 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
721 This, Width, Height, Format, debug_d3dformat(Format),
722 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
727 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
728 DWORD Usage, WINED3DFORMAT Format, D3DPOOL Pool,
729 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
730 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
732 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
733 IWineD3DTextureImpl *object;
738 unsigned int pow2Width = Width;
739 unsigned int pow2Height = Height;
742 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) .... \n", This, Width, Height, Levels, Usage);
744 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, D3DRTYPE_TEXTURE, 0);
745 D3DINITILIZEBASETEXTURE(object->baseTexture);
746 object->width = Width;
747 object->height = Height;
749 /** Non-power2 support **/
750 /* Find the nearest pow2 match */
751 pow2Width = pow2Height = 1;
752 while (pow2Width < Width) pow2Width <<= 1;
753 while (pow2Height < Height) pow2Height <<= 1;
755 /** FIXME: add support for real non-power-two if it's provided by the video card **/
756 /* Precalculated scaling for 'faked' non power of two texture coords */
757 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
758 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
759 TRACE(" xf(%f) yf(%f) \n", object->pow2scalingFactorX, object->pow2scalingFactorY);
761 /* Calculate levels for mip mapping */
763 TRACE("calculating levels %d\n", object->baseTexture.levels);
764 object->baseTexture.levels++;
767 while (tmpW > 1 && tmpH > 1) {
768 tmpW = max(1, tmpW >> 1);
769 tmpH = max(1, tmpH >> 1);
770 object->baseTexture.levels++;
772 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
775 /* Generate all the surfaces */
778 for (i = 0; i < object->baseTexture.levels; i++)
780 /* use the callback to create the texture surface */
781 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
784 FIXME("Failed to create surface %p \n",object);
786 for (j = 0 ; j < i ; j++) {
787 IWineD3DSurface_Release(object->surfaces[j]);
789 /* heap free object */
790 HeapFree(GetProcessHeap(), 0, object);
796 IWineD3DSurface_SetContainer(object->surfaces[i], (IUnknown *)object);
797 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
798 /* calculate the next mipmap level */
799 tmpW = max(1, tmpW >> 1);
800 tmpH = max(1, tmpH >> 1);
803 TRACE("(%p) : Created texture %p\n", This, object);
807 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
808 UINT Width, UINT Height, UINT Depth,
809 UINT Levels, DWORD Usage,
810 WINED3DFORMAT Format, D3DPOOL Pool,
811 IWineD3DVolumeTexture **ppVolumeTexture,
812 HANDLE *pSharedHandle, IUnknown *parent,
813 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
815 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
816 IWineD3DVolumeTextureImpl *object;
822 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, D3DRTYPE_VOLUMETEXTURE, 0);
823 D3DINITILIZEBASETEXTURE(object->baseTexture);
825 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
826 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
828 object->width = Width;
829 object->height = Height;
830 object->depth = Depth;
832 /* Calculate levels for mip mapping */
834 object->baseTexture.levels++;
838 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
839 tmpW = max(1, tmpW >> 1);
840 tmpH = max(1, tmpH >> 1);
841 tmpD = max(1, tmpD >> 1);
842 object->baseTexture.levels++;
844 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
847 /* Generate all the surfaces */
852 for (i = 0; i < object->baseTexture.levels; i++)
854 /* Create the volume */
855 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
856 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
858 /* Set it's container to this object */
859 IWineD3DVolume_SetContainer(object->volumes[i], (IUnknown *)object);
861 /* calcualte the next mipmap level */
862 tmpW = max(1, tmpW >> 1);
863 tmpH = max(1, tmpH >> 1);
864 tmpD = max(1, tmpD >> 1);
867 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
868 TRACE("(%p) : Created volume texture %p\n", This, object);
872 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
873 UINT Width, UINT Height, UINT Depth,
875 WINED3DFORMAT Format, D3DPOOL Pool,
876 IWineD3DVolume** ppVolume,
877 HANDLE* pSharedHandle, IUnknown *parent) {
879 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
880 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
882 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, D3DRTYPE_VOLUME, ((Width * D3DFmtGetBpp(This, Format)) * Height * Depth))
884 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
885 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
887 object->currentDesc.Width = Width;
888 object->currentDesc.Height = Height;
889 object->currentDesc.Depth = Depth;
890 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
892 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
893 object->lockable = TRUE;
894 object->locked = FALSE;
895 memset(&object->lockedBox, 0, sizeof(D3DBOX));
896 object->dirty = TRUE;
898 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
901 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
902 UINT Levels, DWORD Usage,
903 WINED3DFORMAT Format, D3DPOOL Pool,
904 IWineD3DCubeTexture **ppCubeTexture,
905 HANDLE *pSharedHandle, IUnknown *parent,
906 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
908 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
909 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
913 unsigned int pow2EdgeLength = EdgeLength;
915 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, D3DRTYPE_CUBETEXTURE, 0);
916 D3DINITILIZEBASETEXTURE(object->baseTexture);
918 TRACE("(%p) Create Cube Texture \n", This);
920 /** Non-power2 support **/
922 /* Find the nearest pow2 match */
924 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
926 object->edgeLength = EdgeLength;
927 /* TODO: support for native non-power 2 */
928 /* Precalculated scaling for 'faked' non power of two texture coords */
929 object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
931 /* Calculate levels for mip mapping */
933 object->baseTexture.levels++;
936 tmpW = max(1, tmpW >> 1);
937 object->baseTexture.levels++;
939 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
942 /* Generate all the surfaces */
944 for (i = 0; i < object->baseTexture.levels; i++) {
946 /* Create the 6 faces */
947 for (j = 0; j < 6; j++) {
949 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
950 i /* Level */, &object->surfaces[j][i],pSharedHandle);
956 for (l = 0; l < j; l++) {
957 IWineD3DSurface_Release(object->surfaces[j][i]);
959 for (k = 0; k < i; k++) {
960 for (l = 0; l < 6; l++) {
961 IWineD3DSurface_Release(object->surfaces[l][j]);
965 FIXME("(%p) Failed to create surface\n",object);
966 HeapFree(GetProcessHeap(),0,object);
967 *ppCubeTexture = NULL;
970 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IUnknown *)object);
971 TRACE("Created surface level %d @ %p, \n", i, object->surfaces[j][i]);
973 tmpW = max(1, tmpW >> 1);
976 TRACE("(%p) : Created Cube Texture %p\n", This, object);
977 *ppCubeTexture = (IWineD3DCubeTexture *) object;
981 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
982 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
983 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
985 if (NULL == ppQuery) {
986 /* Just a check to see if we support this type of query */
987 HRESULT hr = D3DERR_NOTAVAILABLE;
988 /* Lie and say everything is good (we can return ok fake data from a stub) */
990 case WINED3DQUERYTYPE_VCACHE:
991 case WINED3DQUERYTYPE_RESOURCEMANAGER:
992 case WINED3DQUERYTYPE_VERTEXSTATS:
993 case WINED3DQUERYTYPE_EVENT:
994 case WINED3DQUERYTYPE_OCCLUSION:
995 case WINED3DQUERYTYPE_TIMESTAMP:
996 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
997 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
998 case WINED3DQUERYTYPE_PIPELINETIMINGS:
999 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1000 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1001 case WINED3DQUERYTYPE_PIXELTIMINGS:
1002 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1003 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1007 FIXME("(%p) Unhandled query type %d\n",This , Type);
1009 FIXME("(%p) : Stub request for query type %d returned %ld\n", This, Type, hr);
1013 D3DCREATEOBJECTINSTANCE(object, Query)
1014 object->type = Type;
1015 object->extendedData = 0;
1016 TRACE("(%p) : Created Query %p\n", This, object);
1020 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1021 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1023 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1024 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1025 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1028 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1030 XVisualInfo template;
1031 GLXContext oldContext;
1032 Drawable oldDrawable;
1033 HRESULT hr = D3D_OK;
1035 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1037 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1038 * does a device hold a reference to a swap chain giving them a lifetime of the device
1039 * or does the swap chain notify the device of it'd destruction.
1040 *******************************/
1042 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1044 /* Initialize other useful values */
1045 object->presentParms.BackBufferCount = 1; /* TODO:? support for gl_aux buffers */
1047 /*********************
1048 * Lookup the window Handle and the relating X window handle
1049 ********************/
1051 /* Setup hwnd we are using, plus which display this equates to */
1052 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1053 if (!object->win_handle) {
1054 object->win_handle = This->createParms.hFocusWindow;
1057 object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window" );
1058 hDc = GetDC(object->win_handle);
1059 object->display = get_display(hDc);
1060 ReleaseDC(object->win_handle, hDc);
1061 TRACE("Using a display of %p %p \n", object->display, hDc);
1063 if (NULL == object->display || NULL == hDc) {
1064 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1065 return D3DERR_NOTAVAILABLE;
1068 if (object->win == 0) {
1069 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1070 return D3DERR_NOTAVAILABLE;
1073 * Create an opengl context for the display visual
1074 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1075 * use different properties after that point in time. FIXME: How to handle when requested format
1076 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1077 * it chooses is identical to the one already being used!
1078 **********************************/
1080 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1083 /* Create a new context for this swapchain */
1084 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1085 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1086 (or the best possible if none is requested) */
1087 TRACE("Found x visual ID : %ld\n", template.visualid);
1089 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1090 if (NULL == object->visInfo) {
1091 ERR("cannot really get XVisual\n");
1093 return D3DERR_NOTAVAILABLE;
1096 /* Write out some debug info about the visual/s */
1097 TRACE("Using x visual ID : %ld\n", template.visualid);
1098 TRACE(" visual info: %p\n", object->visInfo);
1099 TRACE(" num items : %d\n", num);
1100 for (n = 0;n < num; n++) {
1101 TRACE("=====item=====: %d\n", n + 1);
1102 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1103 TRACE(" screen : %d\n", object->visInfo[n].screen);
1104 TRACE(" depth : %u\n", object->visInfo[n].depth);
1105 TRACE(" class : %d\n", object->visInfo[n].class);
1106 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1107 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1108 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1109 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1110 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1111 /* log some extra glx info */
1112 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1113 TRACE(" gl_aux_buffers : %d\n", value);
1114 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1115 TRACE(" gl_buffer_size : %d\n", value);
1116 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1117 TRACE(" gl_red_size : %d\n", value);
1118 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1119 TRACE(" gl_green_size : %d\n", value);
1120 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1121 TRACE(" gl_blue_size : %d\n", value);
1122 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1123 TRACE(" gl_alpha_size : %d\n", value);
1124 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1125 TRACE(" gl_depth_size : %d\n", value);
1126 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1127 TRACE(" gl_stencil_size : %d\n", value);
1129 /* Now choose a simila visual ID*/
1131 #ifdef USE_CONTEXT_MANAGER
1133 /** TODO: use a context mamager **/
1137 IWineD3DSwapChain *implSwapChain;
1138 if (D3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1139 /* The first time around we create the context that is shared with all other swapchains and render targets */
1140 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1141 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1144 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1145 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1146 /* and create a new context with the implicit swapchains context as the shared context */
1147 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1148 IWineD3DSwapChain_Release(implSwapChain);
1153 XFree(object->visInfo);
1154 object->visInfo = NULL;
1156 if (NULL == object->glCtx) {
1157 ERR("cannot create glxContext\n");
1159 return D3DERR_NOTAVAILABLE;
1163 if (object->glCtx == NULL) {
1164 ERR("Error in context creation !\n");
1165 return D3DERR_INVALIDCALL;
1167 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1168 object->win_handle, object->glCtx, object->win, object->visInfo);
1171 /*********************
1172 * Windowed / Fullscreen
1173 *******************/
1176 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1177 * so we should really check to see if their is a fullscreen swapchain already
1178 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1179 **************************************/
1181 if (!*(pPresentationParameters->Windowed)) {
1187 /* Get info on the current display setup */
1188 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1189 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1192 /* Change the display settings */
1193 memset(&devmode, 0, sizeof(DEVMODEW));
1194 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1195 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1196 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1197 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1198 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1199 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1201 /* Make popup window */
1202 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1203 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1204 *(pPresentationParameters->BackBufferWidth),
1205 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1211 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1212 * then the corresponding dimension of the client area of the hDeviceWindow
1213 * (or the focus window, if hDeviceWindow is NULL) is taken.
1214 **********************/
1216 if (*(pPresentationParameters->Windowed) &&
1217 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1218 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1221 GetClientRect(object->win_handle, &Rect);
1223 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1224 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1225 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1227 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1228 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1229 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1233 /*********************
1234 * finish off parameter initialization
1235 *******************/
1237 /* Put the correct figures in the presentation parameters */
1238 TRACE("Coppying accross presentaion paraneters\n");
1239 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1240 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1241 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1242 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1243 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1244 object->presentParms.MultiSampleQuality = *(pPresentationParameters->MultiSampleQuality);
1245 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1246 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1247 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1248 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1249 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1250 object->presentParms.Flags = *(pPresentationParameters->Flags);
1251 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1252 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1255 /*********************
1256 * Create the back, front and stencil buffers
1257 *******************/
1258 TRACE("calling rendertarget CB\n");
1259 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1260 object->presentParms.BackBufferWidth,
1261 object->presentParms.BackBufferHeight,
1262 object->presentParms.BackBufferFormat,
1263 object->presentParms.MultiSampleType,
1264 object->presentParms.MultiSampleQuality,
1265 TRUE /* Lockable */,
1266 &object->frontBuffer,
1267 NULL /* pShared (always null)*/);
1268 if (object->frontBuffer != NULL)
1269 IWineD3DSurface_SetContainer(object->frontBuffer, (IUnknown *)object);
1270 TRACE("calling rendertarget CB\n");
1271 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1272 object->presentParms.BackBufferWidth,
1273 object->presentParms.BackBufferHeight,
1274 object->presentParms.BackBufferFormat,
1275 object->presentParms.MultiSampleType,
1276 object->presentParms.MultiSampleQuality,
1277 TRUE /* Lockable */,
1278 &object->backBuffer,
1279 NULL /* pShared (always null)*/);
1280 if (object->backBuffer != NULL)
1281 IWineD3DSurface_SetContainer(object->backBuffer, (IUnknown *)object);
1283 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1284 if (pPresentationParameters->EnableAutoDepthStencil) {
1285 TRACE("Creating depth stencil buffer\n");
1286 if (This->depthStencilBuffer == NULL ) {
1287 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1288 object->presentParms.BackBufferWidth,
1289 object->presentParms.BackBufferHeight,
1290 object->presentParms.AutoDepthStencilFormat,
1291 object->presentParms.MultiSampleType,
1292 object->presentParms.MultiSampleQuality,
1293 FALSE /* FIXME: Discard */,
1294 &This->depthStencilBuffer,
1295 NULL /* pShared (always null)*/ );
1296 if (This->depthStencilBuffer != NULL)
1297 IWineD3DSurface_SetContainer(This->depthStencilBuffer, (IUnknown *)iface);
1300 /** TODO: A check on width, height and multisample types
1301 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1302 ****************************/
1303 object->wantsDepthStencilBuffer = TRUE;
1305 object->wantsDepthStencilBuffer = FALSE;
1308 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1311 /*********************
1312 * init the default renderTarget management
1313 *******************/
1314 object->drawable = object->win;
1315 object->render_ctx = object->glCtx;
1318 /*********************
1319 * Setup some defaults and clear down the buffers
1320 *******************/
1322 /** save current context and drawable **/
1323 oldContext = glXGetCurrentContext();
1324 oldDrawable = glXGetCurrentDrawable();
1326 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1327 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1328 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1330 checkGLcall("glXMakeCurrent");
1332 TRACE("Setting up the screen\n");
1333 /* Clear the screen */
1334 glClearColor(0.0, 0.0, 0.0, 0.0);
1335 checkGLcall("glClearColor");
1338 glClearStencil(0xffff);
1340 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1341 checkGLcall("glClear");
1343 glColor3f(1.0, 1.0, 1.0);
1344 checkGLcall("glColor3f");
1346 glEnable(GL_LIGHTING);
1347 checkGLcall("glEnable");
1349 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1350 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1352 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1353 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1355 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1356 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1358 /* switch back to the original context (if there was one)*/
1359 if (This->swapchains != NULL) {
1360 /** TODO: restore the context and drawable **/
1361 glXMakeCurrent(object->display, oldDrawable, oldContext);
1366 { /* Finally add the swapchain to the end of the devices' swapchain list */
1367 SwapChainList **nextSwapchain;
1368 nextSwapchain = &This->swapchains;
1369 while (*nextSwapchain != NULL) {
1370 nextSwapchain = &((*nextSwapchain)->next);
1372 (*nextSwapchain) = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->swapchains));
1373 (*nextSwapchain)->swapchain = (IWineD3DSwapChain *)object;
1375 TRACE("Set swapchain to %p\n", object);
1376 } else { /* something went wrong so clean up */
1377 IUnknown* bufferParent;
1378 if (object->frontBuffer) {
1379 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1380 IUnknown_Release(bufferParent); /* once for the get parent */
1381 if (IUnknown_Release(bufferParent) > 0) {
1382 FIXME("(%p) Something's still holding the front buffer\n",This);
1385 if (object->backBuffer) {
1386 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1387 IUnknown_Release(bufferParent); /* once for the get parent */
1388 if (IUnknown_Release(bufferParent) > 0) {
1389 FIXME("(%p) Something's still holding the back buffer\n",This);
1392 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1393 /* Clean up the context */
1394 /* check that we are the current context first (we shouldn't be though!) */
1395 if (object->glCtx != 0) {
1396 if(glXGetCurrentContext() == object->glCtx) {
1397 glXMakeCurrent(object->display, None, NULL);
1399 glXDestroyContext(object->display, object->glCtx);
1401 HeapFree(GetProcessHeap(), 0, object);
1408 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1409 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1410 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1411 unsigned int numberOfSwapChains = 0;
1412 SwapChainList *swapchain;
1414 swapchain = This->swapchains;
1415 /* itterate through the list to get a count */
1416 while (swapchain != NULL) {
1417 swapchain = swapchain->next;
1418 numberOfSwapChains++;
1421 TRACE("(%p) returning %d\n", This, numberOfSwapChains);
1422 return numberOfSwapChains;
1425 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1426 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1427 SwapChainList *swapchain;
1428 HRESULT hr = D3DERR_INVALIDCALL;
1429 swapchain = This->swapchains;
1430 TRACE("(%p) : swapchain %d \n", This, iSwapChain);
1433 TRACE("(%p) Finding swapchain %d\n", This, iSwapChain);
1434 while (iSwapChain > 0 && swapchain != NULL) {
1435 swapchain = swapchain->next;
1439 if (iSwapChain > 0 || swapchain == NULL) {
1440 FIXME("(%p) Unable to find swapchain %d\n", This, iSwapChain);
1443 /** TODO: move off to a linkesList implementation **/
1444 *pSwapChain = swapchain->swapchain;
1445 IWineD3DSwapChain_AddRef(*pSwapChain);
1449 TRACE("(%p) returning %p\n", This, *pSwapChain);
1453 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
1454 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1456 FIXME("(%p) : Stub\n",This);
1462 * Vertex Declaration
1464 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1465 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1466 IWineD3DVertexDeclarationImpl *object = NULL;
1467 HRESULT hr = D3D_OK;
1468 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1469 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1472 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1477 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1478 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DVertexShader** ppVertexShader, IUnknown *parent) {
1479 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1480 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1481 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1483 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1484 IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1489 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DPixelShader** ppPixelShader, IUnknown *parent) {
1490 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1491 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1493 D3DCREATEOBJECTINSTANCE(object, PixelShader)
1495 object->function = pFunction;
1496 #else /* TODO: pixel shader set function */
1497 IWineD3DPixelShaderImpl_SetFuction(*ppPixelShader, pFunction);
1499 FIXME("(%p) : STUB: Created Pixel shader %p\n", This, ppPixelShader);
1505 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice* iface, IWineD3D** ppD3D) {
1506 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1507 *ppD3D= This->wineD3D;
1508 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1509 IWineD3D_AddRef(*ppD3D);
1513 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1514 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1515 * Into the video ram as possible and seeing how many fit
1516 * you can also get the correct initial value from via X and ATI's driver
1517 *******************/
1518 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1519 static BOOL showfixmes = TRUE;
1521 FIXME("(%p) : stub, emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1522 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1525 TRACE("(%p) : emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1526 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1527 /* videomemory is simulated videomemory + AGP memory left */
1528 return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1536 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1537 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1539 /* Update the current state block */
1540 This->updateStateBlock->fvf = fvf;
1541 This->updateStateBlock->changed.fvf = TRUE;
1542 This->updateStateBlock->set.fvf = TRUE;
1544 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1545 /* clear down the vertex declaration
1546 NOTE: Axis and Allies doesn't work properly otherwise
1547 (may be a stateblock problem though!)
1549 /* No difference if recording or not */
1550 return IWineD3DDevice_SetVertexDeclaration(iface, NULL);
1555 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1556 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1557 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1558 *pfvf = This->stateBlock->fvf;
1563 * Get / Set Stream Source
1565 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1566 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1567 IWineD3DVertexBuffer *oldSrc;
1569 /**TODO: instance and index data, see
1570 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1572 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
1575 /* D3d9 only, but shouldn't hurt d3d8 */
1578 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1580 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1581 FIXME("stream index data not supported\n");
1583 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1584 FIXME("stream instance data not supported\n");
1588 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1590 if (StreamNumber >= MAX_STREAMS) {
1591 WARN("Stream out of range %d\n", StreamNumber);
1592 return D3DERR_INVALIDCALL;
1595 oldSrc = This->stateBlock->streamSource[StreamNumber];
1596 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1598 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
1599 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
1600 This->updateStateBlock->streamStride[StreamNumber] = Stride;
1601 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
1602 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
1603 This->updateStateBlock->streamFlags[StreamNumber] = streamFlags;
1605 /* Handle recording of state blocks */
1606 if (This->isRecordingState) {
1607 TRACE("Recording... not performing anything\n");
1611 /* Not recording... */
1612 /* Need to do a getParent and pass the reffs up */
1613 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
1614 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
1615 so for now, just count internally */
1616 if (pStreamData != NULL) {
1617 IUnknown *newVertexBufferParent;
1618 /* GetParent will add a ref, so leave it hanging until the vertex buffer is cleared */
1619 IWineD3DVertexBuffer_GetParent(pStreamData, &newVertexBufferParent);
1621 if (oldSrc != NULL) {
1622 IUnknown *oldVertexBufferParent;
1623 IWineD3DVertexBuffer_GetParent(oldSrc, &oldVertexBufferParent);
1624 IUnknown_Release(oldVertexBufferParent);
1625 IUnknown_Release(oldVertexBufferParent);
1631 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
1632 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1635 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
1636 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
1639 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1641 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1642 FIXME("stream index data not supported\n");
1644 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1645 FIXME("stream instance data not supported\n");
1649 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1651 if (StreamNumber >= MAX_STREAMS) {
1652 WARN("Stream out of range %d\n", StreamNumber);
1653 return D3DERR_INVALIDCALL;
1655 *pStream = This->stateBlock->streamSource[StreamNumber];
1656 *pStride = This->stateBlock->streamStride[StreamNumber];
1657 *pOffset = This->stateBlock->streamOffset[StreamNumber];
1659 if (*pStream == NULL) {
1660 FIXME("Attempting to get an empty stream %d, returning D3DERR_INVALIDCALL\n", StreamNumber);
1661 return D3DERR_INVALIDCALL;
1664 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
1668 /*Should be quite easy, just an extension of vertexdata
1670 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1672 The divider is a bit odd though
1674 VertexOffset = StartVertex / Divider * StreamStride +
1675 VertexIndex / Divider * StreamStride + StreamOffset
1678 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
1679 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1681 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
1682 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (D3DSTREAMSOURCE_INSTANCEDATA | D3DSTREAMSOURCE_INDEXEDDATA );
1684 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
1685 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
1686 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
1688 if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
1689 FIXME("Stream indexing not fully supported\n");
1695 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
1696 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1698 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
1699 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
1701 TRACE("(%p) : returning %d\n", This, *Divider);
1707 * Get / Set & Multiply Transform
1709 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1710 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1712 /* Most of this routine, comments included copied from ddraw tree initially: */
1713 TRACE("(%p) : Transform State=%d\n", This, d3dts);
1715 /* Handle recording of state blocks */
1716 if (This->isRecordingState) {
1717 TRACE("Recording... not performing anything\n");
1718 This->updateStateBlock->changed.transform[d3dts] = TRUE;
1719 This->updateStateBlock->set.transform[d3dts] = TRUE;
1720 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1725 * If the new matrix is the same as the current one,
1726 * we cut off any further processing. this seems to be a reasonable
1727 * optimization because as was noticed, some apps (warcraft3 for example)
1728 * tend towards setting the same matrix repeatedly for some reason.
1730 * From here on we assume that the new matrix is different, wherever it matters.
1732 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1733 TRACE("The app is setting the same matrix over again\n");
1736 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1740 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1741 where ViewMat = Camera space, WorldMat = world space.
1743 In OpenGL, camera and world space is combined into GL_MODELVIEW
1744 matrix. The Projection matrix stay projection matrix.
1747 /* Capture the times we can just ignore the change for now */
1748 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1749 This->modelview_valid = FALSE;
1752 } else if (d3dts == D3DTS_PROJECTION) {
1753 This->proj_valid = FALSE;
1756 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1757 /* Indexed Vertex Blending Matrices 256 -> 511 */
1758 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1759 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1763 /* Now we really are going to have to change a matrix */
1766 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1767 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
1768 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1771 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1772 * NOTE: We have to reset the positions even if the light/plane is not currently
1773 * enabled, since the call to enable it will not reset the position.
1774 * NOTE2: Apparently texture transforms do NOT need reapplying
1777 PLIGHTINFOEL *lightChain = NULL;
1778 This->modelview_valid = FALSE;
1779 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
1781 glMatrixMode(GL_MODELVIEW);
1782 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1784 glLoadMatrixf((float *)lpmatrix);
1785 checkGLcall("glLoadMatrixf(...)");
1788 lightChain = This->stateBlock->lights;
1789 while (lightChain && lightChain->glIndex != -1) {
1790 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1791 checkGLcall("glLightfv posn");
1792 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1793 checkGLcall("glLightfv dirn");
1794 lightChain = lightChain->next;
1797 /* Reset Clipping Planes if clipping is enabled */
1798 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1799 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1800 checkGLcall("glClipPlane");
1804 } else { /* What was requested!?? */
1805 WARN("invalid matrix specified: %i\n", d3dts);
1808 /* Release lock, all done */
1813 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1814 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1815 TRACE("(%p) : for Transform State %d\n", This, State);
1816 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1820 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1821 D3DMATRIX *mat = NULL;
1824 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1825 * below means it will be recorded in a state block change, but it
1826 * works regardless where it is recorded.
1827 * If this is found to be wrong, change to StateBlock.
1829 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1830 TRACE("(%p) : For state %u\n", This, State);
1832 if (State < HIGHEST_TRANSFORMSTATE)
1834 mat = &This->updateStateBlock->transforms[State];
1836 FIXME("Unhandled transform state!!\n");
1839 /* Copied from ddraw code: */
1840 temp.u.s._11 = (mat->u.s._11 * pMatrix->u.s._11) + (mat->u.s._21 * pMatrix->u.s._12) +
1841 (mat->u.s._31 * pMatrix->u.s._13) + (mat->u.s._41 * pMatrix->u.s._14);
1842 temp.u.s._21 = (mat->u.s._11 * pMatrix->u.s._21) + (mat->u.s._21 * pMatrix->u.s._22) +
1843 (mat->u.s._31 * pMatrix->u.s._23) + (mat->u.s._41 * pMatrix->u.s._24);
1844 temp.u.s._31 = (mat->u.s._11 * pMatrix->u.s._31) + (mat->u.s._21 * pMatrix->u.s._32) +
1845 (mat->u.s._31 * pMatrix->u.s._33) + (mat->u.s._41 * pMatrix->u.s._34);
1846 temp.u.s._41 = (mat->u.s._11 * pMatrix->u.s._41) + (mat->u.s._21 * pMatrix->u.s._42) +
1847 (mat->u.s._31 * pMatrix->u.s._43) + (mat->u.s._41 * pMatrix->u.s._44);
1849 temp.u.s._12 = (mat->u.s._12 * pMatrix->u.s._11) + (mat->u.s._22 * pMatrix->u.s._12) +
1850 (mat->u.s._32 * pMatrix->u.s._13) + (mat->u.s._42 * pMatrix->u.s._14);
1851 temp.u.s._22 = (mat->u.s._12 * pMatrix->u.s._21) + (mat->u.s._22 * pMatrix->u.s._22) +
1852 (mat->u.s._32 * pMatrix->u.s._23) + (mat->u.s._42 * pMatrix->u.s._24);
1853 temp.u.s._32 = (mat->u.s._12 * pMatrix->u.s._31) + (mat->u.s._22 * pMatrix->u.s._32) +
1854 (mat->u.s._32 * pMatrix->u.s._33) + (mat->u.s._42 * pMatrix->u.s._34);
1855 temp.u.s._42 = (mat->u.s._12 * pMatrix->u.s._41) + (mat->u.s._22 * pMatrix->u.s._42) +
1856 (mat->u.s._32 * pMatrix->u.s._43) + (mat->u.s._42 * pMatrix->u.s._44);
1858 temp.u.s._13 = (mat->u.s._13 * pMatrix->u.s._11) + (mat->u.s._23 * pMatrix->u.s._12) +
1859 (mat->u.s._33 * pMatrix->u.s._13) + (mat->u.s._43 * pMatrix->u.s._14);
1860 temp.u.s._23 = (mat->u.s._13 * pMatrix->u.s._21) + (mat->u.s._23 * pMatrix->u.s._22) +
1861 (mat->u.s._33 * pMatrix->u.s._23) + (mat->u.s._43 * pMatrix->u.s._24);
1862 temp.u.s._33 = (mat->u.s._13 * pMatrix->u.s._31) + (mat->u.s._23 * pMatrix->u.s._32) +
1863 (mat->u.s._33 * pMatrix->u.s._33) + (mat->u.s._43 * pMatrix->u.s._34);
1864 temp.u.s._43 = (mat->u.s._13 * pMatrix->u.s._41) + (mat->u.s._23 * pMatrix->u.s._42) +
1865 (mat->u.s._33 * pMatrix->u.s._43) + (mat->u.s._43 * pMatrix->u.s._44);
1867 temp.u.s._14 = (mat->u.s._14 * pMatrix->u.s._11) + (mat->u.s._24 * pMatrix->u.s._12) +
1868 (mat->u.s._34 * pMatrix->u.s._13) + (mat->u.s._44 * pMatrix->u.s._14);
1869 temp.u.s._24 = (mat->u.s._14 * pMatrix->u.s._21) + (mat->u.s._24 * pMatrix->u.s._22) +
1870 (mat->u.s._34 * pMatrix->u.s._23) + (mat->u.s._44 * pMatrix->u.s._24);
1871 temp.u.s._34 = (mat->u.s._14 * pMatrix->u.s._31) + (mat->u.s._24 * pMatrix->u.s._32) +
1872 (mat->u.s._34 * pMatrix->u.s._33) + (mat->u.s._44 * pMatrix->u.s._34);
1873 temp.u.s._44 = (mat->u.s._14 * pMatrix->u.s._41) + (mat->u.s._24 * pMatrix->u.s._42) +
1874 (mat->u.s._34 * pMatrix->u.s._43) + (mat->u.s._44 * pMatrix->u.s._44);
1876 /* Apply change via set transform - will reapply to eg. lights this way */
1877 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
1882 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
1884 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1885 you can reference any indexes you want as long as that number max are enabled at any
1886 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1887 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1888 but when recording, just build a chain pretty much of commands to be replayed. */
1890 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
1892 PLIGHTINFOEL *object, *temp;
1894 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1895 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1897 /* If recording state block, just add to end of lights chain */
1898 if (This->isRecordingState) {
1899 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1900 if (NULL == object) {
1901 return D3DERR_OUTOFVIDEOMEMORY;
1903 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1904 object->OriginalIndex = Index;
1905 object->glIndex = -1;
1906 object->changed = TRUE;
1908 /* Add to the END of the chain of lights changes to be replayed */
1909 if (This->updateStateBlock->lights == NULL) {
1910 This->updateStateBlock->lights = object;
1912 temp = This->updateStateBlock->lights;
1913 while (temp->next != NULL) temp=temp->next;
1914 temp->next = object;
1916 TRACE("Recording... not performing anything more\n");
1920 /* Ok, not recording any longer so do real work */
1921 object = This->stateBlock->lights;
1922 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1924 /* If we didn't find it in the list of lights, time to add it */
1925 if (object == NULL) {
1926 PLIGHTINFOEL *insertAt,*prevPos;
1928 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1929 if (NULL == object) {
1930 return D3DERR_OUTOFVIDEOMEMORY;
1932 object->OriginalIndex = Index;
1933 object->glIndex = -1;
1935 /* Add it to the front of list with the idea that lights will be changed as needed
1936 BUT after any lights currently assigned GL indexes */
1937 insertAt = This->stateBlock->lights;
1939 while (insertAt != NULL && insertAt->glIndex != -1) {
1941 insertAt = insertAt->next;
1944 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1945 This->stateBlock->lights = object;
1946 } else if (insertAt == NULL) { /* End of list */
1947 prevPos->next = object;
1948 object->prev = prevPos;
1949 } else { /* Middle of chain */
1950 if (prevPos == NULL) {
1951 This->stateBlock->lights = object;
1953 prevPos->next = object;
1955 object->prev = prevPos;
1956 object->next = insertAt;
1957 insertAt->prev = object;
1961 /* Initialze the object */
1962 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,
1963 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1964 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1965 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1966 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1967 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1968 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1970 /* Save away the information */
1971 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1973 switch (pLight->Type) {
1974 case D3DLIGHT_POINT:
1976 object->lightPosn[0] = pLight->Position.x;
1977 object->lightPosn[1] = pLight->Position.y;
1978 object->lightPosn[2] = pLight->Position.z;
1979 object->lightPosn[3] = 1.0f;
1980 object->cutoff = 180.0f;
1984 case D3DLIGHT_DIRECTIONAL:
1986 object->lightPosn[0] = -pLight->Direction.x;
1987 object->lightPosn[1] = -pLight->Direction.y;
1988 object->lightPosn[2] = -pLight->Direction.z;
1989 object->lightPosn[3] = 0.0;
1990 object->exponent = 0.0f;
1991 object->cutoff = 180.0f;
1996 object->lightPosn[0] = pLight->Position.x;
1997 object->lightPosn[1] = pLight->Position.y;
1998 object->lightPosn[2] = pLight->Position.z;
1999 object->lightPosn[3] = 1.0;
2002 object->lightDirn[0] = pLight->Direction.x;
2003 object->lightDirn[1] = pLight->Direction.y;
2004 object->lightDirn[2] = pLight->Direction.z;
2005 object->lightDirn[3] = 1.0;
2008 * opengl-ish and d3d-ish spot lights use too different models for the
2009 * light "intensity" as a function of the angle towards the main light direction,
2010 * so we only can approximate very roughly.
2011 * however spot lights are rather rarely used in games (if ever used at all).
2012 * furthermore if still used, probably nobody pays attention to such details.
2014 if (pLight->Falloff == 0) {
2017 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2019 if (rho < 0.0001) rho = 0.0001f;
2020 object->exponent = -0.3/log(cos(rho/2));
2021 object->cutoff = pLight->Phi*90/M_PI;
2027 FIXME("Unrecognized light type %d\n", pLight->Type);
2030 /* Update the live definitions if the light is currently assigned a glIndex */
2031 if (object->glIndex != -1) {
2032 setup_light(iface, object->glIndex, object);
2037 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2038 PLIGHTINFOEL *lightInfo = NULL;
2039 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2040 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2042 /* Locate the light in the live lights */
2043 lightInfo = This->stateBlock->lights;
2044 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2046 if (lightInfo == NULL) {
2047 TRACE("Light information requested but light not defined\n");
2048 return D3DERR_INVALIDCALL;
2051 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
2056 * Get / Set Light Enable
2057 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2059 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2060 PLIGHTINFOEL *lightInfo = NULL;
2061 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2062 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2064 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2065 if (This->isRecordingState) {
2066 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2067 if (NULL == lightInfo) {
2068 return D3DERR_OUTOFVIDEOMEMORY;
2070 lightInfo->OriginalIndex = Index;
2071 lightInfo->glIndex = -1;
2072 lightInfo->enabledChanged = TRUE;
2074 /* Add to the END of the chain of lights changes to be replayed */
2075 if (This->updateStateBlock->lights == NULL) {
2076 This->updateStateBlock->lights = lightInfo;
2078 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2079 while (temp->next != NULL) temp=temp->next;
2080 temp->next = lightInfo;
2082 TRACE("Recording... not performing anything more\n");
2086 /* Not recording... So, locate the light in the live lights */
2087 lightInfo = This->stateBlock->lights;
2088 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2090 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2091 if (lightInfo == NULL) {
2092 D3DLIGHT9 lightParms;
2093 /* Warning - untested code :-) Prob safe to change fixme to a trace but
2094 wait until someone confirms it seems to work! */
2095 TRACE("Light enabled requested but light not defined, so defining one!\n");
2096 lightParms.Type = D3DLIGHT_DIRECTIONAL;
2097 lightParms.Diffuse.r = 1.0;
2098 lightParms.Diffuse.g = 1.0;
2099 lightParms.Diffuse.b = 1.0;
2100 lightParms.Diffuse.a = 0.0;
2101 lightParms.Specular.r = 0.0;
2102 lightParms.Specular.g = 0.0;
2103 lightParms.Specular.b = 0.0;
2104 lightParms.Specular.a = 0.0;
2105 lightParms.Ambient.r = 0.0;
2106 lightParms.Ambient.g = 0.0;
2107 lightParms.Ambient.b = 0.0;
2108 lightParms.Ambient.a = 0.0;
2109 lightParms.Position.x = 0.0;
2110 lightParms.Position.y = 0.0;
2111 lightParms.Position.z = 0.0;
2112 lightParms.Direction.x = 0.0;
2113 lightParms.Direction.y = 0.0;
2114 lightParms.Direction.z = 1.0;
2115 lightParms.Range = 0.0;
2116 lightParms.Falloff = 0.0;
2117 lightParms.Attenuation0 = 0.0;
2118 lightParms.Attenuation1 = 0.0;
2119 lightParms.Attenuation2 = 0.0;
2120 lightParms.Theta = 0.0;
2121 lightParms.Phi = 0.0;
2122 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
2124 /* Search for it again! Should be fairly quick as near head of list */
2125 lightInfo = This->stateBlock->lights;
2126 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2127 if (lightInfo == NULL) {
2128 FIXME("Adding default lights has failed dismally\n");
2129 return D3DERR_INVALIDCALL;
2133 /* OK, we now have a light... */
2134 if (Enable == FALSE) {
2136 /* If we are disabling it, check it was enabled, and
2137 still only do something if it has assigned a glIndex (which it should have!) */
2138 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2139 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2141 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2142 checkGLcall("glDisable GL_LIGHT0+Index");
2145 TRACE("Nothing to do as light was not enabled\n");
2147 lightInfo->lightEnabled = FALSE;
2150 /* We are enabling it. If it is enabled, it's really simple */
2151 if (lightInfo->lightEnabled) {
2153 TRACE("Nothing to do as light was enabled\n");
2155 /* If it already has a glIndex, it's still simple */
2156 } else if (lightInfo->glIndex != -1) {
2157 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2158 lightInfo->lightEnabled = TRUE;
2160 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2161 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2164 /* Otherwise got to find space - lights are ordered gl indexes first */
2166 PLIGHTINFOEL *bsf = NULL;
2167 PLIGHTINFOEL *pos = This->stateBlock->lights;
2168 PLIGHTINFOEL *prev = NULL;
2172 /* Try to minimize changes as much as possible */
2173 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2175 /* Try to remember which index can be replaced if necessary */
2176 if (bsf==NULL && pos->lightEnabled == FALSE) {
2177 /* Found a light we can replace, save as best replacement */
2181 /* Step to next space */
2187 /* If we have too many active lights, fail the call */
2188 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2189 FIXME("Program requests too many concurrent lights\n");
2190 return D3DERR_INVALIDCALL;
2192 /* If we have allocated all lights, but not all are enabled,
2193 reuse one which is not enabled */
2194 } else if (Index == This->maxConcurrentLights) {
2195 /* use bsf - Simply swap the new light and the BSF one */
2196 PLIGHTINFOEL *bsfNext = bsf->next;
2197 PLIGHTINFOEL *bsfPrev = bsf->prev;
2200 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2201 if (bsf->prev != NULL) {
2202 bsf->prev->next = lightInfo;
2204 This->stateBlock->lights = lightInfo;
2207 /* If not side by side, lots of chains to update */
2208 if (bsf->next != lightInfo) {
2209 lightInfo->prev->next = bsf;
2210 bsf->next->prev = lightInfo;
2211 bsf->next = lightInfo->next;
2212 bsf->prev = lightInfo->prev;
2213 lightInfo->next = bsfNext;
2214 lightInfo->prev = bsfPrev;
2218 bsf->prev = lightInfo;
2219 bsf->next = lightInfo->next;
2220 lightInfo->next = bsf;
2221 lightInfo->prev = bsfPrev;
2226 glIndex = bsf->glIndex;
2228 lightInfo->glIndex = glIndex;
2229 lightInfo->lightEnabled = TRUE;
2231 /* Finally set up the light in gl itself */
2232 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2234 setup_light(iface, glIndex, lightInfo);
2235 glEnable(GL_LIGHT0 + glIndex);
2236 checkGLcall("glEnable GL_LIGHT0 new setup");
2239 /* If we reached the end of the allocated lights, with space in the
2240 gl lights, setup a new light */
2241 } else if (pos->glIndex == -1) {
2243 /* We reached the end of the allocated gl lights, so already
2244 know the index of the next one! */
2246 lightInfo->glIndex = glIndex;
2247 lightInfo->lightEnabled = TRUE;
2249 /* In an ideal world, it's already in the right place */
2250 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2251 /* No need to move it */
2253 /* Remove this light from the list */
2254 lightInfo->prev->next = lightInfo->next;
2255 if (lightInfo->next != NULL) {
2256 lightInfo->next->prev = lightInfo->prev;
2259 /* Add in at appropriate place (inbetween prev and pos) */
2260 lightInfo->prev = prev;
2261 lightInfo->next = pos;
2263 This->stateBlock->lights = lightInfo;
2265 prev->next = lightInfo;
2268 pos->prev = lightInfo;
2272 /* Finally set up the light in gl itself */
2273 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2275 setup_light(iface, glIndex, lightInfo);
2276 glEnable(GL_LIGHT0 + glIndex);
2277 checkGLcall("glEnable GL_LIGHT0 new setup");
2286 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2288 PLIGHTINFOEL *lightInfo = NULL;
2289 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2290 TRACE("(%p) : for idx(%ld)\n", This, Index);
2292 /* Locate the light in the live lights */
2293 lightInfo = This->stateBlock->lights;
2294 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2296 if (lightInfo == NULL) {
2297 TRACE("Light enabled state requested but light not defined\n");
2298 return D3DERR_INVALIDCALL;
2300 *pEnable = lightInfo->lightEnabled;
2305 * Get / Set Clip Planes
2307 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2308 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2309 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2311 /* Validate Index */
2312 if (Index >= GL_LIMITS(clipplanes)) {
2313 TRACE("Application has requested clipplane this device doesn't support\n");
2314 return D3DERR_INVALIDCALL;
2317 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2318 This->updateStateBlock->set.clipplane[Index] = TRUE;
2319 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2320 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2321 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2322 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2324 /* Handle recording of state blocks */
2325 if (This->isRecordingState) {
2326 TRACE("Recording... not performing anything\n");
2334 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2335 glMatrixMode(GL_MODELVIEW);
2337 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2339 TRACE("Clipplane [%f,%f,%f,%f]\n",
2340 This->updateStateBlock->clipplane[Index][0],
2341 This->updateStateBlock->clipplane[Index][1],
2342 This->updateStateBlock->clipplane[Index][2],
2343 This->updateStateBlock->clipplane[Index][3]);
2344 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2345 checkGLcall("glClipPlane");
2353 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2354 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2355 TRACE("(%p) : for idx %ld\n", This, Index);
2357 /* Validate Index */
2358 if (Index >= GL_LIMITS(clipplanes)) {
2359 TRACE("Application has requested clipplane this device doesn't support\n");
2360 return D3DERR_INVALIDCALL;
2363 pPlane[0] = This->stateBlock->clipplane[Index][0];
2364 pPlane[1] = This->stateBlock->clipplane[Index][1];
2365 pPlane[2] = This->stateBlock->clipplane[Index][2];
2366 pPlane[3] = This->stateBlock->clipplane[Index][3];
2371 * Get / Set Clip Plane Status
2372 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2374 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2375 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2376 FIXME("(%p) : stub\n", This);
2377 if (NULL == pClipStatus) {
2378 return D3DERR_INVALIDCALL;
2380 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2381 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2385 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2386 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2387 FIXME("(%p) : stub\n", This);
2388 if (NULL == pClipStatus) {
2389 return D3DERR_INVALIDCALL;
2391 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2392 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2397 * Get / Set Material
2398 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2400 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2401 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2403 This->updateStateBlock->changed.material = TRUE;
2404 This->updateStateBlock->set.material = TRUE;
2405 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2407 /* Handle recording of state blocks */
2408 if (This->isRecordingState) {
2409 TRACE("Recording... not performing anything\n");
2414 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2415 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2416 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2417 pMaterial->Ambient.b, pMaterial->Ambient.a);
2418 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2419 pMaterial->Specular.b, pMaterial->Specular.a);
2420 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2421 pMaterial->Emissive.b, pMaterial->Emissive.a);
2422 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2424 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2425 checkGLcall("glMaterialfv(GL_AMBIENT)");
2426 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2427 checkGLcall("glMaterialfv(GL_DIFFUSE)");
2429 /* Only change material color if specular is enabled, otherwise it is set to black */
2430 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2431 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2432 checkGLcall("glMaterialfv(GL_SPECULAR");
2434 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2435 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2436 checkGLcall("glMaterialfv(GL_SPECULAR");
2438 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2439 checkGLcall("glMaterialfv(GL_EMISSION)");
2440 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2441 checkGLcall("glMaterialf(GL_SHININESS");
2447 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2448 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2449 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2450 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2451 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2452 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2453 pMaterial->Ambient.b, pMaterial->Ambient.a);
2454 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2455 pMaterial->Specular.b, pMaterial->Specular.a);
2456 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2457 pMaterial->Emissive.b, pMaterial->Emissive.a);
2458 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2466 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2467 UINT BaseVertexIndex) {
2468 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2469 IWineD3DIndexBuffer *oldIdxs;
2471 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2472 oldIdxs = This->updateStateBlock->pIndexData;
2474 This->updateStateBlock->changed.indices = TRUE;
2475 This->updateStateBlock->set.indices = TRUE;
2476 This->updateStateBlock->pIndexData = pIndexData;
2477 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2479 /* Handle recording of state blocks */
2480 if (This->isRecordingState) {
2481 TRACE("Recording... not performing anything\n");
2486 IUnknown *indexBufferParent;
2487 /* Getting the parent causes a addRef... it gets released when the indicies are clear */
2488 IWineD3DIndexBuffer_GetParent(pIndexData, &indexBufferParent);
2491 IUnknown *indexBufferParent;
2492 IWineD3DIndexBuffer_GetParent(oldIdxs, &indexBufferParent);
2493 IUnknown_Release(indexBufferParent);
2494 IUnknown_Release(indexBufferParent);
2499 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2500 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2502 *ppIndexData = This->stateBlock->pIndexData;
2504 /* up ref count on ppindexdata */
2506 IWineD3DIndexBuffer_AddRef(*ppIndexData);
2507 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2508 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
2510 TRACE("(%p) No index data set\n", This);
2512 TRACE("Returning %p %d \n",*ppIndexData, *pBaseVertexIndex);
2518 * Get / Set Viewports
2520 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2521 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2523 TRACE("(%p)\n", This);
2524 This->updateStateBlock->changed.viewport = TRUE;
2525 This->updateStateBlock->set.viewport = TRUE;
2526 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2528 /* Handle recording of state blocks */
2529 if (This->isRecordingState) {
2530 TRACE("Recording... not performing anything\n");
2536 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2537 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2539 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2540 checkGLcall("glDepthRange");
2541 /* Note: GL requires lower left, DirectX supplies upper left */
2542 /* TODO: replace usage of renderTarget with context management */
2543 glViewport(pViewport->X,
2544 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2545 pViewport->Width, pViewport->Height);
2547 checkGLcall("glViewport");
2555 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2556 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2557 TRACE("(%p)\n", This);
2558 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2563 * Get / Set Render States
2564 * TODO: Verify against dx9 definitions
2566 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2568 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2569 DWORD OldValue = This->stateBlock->renderState[State];
2571 /* Simple way of referring to either a DWORD or a 4 byte float */
2577 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2578 This->updateStateBlock->changed.renderState[State] = TRUE;
2579 This->updateStateBlock->set.renderState[State] = TRUE;
2580 This->updateStateBlock->renderState[State] = Value;
2582 /* Handle recording of state blocks */
2583 if (This->isRecordingState) {
2584 TRACE("Recording... not performing anything\n");
2591 case WINED3DRS_FILLMODE :
2592 switch ((D3DFILLMODE) Value) {
2593 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2594 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2595 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2597 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
2599 checkGLcall("glPolygonMode (fillmode)");
2602 case WINED3DRS_LIGHTING :
2604 glEnable(GL_LIGHTING);
2605 checkGLcall("glEnable GL_LIGHTING");
2607 glDisable(GL_LIGHTING);
2608 checkGLcall("glDisable GL_LIGHTING");
2612 case WINED3DRS_ZENABLE :
2613 switch ((D3DZBUFFERTYPE) Value) {
2615 glDisable(GL_DEPTH_TEST);
2616 checkGLcall("glDisable GL_DEPTH_TEST");
2619 glEnable(GL_DEPTH_TEST);
2620 checkGLcall("glEnable GL_DEPTH_TEST");
2623 glEnable(GL_DEPTH_TEST);
2624 checkGLcall("glEnable GL_DEPTH_TEST");
2625 FIXME("W buffer is not well handled\n");
2628 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2632 case WINED3DRS_CULLMODE :
2634 /* If we are culling "back faces with clockwise vertices" then
2635 set front faces to be counter clockwise and enable culling
2637 switch ((D3DCULL) Value) {
2639 glDisable(GL_CULL_FACE);
2640 checkGLcall("glDisable GL_CULL_FACE");
2643 glEnable(GL_CULL_FACE);
2644 checkGLcall("glEnable GL_CULL_FACE");
2645 if (This->renderUpsideDown) {
2647 checkGLcall("glFrontFace GL_CW");
2649 glFrontFace(GL_CCW);
2650 checkGLcall("glFrontFace GL_CCW");
2652 glCullFace(GL_BACK);
2655 glEnable(GL_CULL_FACE);
2656 checkGLcall("glEnable GL_CULL_FACE");
2657 if (This->renderUpsideDown) {
2658 glFrontFace(GL_CCW);
2659 checkGLcall("glFrontFace GL_CCW");
2662 checkGLcall("glFrontFace GL_CW");
2664 glCullFace(GL_BACK);
2667 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2671 case WINED3DRS_SHADEMODE :
2672 switch ((D3DSHADEMODE) Value) {
2674 glShadeModel(GL_FLAT);
2675 checkGLcall("glShadeModel");
2677 case D3DSHADE_GOURAUD:
2678 glShadeModel(GL_SMOOTH);
2679 checkGLcall("glShadeModel");
2681 case D3DSHADE_PHONG:
2682 FIXME("D3DSHADE_PHONG isn't supported?\n");
2685 return D3DERR_INVALIDCALL;
2687 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2691 case WINED3DRS_DITHERENABLE :
2693 glEnable(GL_DITHER);
2694 checkGLcall("glEnable GL_DITHER");
2696 glDisable(GL_DITHER);
2697 checkGLcall("glDisable GL_DITHER");
2701 case WINED3DRS_ZWRITEENABLE :
2704 checkGLcall("glDepthMask");
2707 checkGLcall("glDepthMask");
2711 case WINED3DRS_ZFUNC :
2713 int glParm = GL_LESS;
2715 switch ((D3DCMPFUNC) Value) {
2716 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2717 case D3DCMP_LESS: glParm=GL_LESS; break;
2718 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2719 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2720 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2721 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2722 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2723 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2725 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2727 glDepthFunc(glParm);
2728 checkGLcall("glDepthFunc");
2732 case WINED3DRS_AMBIENT :
2735 D3DCOLORTOGLFLOAT4(Value, col);
2736 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2737 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2738 checkGLcall("glLightModel for MODEL_AMBIENT");
2743 case WINED3DRS_ALPHABLENDENABLE :
2746 checkGLcall("glEnable GL_BLEND");
2748 glDisable(GL_BLEND);
2749 checkGLcall("glDisable GL_BLEND");
2753 case WINED3DRS_SRCBLEND :
2754 case WINED3DRS_DESTBLEND :
2756 int newVal = GL_ZERO;
2758 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2759 case D3DBLEND_ONE : newVal = GL_ONE; break;
2760 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2761 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2762 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2763 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2764 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2765 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2766 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2767 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2768 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2770 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2771 This->srcBlend = newVal;
2772 This->dstBlend = newVal;
2775 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2776 This->srcBlend = newVal;
2777 This->dstBlend = newVal;
2780 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2783 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2784 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2785 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2786 glBlendFunc(This->srcBlend, This->dstBlend);
2788 checkGLcall("glBlendFunc");
2792 case WINED3DRS_ALPHATESTENABLE :
2794 glEnable(GL_ALPHA_TEST);
2795 checkGLcall("glEnable GL_ALPHA_TEST");
2797 glDisable(GL_ALPHA_TEST);
2798 checkGLcall("glDisable GL_ALPHA_TEST");
2802 case WINED3DRS_ALPHAFUNC :
2804 int glParm = GL_LESS;
2805 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2807 switch ((D3DCMPFUNC) Value) {
2808 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2809 case D3DCMP_LESS: glParm = GL_LESS; break;
2810 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2811 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2812 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2813 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2814 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2815 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2817 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2819 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2820 glAlphaFunc(glParm, ref);
2821 This->alphafunc = glParm;
2822 checkGLcall("glAlphaFunc");
2826 case WINED3DRS_ALPHAREF :
2828 int glParm = This->alphafunc;
2831 ref = ((float) Value) / 255.0f;
2832 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2833 glAlphaFunc(glParm, ref);
2834 checkGLcall("glAlphaFunc");
2838 case WINED3DRS_CLIPPLANEENABLE :
2839 case WINED3DRS_CLIPPING :
2841 /* Ensure we only do the changed clip planes */
2842 DWORD enable = 0xFFFFFFFF;
2843 DWORD disable = 0x00000000;
2845 /* If enabling / disabling all */
2846 if (State == WINED3DRS_CLIPPING) {
2848 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2851 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2855 enable = Value & ~OldValue;
2856 disable = ~Value & OldValue;
2859 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2860 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2861 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2862 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2863 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2864 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2866 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2867 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2868 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2869 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2870 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2871 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2873 /** update clipping status */
2875 This->stateBlock->clip_status.ClipUnion = 0;
2876 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
2878 This->stateBlock->clip_status.ClipUnion = 0;
2879 This->stateBlock->clip_status.ClipIntersection = 0;
2884 case WINED3DRS_BLENDOP :
2886 int glParm = GL_FUNC_ADD;
2888 switch ((D3DBLENDOP) Value) {
2889 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2890 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2891 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2892 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2893 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2895 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2897 TRACE("glBlendEquation(%x)\n", glParm);
2898 glBlendEquation(glParm);
2899 checkGLcall("glBlendEquation");
2903 case WINED3DRS_TEXTUREFACTOR :
2907 /* Note the texture color applies to all textures whereas
2908 GL_TEXTURE_ENV_COLOR applies to active only */
2910 D3DCOLORTOGLFLOAT4(Value, col);
2911 /* Set the default alpha blend color */
2912 glBlendColor(col[0], col[1], col[2], col[3]);
2913 checkGLcall("glBlendColor");
2915 /* And now the default texture color as well */
2916 for (i = 0; i < GL_LIMITS(textures); i++) {
2918 /* Note the D3DRS value applies to all textures, but GL has one
2919 per texture, so apply it now ready to be used! */
2920 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2923 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2926 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2927 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2932 case WINED3DRS_SPECULARENABLE :
2934 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2935 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2936 specular color. This is wrong:
2937 Separate specular color means the specular colour is maintained separately, whereas
2938 single color means it is merged in. However in both cases they are being used to
2940 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2941 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2945 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2946 checkGLcall("glMaterialfv");
2947 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2948 glEnable(GL_COLOR_SUM_EXT);
2950 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2952 checkGLcall("glEnable(GL_COLOR_SUM)");
2954 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2956 /* for the case of enabled lighting: */
2957 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2958 checkGLcall("glMaterialfv");
2960 /* for the case of disabled lighting: */
2961 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2962 glDisable(GL_COLOR_SUM_EXT);
2964 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2966 checkGLcall("glDisable(GL_COLOR_SUM)");
2971 case WINED3DRS_STENCILENABLE :
2973 glEnable(GL_STENCIL_TEST);
2974 checkGLcall("glEnable GL_STENCIL_TEST");
2976 glDisable(GL_STENCIL_TEST);
2977 checkGLcall("glDisable GL_STENCIL_TEST");
2981 case WINED3DRS_STENCILFUNC :
2983 int glParm = GL_ALWAYS;
2984 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2985 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2987 switch ((D3DCMPFUNC) Value) {
2988 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2989 case D3DCMP_LESS: glParm=GL_LESS; break;
2990 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2991 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2992 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2993 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2994 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2995 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2997 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2999 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3000 This->stencilfunc = glParm;
3001 glStencilFunc(glParm, ref, mask);
3002 checkGLcall("glStencilFunc");
3006 case WINED3DRS_STENCILREF :
3008 int glParm = This->stencilfunc;
3010 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3013 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3014 glStencilFunc(glParm, ref, mask);
3015 checkGLcall("glStencilFunc");
3019 case WINED3DRS_STENCILMASK :
3021 int glParm = This->stencilfunc;
3022 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3023 GLuint mask = Value;
3025 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3026 glStencilFunc(glParm, ref, mask);
3027 checkGLcall("glStencilFunc");
3031 case WINED3DRS_STENCILFAIL :
3037 fail = StencilOp(Value);
3038 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
3039 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
3040 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
3041 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
3043 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3044 glStencilOp(fail, zfail, zpass);
3045 checkGLcall("glStencilOp(fail, zfail, zpass);");
3048 case WINED3DRS_STENCILZFAIL :
3054 glGetIntegerv(GL_STENCIL_FAIL, &fail);
3055 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
3056 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
3057 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
3058 zfail = StencilOp(Value);
3060 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3061 glStencilOp(fail, zfail, zpass);
3062 checkGLcall("glStencilOp(fail, zfail, zpass);");
3065 case WINED3DRS_STENCILPASS :
3071 glGetIntegerv(GL_STENCIL_FAIL, &fail);
3072 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
3073 zpass = StencilOp(Value);
3074 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
3075 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
3077 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3078 glStencilOp(fail, zfail, zpass);
3079 checkGLcall("glStencilOp(fail, zfail, zpass);");
3083 case WINED3DRS_STENCILWRITEMASK :
3085 glStencilMask(Value);
3086 TRACE("glStencilMask(%lu)\n", Value);
3087 checkGLcall("glStencilMask");
3091 case WINED3DRS_FOGENABLE :
3093 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
3095 checkGLcall("glEnable GL_FOG");
3098 checkGLcall("glDisable GL_FOG");
3103 case WINED3DRS_RANGEFOGENABLE :
3106 TRACE("Enabled RANGEFOG");
3108 TRACE("Disabled RANGEFOG");
3113 case WINED3DRS_FOGCOLOR :
3116 D3DCOLORTOGLFLOAT4(Value, col);
3117 /* Set the default alpha blend color */
3118 glFogfv(GL_FOG_COLOR, &col[0]);
3119 checkGLcall("glFog GL_FOG_COLOR");
3123 case WINED3DRS_FOGTABLEMODE :
3125 glHint(GL_FOG_HINT, GL_NICEST);
3127 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3128 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3129 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3130 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3132 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3134 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3135 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3140 case WINED3DRS_FOGVERTEXMODE :
3142 glHint(GL_FOG_HINT, GL_FASTEST);
3144 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3145 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3146 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3147 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3149 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3151 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3152 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
3157 case WINED3DRS_FOGSTART :
3160 glFogfv(GL_FOG_START, &tmpvalue.f);
3161 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3162 TRACE("Fog Start == %f\n", tmpvalue.f);
3166 case WINED3DRS_FOGEND :
3169 glFogfv(GL_FOG_END, &tmpvalue.f);
3170 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3171 TRACE("Fog End == %f\n", tmpvalue.f);
3175 case WINED3DRS_FOGDENSITY :
3178 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3179 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3183 case WINED3DRS_VERTEXBLEND :
3185 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3186 TRACE("Vertex Blending state to %ld\n", Value);
3190 case WINED3DRS_TWEENFACTOR :
3193 This->updateStateBlock->tween_factor = tmpvalue.f;
3194 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3198 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
3200 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3204 case WINED3DRS_COLORVERTEX :
3205 case WINED3DRS_DIFFUSEMATERIALSOURCE :
3206 case WINED3DRS_SPECULARMATERIALSOURCE :
3207 case WINED3DRS_AMBIENTMATERIALSOURCE :
3208 case WINED3DRS_EMISSIVEMATERIALSOURCE :
3210 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3212 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3213 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3214 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3215 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3216 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3217 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3219 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3220 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3221 Parm = GL_AMBIENT_AND_DIFFUSE;
3225 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3227 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3229 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3236 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3238 This->tracking_color = NEEDS_TRACKING;
3239 This->tracking_parm = Parm;
3243 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3248 case WINED3DRS_LINEPATTERN :
3254 tmppattern.d = Value;
3256 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3258 if (tmppattern.lp.wRepeatFactor) {
3259 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3260 checkGLcall("glLineStipple(repeat, linepattern)");
3261 glEnable(GL_LINE_STIPPLE);
3262 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3264 glDisable(GL_LINE_STIPPLE);
3265 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3270 case WINED3DRS_ZBIAS : /* D3D8 only */
3274 TRACE("ZBias value %f\n", tmpvalue.f);
3275 glPolygonOffset(0, -tmpvalue.f);
3276 checkGLcall("glPolygonOffset(0, -Value)");
3277 glEnable(GL_POLYGON_OFFSET_FILL);
3278 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3279 glEnable(GL_POLYGON_OFFSET_LINE);
3280 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3281 glEnable(GL_POLYGON_OFFSET_POINT);
3282 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3284 glDisable(GL_POLYGON_OFFSET_FILL);
3285 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3286 glDisable(GL_POLYGON_OFFSET_LINE);
3287 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3288 glDisable(GL_POLYGON_OFFSET_POINT);
3289 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3294 case WINED3DRS_NORMALIZENORMALS :
3296 glEnable(GL_NORMALIZE);
3297 checkGLcall("glEnable(GL_NORMALIZE);");
3299 glDisable(GL_NORMALIZE);
3300 checkGLcall("glDisable(GL_NORMALIZE);");
3304 case WINED3DRS_POINTSIZE :
3305 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
3307 TRACE("Set point size to %f\n", tmpvalue.f);
3308 glPointSize(tmpvalue.f);
3309 checkGLcall("glPointSize(...);");
3312 case WINED3DRS_POINTSIZE_MIN :
3313 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3315 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3316 checkGLcall("glPointParameterfEXT(...);");
3318 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3322 case WINED3DRS_POINTSIZE_MAX :
3323 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3325 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3326 checkGLcall("glPointParameterfEXT(...);");
3328 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3332 case WINED3DRS_POINTSCALE_A :
3333 case WINED3DRS_POINTSCALE_B :
3334 case WINED3DRS_POINTSCALE_C :
3335 case WINED3DRS_POINTSCALEENABLE :
3337 /* If enabled, supply the parameters, otherwise fall back to defaults */
3338 if (This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3339 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3340 /* TODO: Correct the scaling (this hack seems to be good enough for every demo that uses point sprites!) */
3341 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A])/ This->stateBlock->viewport.Width;
3342 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B])/ This->stateBlock->viewport.Height;
3343 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) *
3344 2.0f /(This->stateBlock->viewport.Width * This->stateBlock->viewport.Height);
3346 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3347 TRACE("glPointParameterfvARB %f %f %f\n", att[0], att[1], att[2]);
3348 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3349 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3351 TRACE("WINED3DRS_POINTSCALEENABLE not supported on this opengl\n");
3354 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3355 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3356 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3357 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3359 TRACE("WINED3DRS_POINTSCALEENABLE not supported, but not on either\n");
3365 case WINED3DRS_COLORWRITEENABLE :
3367 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3368 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3369 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3370 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3371 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3372 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3373 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3374 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3375 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3376 checkGLcall("glColorMask(...)");
3380 case WINED3DRS_LOCALVIEWER :
3382 GLint state = (Value) ? 1 : 0;
3383 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3384 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3388 case WINED3DRS_LASTPIXEL :
3391 TRACE("Last Pixel Drawing Enabled\n");
3393 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3398 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3401 TRACE("Software Processing Enabled\n");
3403 TRACE("Software Processing Disabled\n");
3408 /** not supported */
3409 case WINED3DRS_ZVISIBLE :
3412 return D3DERR_INVALIDCALL;
3414 case WINED3DRS_POINTSPRITEENABLE :
3415 /* TODO: NV_POINT_SPRITE */
3416 if (GL_SUPPORT(ARB_POINT_SPRITE)) {
3417 if (Value != FALSE) {
3418 /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
3419 glDisable(GL_POINT_SMOOTH);
3420 /* Centre the texture on the vertex */
3421 VTRACE("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
3422 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
3424 VTRACE("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
3425 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
3426 checkGLcall("glTexEnvf(...)");
3427 VTRACE("glEnable( GL_POINT_SPRITE_ARB )\n");
3428 glEnable( GL_POINT_SPRITE_ARB );
3429 checkGLcall("glEnable(...)");
3431 VTRACE("glDisable( GL_POINT_SPRITE_ARB )\n");
3432 glDisable( GL_POINT_SPRITE_ARB );
3433 checkGLcall("glEnable(...)");
3437 /* Unhandled yet...! */
3438 case WINED3DRS_EDGEANTIALIAS :
3439 case WINED3DRS_WRAP0 :
3440 case WINED3DRS_WRAP1 :
3441 case WINED3DRS_WRAP2 :
3442 case WINED3DRS_WRAP3 :
3443 case WINED3DRS_WRAP4 :
3444 case WINED3DRS_WRAP5 :
3445 case WINED3DRS_WRAP6 :
3446 case WINED3DRS_WRAP7 :
3448 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
3449 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
3450 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
3451 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
3452 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
3454 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
3456 TRACE("(%p)->(%d,%ld) Texture wraping not yet supported\n",This, State, Value);
3458 case WINED3DRS_MULTISAMPLEANTIALIAS :
3459 case WINED3DRS_MULTISAMPLEMASK :
3460 case WINED3DRS_PATCHEDGESTYLE :
3461 case WINED3DRS_PATCHSEGMENTS :
3462 case WINED3DRS_DEBUGMONITORTOKEN :
3463 case WINED3DRS_POSITIONORDER :
3464 case WINED3DRS_NORMALORDER :
3465 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3466 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3469 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3477 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3478 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3479 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3480 *pValue = This->stateBlock->renderState[State];
3485 * Get / Set Sampler States
3486 * TODO: Verify against dx9 definitions
3489 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3490 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3492 * SetSampler is designed to allow for more than the standard up to 8 textures
3493 * and Geforce has stopped supporting more than 6 standard textures in openGL.
3494 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3496 * http://developer.nvidia.com/object/General_FAQ.html#t6
3498 * There are two new settings for GForce
3500 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3501 * and the texture one:
3502 * GL_MAX_TEXTURE_COORDS_ARB.
3503 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3505 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
3506 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
3508 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
3509 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE, Sampler, Type);
3510 return D3DERR_INVALIDCALL;
3512 TRACE("Setting sampler %ld %d to %ld \n", Sampler, Type, Value);
3513 This->updateStateBlock->samplerState[Sampler][Type] = Value;
3514 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
3515 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
3517 /* Handle recording of state blocks */
3518 if (This->isRecordingState) {
3519 TRACE("Recording... not performing anything\n");
3526 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3527 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3528 /** TODO: check that sampler is in range **/
3529 *Value = This->updateStateBlock->samplerState[Sampler][Type];
3530 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
3535 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3536 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3539 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3540 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3541 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3547 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3548 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3549 GLint scissorBox[4];
3552 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3553 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
3554 pRect->left = scissorBox[1];
3555 pRect->top = scissorBox[2];
3556 pRect->right = scissorBox[1] + scissorBox[3];
3557 pRect->bottom = scissorBox[2] + scissorBox[4];
3558 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3563 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3564 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3566 TRACE("(%p) : pDecl=%p\n", This, pDecl);
3568 /* TODO: what about recording stateblocks? */
3569 if (NULL != pDecl) {
3570 IWineD3DVertexDeclaration_AddRef(pDecl);
3572 if (NULL != This->updateStateBlock->vertexDecl) {
3573 IWineD3DVertexDeclaration_Release(This->updateStateBlock->vertexDecl);
3575 This->updateStateBlock->vertexDecl = pDecl;
3576 This->updateStateBlock->changed.vertexDecl = TRUE;
3577 This->updateStateBlock->set.vertexDecl = TRUE;
3581 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3582 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3584 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3586 *ppDecl = This->updateStateBlock->vertexDecl;
3587 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3591 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
3592 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3593 IWineD3DVertexShader *oldShader = This->updateStateBlock->vertexShader;
3595 This->updateStateBlock->vertexShader = pShader;
3596 This->updateStateBlock->changed.vertexShader = TRUE;
3597 This->updateStateBlock->set.vertexShader = TRUE;
3599 if (This->isRecordingState) {
3600 TRACE("Recording... not performing anything\n");
3604 if (pShader != NULL) {
3605 IUnknown *newVertexShaderParent;
3606 /* GetParent will add a ref, so leave it hanging until the vertex buffer is cleared */
3607 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3608 IWineD3DVertexShader_GetParent(pShader, &newVertexShaderParent);
3610 TRACE("Clear down the shader\n");
3612 if (oldShader != NULL) {
3613 IUnknown *oldVertexShaderParent;
3614 IWineD3DVertexShader_GetParent(oldShader, &oldVertexShaderParent);
3615 IUnknown_Release(oldVertexShaderParent);
3616 IUnknown_Release(oldVertexShaderParent);
3619 * TODO: merge HAL shaders context switching from prototype
3624 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
3625 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3627 if (NULL == ppShader) {
3628 return D3DERR_INVALIDCALL;
3630 *ppShader = This->stateBlock->vertexShader;
3631 if( NULL != *ppShader)
3632 IWineD3DVertexShader_AddRef(*ppShader);
3634 TRACE("(%p) : returning %p\n", This, *ppShader);
3638 #define GET_SHADER_CONSTANT(_vertexshaderconstant, _count, _sizecount) \
3639 int count = min(_count, MAX_VSHADER_CONSTANTS - (StartRegister + 1)); \
3640 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3641 return D3DERR_INVALIDCALL; \
3642 memcpy(pConstantData, This->updateStateBlock->_vertexshaderconstant + (StartRegister * _sizecount), count * (sizeof(*pConstantData) * _sizecount));
3644 #define SET_SHADER_CONSTANT(_vertexshaderconstant, _count, _sizecount) \
3645 int count = min(_count, MAX_VSHADER_CONSTANTS - (StartRegister + 1)); \
3646 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3647 return D3DERR_INVALIDCALL; \
3648 memcpy(This->updateStateBlock->_vertexshaderconstant + (StartRegister * _sizecount), pConstantData, count * (sizeof(*pConstantData) * _sizecount)); \
3649 This->updateStateBlock->changed.vertexShader = TRUE; \
3650 This->updateStateBlock->set.vertexShader = TRUE;
3652 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
3653 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3654 static BOOL showFixmes = TRUE;
3655 SET_SHADER_CONSTANT(vertexShaderConstantB, BoolCount, 1);
3656 #if 0 /* TODO: a bitmasp to say which constant type we should load */
3657 memset(This->updateStateBlock->vsibfBitmap + StartRegister, WINESHADER_CONSTANTB, BoolCount);
3659 /* clean out the other constants? */
3660 if(showFixmes || TRUE) {
3661 FIXME("(%p) : stub\n", This);
3667 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
3668 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3669 static BOOL showFixmes = TRUE;
3670 #if 0 /* TODO: a bitmasp to say which constant type we should load */
3671 for (i = 0; i < BoolCount; i++ ) {
3672 if (This->updateStateBlock->vsibfBitmap[StartRegister + i] != WINESHADER_CONSTANTB) {
3673 /* the constant for this register isn't a boolean */
3674 return D3DERR_INVALIDCALL;
3678 GET_SHADER_CONSTANT(vertexShaderConstantB, BoolCount, 1);
3679 if(showFixmes || TRUE) {
3680 FIXME("(%p) : stub\n", This);
3686 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
3687 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3688 static BOOL showFixmes = TRUE;
3689 #if 0 /* TODO: a bitmasp to say which constant type we should load */
3690 memset(This->updateStateBlock->vsibfBitmap + StartRegister, WINESHADER_CONSTANTI, Vector4iCount);
3692 SET_SHADER_CONSTANT(vertexShaderConstantI, Vector4iCount, 4);
3693 /* clean out the other constants? */
3694 if(showFixmes || TRUE) {
3695 FIXME("(%p) : stub\n", This);
3701 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
3702 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3703 static BOOL showFixmes = TRUE;
3704 #if 0 /* TODO: a bitmap to say which constant type we should load */
3705 for (i = 0; i < Vector4iCount; i++ ) {
3706 if (This->updateStateBlock->vsibfBitmap[StartRegister + i] != WINESHADER_CONSTANTI) {
3707 /* the constant for this register isn't a boolean */
3708 return D3DERR_INVALIDCALL;
3712 GET_SHADER_CONSTANT(vertexShaderConstantI, Vector4iCount, 4);
3713 if(showFixmes || TRUE) {
3714 FIXME("(%p) : stub\n", This);
3720 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
3721 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3722 static BOOL showFixmes = TRUE;
3723 #if 0 /* TODO: a bitmasp to say which constant type we should load */
3724 memset(This->updateStateBlock->vsibfBitmap + StartRegister, WINESHADER_CONSTANTF, Vector4fCount);
3726 SET_SHADER_CONSTANT(vertexShaderConstantF, Vector4fCount, 4);
3727 /* clean out the other constants? */
3729 TRACE("(%p) : ConstantF isn't intergrated properly with the other constants.\n", This);
3735 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
3736 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3737 static BOOL showFixmes = TRUE;
3738 #if 0 /* TODO: a bitmap to say which constant type we should load */
3739 for (i = 0; i < Vector4fCount; i++ ) {
3740 if (This->updateStateBlock->vsibfBitmap[StartRegister + i] != WINESHADER_CONSTANTF) {
3741 /* the constant for this register isn't a boolean */
3742 return D3DERR_INVALIDCALL;
3746 GET_SHADER_CONSTANT(vertexShaderConstantF, Vector4fCount, 4);
3748 TRACE("(%p) : ConstantF isn't intergrated properly with the other constants.\n", This);
3754 #undef SET_SHADER_CONSTANT
3755 #undef GET_SHADER_CONSTANT
3758 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
3760 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3761 IWineD3DPixelShader *oldpShader = This->updateStateBlock->pixelShader;
3762 static BOOL showFixmes = TRUE;
3764 /** FIXME: reference counting? **/
3765 This->updateStateBlock->pixelShader = pShader;
3766 This->updateStateBlock->changed.pixelShader = TRUE;
3767 This->updateStateBlock->set.pixelShader = TRUE;
3769 if (pShader == NULL) {
3770 /* clear down the shader */
3771 TRACE("Clear down the shader\n");
3774 FIXME("(%p) : stub pShader(%p)\n", This, pShader);
3779 /* Handle recording of state blocks */
3780 if (This->isRecordingState) {
3781 TRACE("Recording... not performing anything\n");
3785 * TODO: merge HAL shaders context switching from prototype
3788 /* manage reference counting. */
3789 if (pShader != NULL) {
3790 IWineD3DPixelShader_GetParent(pShader, &parent); /* get parent adds a ref for us*/
3793 if (oldpShader != NULL) {
3794 IWineD3DPixelShader_GetParent(oldpShader, &parent);
3795 IUnknown_Release(parent); /* once for the getparent */
3796 IUnknown_Release(parent); /* and once for the ref */
3804 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3805 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3807 if (ppShader == NULL) {
3808 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
3809 return D3DERR_INVALIDCALL;
3812 *ppShader = This->updateStateBlock->pixelShader;
3813 if (NULL != ppShader) {
3814 IWineD3DPixelShader_AddRef(*ppShader);
3816 TRACE("(%p) : returning %p\n", This, *ppShader);
3820 #define GET_SHADER_CONSTANT(_pixelshaderconstant, _count, _sizecount) \
3821 int count = min(_count, MAX_PSHADER_CONSTANTS - (StartRegister + 1)); \
3822 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3823 return D3DERR_INVALIDCALL; \
3824 memcpy(pConstantData, This->updateStateBlock->_pixelshaderconstant + (StartRegister * _sizecount), count * (sizeof(*pConstantData) * _sizecount)); \
3827 #define SET_SHADER_CONSTANT(_pixelshaderconstant, _count, _sizecount) \
3828 int count = min(_count, MAX_PSHADER_CONSTANTS - (StartRegister + 1)); \
3829 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3830 return D3DERR_INVALIDCALL; \
3831 memcpy(This->updateStateBlock->_pixelshaderconstant + (StartRegister * _sizecount), pConstantData, count * (sizeof(*pConstantData) * _sizecount)); \
3832 This->updateStateBlock->changed.pixelShader = TRUE; \
3833 This->updateStateBlock->set.pixelShader = TRUE;
3836 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
3837 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3838 static BOOL showFixmes = TRUE;
3839 SET_SHADER_CONSTANT(pixelShaderConstantB, BoolCount, 1);
3841 FIXME("(%p) : stub\n", This);
3848 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
3849 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3850 static BOOL showFixmes = TRUE;
3851 GET_SHADER_CONSTANT(pixelShaderConstantB, BoolCount, 1);
3853 FIXME("(%p) : stub\n", This);
3859 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
3860 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3861 static BOOL showFixmes = TRUE;
3862 SET_SHADER_CONSTANT(pixelShaderConstantI, Vector4iCount, 4);
3864 FIXME("(%p) : stub\n", This);
3870 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
3871 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3872 static BOOL showFixmes = TRUE;
3873 GET_SHADER_CONSTANT(pixelShaderConstantI, Vector4iCount, 4);
3875 FIXME("(%p) : stub\n", This);
3881 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
3882 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3883 static BOOL showFixmes = TRUE;
3884 SET_SHADER_CONSTANT(pixelShaderConstantF, Vector4fCount, 4);
3886 FIXME("(%p) : stub\n", This);
3892 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
3893 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3894 static BOOL showFixmes = TRUE;
3895 GET_SHADER_CONSTANT(pixelShaderConstantF, Vector4fCount, 4);
3897 FIXME("(%p) : stub\n", This);
3903 #undef SET_SHADER_CONSTANT
3904 #undef GET_SHADER_CONSTANT
3906 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
3907 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3908 FIXME("(%p) : stub\n", This);
3913 * Apply / Get / Set Texture Stage States
3914 * TODO: Verify against dx9 definitions
3917 /* 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 callnig ApplyTextureStageState */
3918 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
3919 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3920 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
3921 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3923 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3925 /* Check that the stage is within limits */
3926 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
3927 TRACE("Attempt to access invalid texture rejected\n");
3934 case WINED3DTSS_ALPHAOP :
3935 case WINED3DTSS_COLOROP :
3936 /* nothing to do as moved to drawprim for now */
3938 case WINED3DTSS_ADDRESSW :
3939 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
3940 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
3941 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3944 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
3945 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
3946 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3947 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3950 case WINED3DTSS_TEXCOORDINDEX :
3952 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3954 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
3955 one flag, you can still specify an index value, which the system uses to
3956 determine the texture wrapping mode.
3957 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3958 means use the vertex position (camera-space) as the input texture coordinates
3959 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
3960 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3961 to the TEXCOORDINDEX value */
3964 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3966 switch (Value & 0xFFFF0000) {
3967 case D3DTSS_TCI_PASSTHRU:
3968 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3969 glDisable(GL_TEXTURE_GEN_S);
3970 glDisable(GL_TEXTURE_GEN_T);
3971 glDisable(GL_TEXTURE_GEN_R);
3972 glDisable(GL_TEXTURE_GEN_Q);
3973 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
3976 case D3DTSS_TCI_CAMERASPACEPOSITION:
3977 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3978 as the input texture coordinates for this stage's texture transformation. This
3979 equates roughly to EYE_LINEAR */
3981 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3982 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3983 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3984 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3985 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3987 glMatrixMode(GL_MODELVIEW);
3990 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3991 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3992 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3993 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3996 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3997 glEnable(GL_TEXTURE_GEN_S);
3998 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3999 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4000 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4001 glEnable(GL_TEXTURE_GEN_T);
4002 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4003 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4004 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4005 glEnable(GL_TEXTURE_GEN_R);
4006 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4007 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4008 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4012 case D3DTSS_TCI_CAMERASPACENORMAL:
4014 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4015 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4016 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4017 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4018 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4019 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
4021 glMatrixMode(GL_MODELVIEW);
4024 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4025 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4026 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4027 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4030 glEnable(GL_TEXTURE_GEN_S);
4031 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4032 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4033 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4034 glEnable(GL_TEXTURE_GEN_T);
4035 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4036 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4037 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4038 glEnable(GL_TEXTURE_GEN_R);
4039 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4040 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4041 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4046 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
4048 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4049 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4050 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4051 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4052 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4053 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
4055 glMatrixMode(GL_MODELVIEW);
4058 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4059 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4060 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4061 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4064 glEnable(GL_TEXTURE_GEN_S);
4065 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4066 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4067 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4068 glEnable(GL_TEXTURE_GEN_T);
4069 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4070 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4071 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4072 glEnable(GL_TEXTURE_GEN_R);
4073 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4074 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4075 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4080 /* Unhandled types: */
4083 /* ? disable GL_TEXTURE_GEN_n ? */
4084 glDisable(GL_TEXTURE_GEN_S);
4085 glDisable(GL_TEXTURE_GEN_T);
4086 glDisable(GL_TEXTURE_GEN_R);
4087 glDisable(GL_TEXTURE_GEN_Q);
4088 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
4095 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
4096 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);
4099 case WINED3DTSS_BUMPENVMAT00 :
4100 case WINED3DTSS_BUMPENVMAT01 :
4101 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
4103 case WINED3DTSS_BUMPENVMAT10 :
4104 case WINED3DTSS_BUMPENVMAT11 :
4105 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
4108 case WINED3DTSS_BUMPENVLSCALE :
4109 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4112 case WINED3DTSS_BUMPENVLOFFSET :
4113 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4116 case WINED3DTSS_RESULTARG :
4117 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4121 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
4122 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4131 * Get / Set Texture Stage States
4132 * TODO: Verify against dx9 definitions
4134 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
4135 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4137 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4139 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4141 /* Reject invalid texture units */
4142 if (Stage >= GL_LIMITS(textures)) {
4143 TRACE("Attempt to access invalid texture rejected\n");
4144 return D3DERR_INVALIDCALL;
4147 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
4148 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
4149 This->updateStateBlock->textureState[Stage][Type] = Value;
4154 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4155 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4156 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4157 *pValue = This->updateStateBlock->textureState[Stage][Type];
4164 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4166 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4167 IWineD3DBaseTexture *oldTexture;
4169 oldTexture = This->updateStateBlock->textures[Stage];
4170 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
4172 #if 0 /* TODO: check so vertex textures */
4173 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
4174 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
4179 /* Reject invalid texture units */
4180 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4181 WARN("Attempt to access invalid texture rejected\n");
4182 return D3DERR_INVALIDCALL;
4185 oldTexture = This->updateStateBlock->textures[Stage];
4186 TRACE("GL_LIMITS %d\n",GL_LIMITS(textures));
4187 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
4189 This->updateStateBlock->set.textures[Stage] = TRUE;
4190 This->updateStateBlock->changed.textures[Stage] = TRUE;
4191 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
4192 This->updateStateBlock->textures[Stage] = pTexture;
4194 /* Handle recording of state blocks */
4195 if (This->isRecordingState) {
4196 TRACE("Recording... not performing anything\n");
4200 /** NOTE: MSDN says that setTexture increases the reference count,
4201 * and the the application nust set the texture back to null (or have a leaky application),
4202 * This means we should pass the refcount upto the parent
4203 *******************************/
4204 if (NULL != This->updateStateBlock->textures[Stage]) {
4205 IUnknown *textureParent;
4206 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[Stage], (IUnknown **)&textureParent);
4207 /** NOTE: GetParent will increase the ref count for me, I won't clean up until the texture is set to NULL **/
4210 if (NULL != oldTexture) {
4211 IUnknown *textureParent;
4212 IWineD3DBaseTexture_GetParent(oldTexture, (IUnknown **)&textureParent);
4213 IUnknown_Release(textureParent);
4214 IUnknown_Release(textureParent); /** NOTE: Twice because GetParent adds a ref **/
4221 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4222 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4223 TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */) \n", This, Stage, ppTexture);
4225 /* Reject invalid texture units */
4226 if (Stage >= GL_LIMITS(textures)) {
4227 TRACE("Attempt to access invalid texture rejected\n");
4228 return D3DERR_INVALIDCALL;
4230 *ppTexture=This->updateStateBlock->textures[Stage];
4232 IWineD3DBaseTexture_AddRef(*ppTexture);
4234 return D3DERR_INVALIDCALL;
4241 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type,
4242 IWineD3DSurface **ppBackBuffer) {
4243 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4244 IWineD3DSwapChain *swapChain;
4247 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4249 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4251 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4252 IWineD3DSwapChain_Release(swapChain);
4254 *ppBackBuffer = NULL;
4259 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4260 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4261 WARN("(%p) : stub, calling idirect3d for now\n", This);
4262 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4265 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
4266 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4267 IWineD3DSwapChain *swapChain;
4270 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4272 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4273 IWineD3DSwapChain_Release(swapChain);
4275 FIXME("(%p) Error getting display mode\n", This);
4280 * Stateblock related functions
4283 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4284 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4285 IWineD3DStateBlockImpl *object;
4286 TRACE("(%p)", This);
4287 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4288 if (NULL == object ) {
4289 FIXME("(%p)Error allocating memory for stateblock\n", This);
4290 return E_OUTOFMEMORY;
4292 TRACE("(%p) creted object %p\n", This, object);
4293 object->wineD3DDevice= This;
4294 /** FIXME: object->parent = parent; **/
4295 object->parent = NULL;
4296 object->blockType = WINED3DSBT_ALL;
4298 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
4300 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4301 This->updateStateBlock = object;
4302 This->isRecordingState = TRUE;
4304 TRACE("(%p) recording stateblock %p\n",This , object);
4308 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4309 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4311 if (!This->isRecordingState) {
4312 FIXME("(%p) not recording! returning error\n", This);
4313 *ppStateBlock = NULL;
4314 return D3DERR_INVALIDCALL;
4317 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4318 This->isRecordingState = FALSE;
4319 This->updateStateBlock = This->stateBlock;
4320 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4321 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4322 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4327 * Scene related functions
4329 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4330 /* At the moment we have no need for any functionality at the beginning
4332 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4333 TRACE("(%p) : stub\n", This);
4337 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4338 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4339 TRACE("(%p)\n", This);
4341 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4343 checkGLcall("glFlush");
4345 TRACE("End Scene\n");
4346 if(This->renderTarget != NULL) {
4348 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4349 IUnknown *targetContainer = NULL;
4350 if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
4351 || D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
4352 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
4353 /** always dirtify for now. we must find a better way to see that surface have been modified
4354 (Modifications should will only occur via draw-primitive, but we do need better locking
4355 switching to render-to-texture should remove the overhead though.
4357 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4358 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
4359 IWineD3DSurface_PreLoad(This->renderTarget);
4360 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4361 IUnknown_Release(targetContainer);
4364 This->sceneEnded = TRUE;
4369 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4370 CONST RECT* pSourceRect, CONST RECT* pDestRect,
4371 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4372 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4373 IWineD3DSwapChain *swapChain = NULL;
4375 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4377 TRACE("(%p) Presenting the frame\n", This);
4379 for(i = 0 ; i < swapchains ; i ++) {
4381 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4382 TRACE("presentinng chain %d, %p\n", i, swapChain);
4383 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4384 IWineD3DSwapChain_Release(swapChain);
4390 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4391 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4392 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4394 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4395 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4396 when the depth-buffer format does not contain stencil buffer information, this method fails. */
4397 GLbitfield glMask = 0;
4398 GLboolean old_ztest;
4399 GLfloat old_z_clear_value;
4400 GLint old_stencil_clear_value;
4401 GLfloat old_color_clear_value[4];
4403 CONST D3DRECT* curRect;
4405 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4406 Count, pRects, Flags, Z, Stencil);
4410 glEnable(GL_SCISSOR_TEST);
4411 checkGLcall("glEnable GL_SCISSOR_TEST");
4413 if (Count > 0 && pRects) {
4419 /* Only set the values up once, as they are not changing */
4420 if (Flags & D3DCLEAR_STENCIL) {
4421 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4422 glClearStencil(Stencil);
4423 checkGLcall("glClearStencil");
4424 glMask = glMask | GL_STENCIL_BUFFER_BIT;
4425 glStencilMask(0xFFFFFFFF);
4428 if (Flags & D3DCLEAR_ZBUFFER) {
4429 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4430 glDepthMask(GL_TRUE);
4431 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4433 checkGLcall("glClearDepth");
4434 glMask = glMask | GL_DEPTH_BUFFER_BIT;
4437 if (Flags & D3DCLEAR_TARGET) {
4438 TRACE("Clearing screen with glClear to color %lx\n", Color);
4439 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4440 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
4441 ((Color >> 8) & 0xFF) / 255.0f,
4442 ((Color >> 0) & 0xFF) / 255.0f,
4443 ((Color >> 24) & 0xFF) / 255.0f);
4444 checkGLcall("glClearColor");
4446 /* Clear ALL colors! */
4447 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4448 glMask = glMask | GL_COLOR_BUFFER_BIT;
4451 /* Now process each rect in turn */
4452 for (i = 0; i < Count || i == 0; i++) {
4455 /* Note gl uses lower left, width/height */
4456 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4457 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4458 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4459 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4460 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4461 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4462 checkGLcall("glScissor");
4464 glScissor(This->stateBlock->viewport.X,
4465 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
4466 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4467 This->stateBlock->viewport.Width,
4468 This->stateBlock->viewport.Height);
4469 checkGLcall("glScissor");
4472 /* Clear the selected rectangle (or full screen) */
4474 checkGLcall("glClear");
4476 /* Step to the next rectangle */
4477 if (curRect) curRect = curRect + sizeof(D3DRECT);
4480 /* Restore the old values (why..?) */
4481 if (Flags & D3DCLEAR_STENCIL) {
4482 glClearStencil(old_stencil_clear_value);
4483 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4485 if (Flags & D3DCLEAR_ZBUFFER) {
4486 glDepthMask(old_ztest);
4487 glClearDepth(old_z_clear_value);
4489 if (Flags & D3DCLEAR_TARGET) {
4490 glClearColor(old_color_clear_value[0],
4491 old_color_clear_value[1],
4492 old_color_clear_value[2],
4493 old_color_clear_value[3]);
4494 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4495 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4496 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4497 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4500 glDisable(GL_SCISSOR_TEST);
4501 checkGLcall("glDisable");
4510 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4511 UINT PrimitiveCount) {
4513 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4514 This->stateBlock->streamIsUP = FALSE;
4516 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4517 debug_d3dprimitivetype(PrimitiveType),
4518 StartVertex, PrimitiveCount);
4519 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
4520 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
4526 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4527 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4528 D3DPRIMITIVETYPE PrimitiveType,
4529 INT baseVIndex, UINT minIndex,
4530 UINT NumVertices, UINT startIndex, UINT primCount) {
4532 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4534 IWineD3DIndexBuffer *pIB;
4535 D3DINDEXBUFFER_DESC IdxBufDsc;
4537 pIB = This->stateBlock->pIndexData;
4538 This->stateBlock->streamIsUP = FALSE;
4540 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d \n", This,
4541 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4542 minIndex, NumVertices, startIndex, baseVIndex, primCount);
4544 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4545 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4551 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
4552 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
4557 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4558 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4559 UINT VertexStreamZeroStride) {
4560 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4562 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4563 debug_d3dprimitivetype(PrimitiveType),
4564 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4566 if (This->stateBlock->streamSource[0] != NULL) {
4567 IUnknown *vertexBufferParent;
4568 IWineD3DVertexBuffer_GetParent(This->stateBlock->streamSource[0], &vertexBufferParent);
4569 IUnknown_Release(vertexBufferParent);
4570 IUnknown_Release(vertexBufferParent);
4573 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4574 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4575 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4576 This->stateBlock->streamIsUP = TRUE;
4578 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
4579 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
4580 /* stream zero settings set to null at end, as per the msdn
4581 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
4583 This->stateBlock->streamStride[0] = 0;
4584 This->stateBlock->streamSource[0] = NULL;
4586 /*stream zero settings set to null at end, as per the msdn */
4590 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4591 UINT MinVertexIndex, UINT NumVertices,
4592 UINT PrimitiveCount, CONST void* pIndexData,
4593 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4594 UINT VertexStreamZeroStride) {
4596 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4598 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4599 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4600 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
4601 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4603 if (IndexDataFormat == WINED3DFMT_INDEX16) {
4609 if (This->stateBlock->streamSource[0] != NULL) {
4610 IUnknown *vertexBufferParent;
4611 IWineD3DVertexBuffer_GetParent(This->stateBlock->streamSource[0], &vertexBufferParent);
4612 This->stateBlock->streamSource[0] = NULL;
4613 IUnknown_Release(vertexBufferParent);
4614 IUnknown_Release(vertexBufferParent);
4617 if (This->stateBlock->pIndexData) {
4618 IUnknown *indexBufferParent;
4619 IWineD3DIndexBuffer_GetParent(This->stateBlock->pIndexData, &indexBufferParent);
4620 This->stateBlock->pIndexData = NULL;
4621 IUnknown_Release(indexBufferParent);
4622 IUnknown_Release(indexBufferParent);
4625 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4626 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4627 This->stateBlock->streamIsUP = TRUE;
4628 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4630 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
4631 /* stream zero settings set to null at end as per the msdn
4632 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
4635 /* stream zero settings set to null at end as per the msdn */
4636 This->stateBlock->streamSource[0] = NULL;
4637 This->stateBlock->streamStride[0] = 0;
4642 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4643 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
4644 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4645 D3DRESOURCETYPE sourceType;
4646 D3DRESOURCETYPE destinationType;
4647 IWineD3DTextureImpl *pDestTexture = (IWineD3DTextureImpl *)pDestinationTexture;
4648 IWineD3DTextureImpl *pSrcTexture = (IWineD3DTextureImpl *)pSourceTexture;
4651 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
4652 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
4653 if(sourceType != D3DRTYPE_TEXTURE && destinationType != D3DRTYPE_TEXTURE){
4654 FIXME("(%p) Only D3DRTYPE_TEXTURE to D3DRTYPE_TEXTURE supported\n", This);
4655 return D3DERR_INVALIDCALL;
4657 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
4659 /** TODO: Get rid of the casts to IWineD3DBaseTextureImpl
4660 repalce surfaces[x] with GetSurfaceLevel, or GetCubeMapSurface etc..
4661 think about moving the code into texture, and adding a member to base texture to occomplish this **/
4663 /* Make sure that the destination texture is loaded */
4664 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
4665 TRACE("Loading source texture\n");
4667 if(pSrcTexture->surfaces[0] == NULL || pDestTexture->surfaces[0] == NULL){
4668 FIXME("(%p) Texture src %p or dest %p has not surface %p %p\n", This, pSrcTexture, pDestTexture,
4669 pSrcTexture->surfaces[0], pDestTexture->surfaces[0]);
4672 if(((IWineD3DSurfaceImpl *)pSrcTexture->surfaces[0])->resource.pool != D3DPOOL_SYSTEMMEM ||
4673 ((IWineD3DSurfaceImpl *)pDestTexture->surfaces[0])->resource.pool != D3DPOOL_DEFAULT){
4675 FIXME("(%p) source %p must be SYSTEMMEM and dest %p must be DEFAULT\n",This, pSrcTexture, pDestTexture);
4676 return D3DERR_INVALIDCALL;
4678 /** TODO: check that both textures have the same number of levels **/
4680 if(IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) !=IWineD3DBaseTexture_GetLevelCount(pSourceTexture))
4681 return D3DERR_INVALIDCALL;
4683 /** TODO: move this code into baseTexture? device should never touch impl*'s **/
4684 for(i = 0 ; i < IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) ; i++){
4685 IWineD3DDevice_UpdateSurface(iface, pSrcTexture->surfaces[i], NULL, pDestTexture->surfaces[i], NULL);
4691 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
4692 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
4693 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
4694 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4696 TRACE("(%p) : stub\n", This);
4699 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
4700 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4701 /** TODO: remove remove casts to IWineD3DSurfaceImpl *
4702 * NOTE It may be best to move the code into surface to occomplish this
4703 ****************************************/
4705 WINED3DSURFACE_DESC surfaceDesc;
4706 unsigned int surfaceWidth, surfaceHeight;
4707 glDescriptor *targetGlDescription = NULL;
4708 glDescriptor *surfaceGlDescription = NULL;
4709 IWineD3DSwapChainImpl *container = NULL;
4711 IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
4712 IWineD3DSurface_GetGlDesc(pSurface, &surfaceGlDescription);
4713 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
4715 surfaceDesc.Width = &surfaceWidth;
4716 surfaceDesc.Height = &surfaceHeight;
4717 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
4718 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sureteh data is upto date)*/
4720 /* Ok, I may need to setup some kind of active swapchain reference on the device */
4721 IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
4723 /* TODO: opengl Context switching for swapchains etc... */
4724 if (NULL != container || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
4725 if (NULL != container && (pRenderTarget == container->backBuffer)) {
4726 glReadBuffer(GL_BACK);
4727 vcheckGLcall("glReadBuffer(GL_BACK)");
4728 } else if ((NULL != container && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
4729 glReadBuffer(GL_FRONT);
4730 vcheckGLcall("glReadBuffer(GL_FRONT)");
4731 } else if (pRenderTarget == This->depthStencilBuffer) {
4732 FIXME("Reading of depthstencil not yet supported\n");
4735 glReadPixels(surfaceGlDescription->target,
4736 surfaceGlDescription->level,
4739 surfaceGlDescription->glFormat,
4740 surfaceGlDescription->glType,
4741 (void *)IWineD3DSurface_GetData(pSurface));
4742 vcheckGLcall("glReadPixels(...)");
4743 if(NULL != container ){
4744 IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
4747 IWineD3DBaseTexture *container;
4748 GLenum textureDimensions = GL_TEXTURE_2D;
4750 if (D3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
4751 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
4752 IWineD3DBaseTexture_Release(container);
4754 /* TODO: 2D -> Cube surface coppies etc.. */
4755 if (surfaceGlDescription->target != textureDimensions) {
4756 FIXME("(%p) : Texture dimension mismatch\n", This);
4758 glEnable(textureDimensions);
4759 vcheckGLcall("glEnable(GL_TEXTURE_...)");
4760 /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
4761 glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
4762 vcheckGLcall("glBindTexture");
4763 glGetTexImage(surfaceGlDescription->target,
4764 surfaceGlDescription->level,
4765 surfaceGlDescription->glFormat,
4766 surfaceGlDescription->glType,
4767 (void *)IWineD3DSurface_GetData(pSurface));
4768 glDisable(textureDimensions);
4769 vcheckGLcall("glDisable(GL_TEXTURE_...)");
4776 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
4777 IWineD3DSwapChain *swapChain;
4779 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4781 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
4782 IWineD3DSwapChain_Release(swapChain);
4787 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4788 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4789 /* return a sensible default */
4791 /* TODO: If the window is minimized then validate device shold return something other than d3d_ok */
4792 FIXME("(%p) : stub\n", This);
4796 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4797 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4799 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4800 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4801 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4802 return D3DERR_INVALIDCALL;
4804 for (j = 0; j < 256; ++j) {
4805 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
4806 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
4807 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
4808 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
4810 TRACE("(%p) : returning\n", This);
4814 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4815 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4817 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4818 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4819 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4820 return D3DERR_INVALIDCALL;
4822 for (j = 0; j < 256; ++j) {
4823 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
4824 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
4825 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
4826 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
4828 TRACE("(%p) : returning\n", This);
4832 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4833 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4834 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4835 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4836 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4837 return D3DERR_INVALIDCALL;
4839 /*TODO: stateblocks */
4840 This->currentPalette = PaletteNumber;
4841 TRACE("(%p) : returning\n", This);
4845 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4846 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4847 if (PaletteNumber == NULL) {
4848 WARN("(%p) : returning Invalid Call\n", This);
4849 return D3DERR_INVALIDCALL;
4851 /*TODO: stateblocks */
4852 *PaletteNumber = This->currentPalette;
4853 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
4857 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4858 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4859 static BOOL showFixmes = TRUE;
4861 FIXME("(%p) : stub\n", This);
4865 This->updateStateBlock->softwareVertexProcessing = bSoftware;
4870 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4871 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4872 static BOOL showFixmes = TRUE;
4874 FIXME("(%p) : stub\n", This);
4877 return This->updateStateBlock->softwareVertexProcessing;
4881 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
4882 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4883 IWineD3DSwapChain *swapChain;
4886 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
4888 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4890 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
4891 IWineD3DSwapChain_Release(swapChain);
4893 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error \n", This);
4899 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4900 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4901 static BOOL showfixmes = TRUE;
4902 if(nSegments != 0.0f) {
4904 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4911 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4912 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4913 static BOOL showfixmes = TRUE;
4915 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4922 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4923 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4924 /** TODO: remove casts to IWineD3DSurfaceImpl
4925 * NOTE: move code to surface to accomplish this
4926 ****************************************/
4927 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
4928 int srcWidth, srcHeight;
4929 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
4930 WINED3DFORMAT destFormat, srcFormat;
4932 int destLeft, destTop;
4933 D3DPOOL srcPool, destPool;
4935 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
4936 glDescriptor *glDescription = NULL;
4937 GLenum textureDimensions = GL_TEXTURE_2D;
4938 IWineD3DBaseTexture *baseTexture;
4940 WINED3DSURFACE_DESC winedesc;
4942 memset(&winedesc, 0, sizeof(winedesc));
4943 winedesc.Width = &srcSurfaceWidth;
4944 winedesc.Height = &srcSurfaceHeight;
4945 winedesc.Pool = &srcPool;
4946 winedesc.Format = &srcFormat;
4948 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
4950 winedesc.Width = &destSurfaceWidth;
4951 winedesc.Height = &destSurfaceHeight;
4952 winedesc.Pool = &destPool;
4953 winedesc.Format = &destFormat;
4954 winedesc.Size = &destSize;
4956 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
4958 if(srcPool != D3DPOOL_SYSTEMMEM || destPool != D3DPOOL_DEFAULT){
4959 FIXME("source %p must be SYSTEMMEM and dest %p must be DEFAULT\n", pSourceSurface, pDestinationSurface);
4960 return D3DERR_INVALIDCALL;
4962 /* TODO: change this to use bindTexture */
4963 /* Make sure the surface is loaded and upto date */
4964 IWineD3DSurface_PreLoad(pDestinationSurface);
4966 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
4970 /* this needs to be done in lines if the sourceRect != the sourceWidth */
4971 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
4972 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
4973 destLeft = pDestPoint ? pDestPoint->x : 0;
4974 destTop = pDestPoint ? pDestPoint->y : 0;
4977 /* This function doesn't support compressed textures
4978 the pitch is just bytesPerPixel * width */
4980 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
4981 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
4982 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
4983 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
4985 /* TODO DXT formats */
4987 if(pSourceRect != NULL && pSourceRect->top != 0){
4988 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
4990 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
4992 ,glDescription->level
4997 ,glDescription->glFormat
4998 ,glDescription->glType
4999 ,IWineD3DSurface_GetData(pSourceSurface)
5003 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
5004 /* need to lock the surface to get the data */
5005 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5007 /* TODO: Cube and volume support */
5009 /* not a whole row so we have to do it a line at a time */
5011 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
5012 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5014 for(j = destTop ; j < (srcHeight + destTop) ; j++){
5016 glTexSubImage2D(glDescription->target
5017 ,glDescription->level
5022 ,glDescription->glFormat
5023 ,glDescription->glType
5024 ,data/* could be quicker using */
5029 } else { /* Full width, so just write out the whole texture */
5031 if (WINED3DFMT_DXT1 == destFormat ||
5032 WINED3DFMT_DXT2 == destFormat ||
5033 WINED3DFMT_DXT3 == destFormat ||
5034 WINED3DFMT_DXT4 == destFormat ||
5035 WINED3DFMT_DXT5 == destFormat) {
5036 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
5037 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
5038 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
5039 FIXME("Updating part of a compressed texture is not supported at the moment\n");
5040 } if (destFormat != srcFormat) {
5041 FIXME("Updating mixed format compressed texture is not curretly support\n");
5043 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
5044 glDescription->level,
5045 glDescription->glFormatInternal,
5050 IWineD3DSurface_GetData(pSourceSurface));
5053 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
5058 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
5059 to repack the data from pow2Width/Height to expected Width,Height, this makes the
5060 data returned by GetData non-power2 width/height with hardware non-power2
5061 pow2Width/height are set to surface width height, repacking isn't needed so it
5062 doesn't matter which function gets called. */
5063 glTexSubImage2D(glDescription->target
5064 ,glDescription->level
5069 ,glDescription->glFormat
5070 ,glDescription->glType
5071 ,IWineD3DSurface_GetData(pSourceSurface)
5076 checkGLcall("glTexSubImage2D");
5077 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
5078 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
5079 * surface bigger than it needs to be hmm.. */
5080 if (D3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
5081 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
5082 IWineD3DBaseTexture_Release(baseTexture);
5085 glDisable(textureDimensions); /* This needs to be managed better.... */
5091 /* Implementation details at http://developer.nvidia.com/attach/6494
5093 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
5094 hmm.. no longer supported use
5095 OpenGL evaluators or tessellate surfaces within your application.
5098 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
5099 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
5100 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5101 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p) \n", This, Handle, pNumSegs, pRectPatchInfo);
5102 FIXME("(%p) : Stub\n", This);
5107 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
5108 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
5109 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5110 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p) \n", This, Handle, pNumSegs, pTriPatchInfo);
5111 FIXME("(%p) : Stub\n", This);
5115 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5116 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5117 TRACE("(%p) Handle(%d)\n", This, Handle);
5118 FIXME("(%p) : Stub\n", This);
5122 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
5123 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
5124 fill a surface with a block of color! */
5125 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5126 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
5127 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
5128 IWineD3DSwapChainImpl *container = NULL;
5129 BOOL isRenderTarget = FALSE;
5130 unsigned int width, height;
5131 unsigned int top, left;
5134 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
5136 if (surface->resource.pool != D3DPOOL_DEFAULT) {
5137 FIXME("call to colorfill with non D3DPOOL_DEFAULT surface\n");
5138 return D3DERR_INVALIDCALL;
5141 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
5142 if (D3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
5143 if (D3DUSAGE_RENDERTARGET & surface->resource.usage) {
5144 /* TODO: make sure we set everything back to the way it was, and context management!
5145 glGetIntegerv(GL_READ_BUFFER, &prev_read);
5146 vcheckGLcall("glIntegerv");
5147 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
5148 vcheckGLcall("glIntegerv");
5150 TRACE("Color fill to render targets may cause some graphics issues\n");
5151 if (pSurface == container->frontBuffer) {
5152 glDrawBuffer(GL_FRONT);
5154 glDrawBuffer(GL_BACK);
5157 if (D3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
5158 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld \n", surface, surface->resource.usage);
5160 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
5162 if (container != NULL) {
5163 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5165 /* we can use GL_STENCIL_INDEX etc...*/
5168 if (container != NULL) {
5169 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5171 isRenderTarget = TRUE;
5173 /* TODO: drawing to GL_FRONT and GL_BACK */
5174 /* TODO: see if things can be speeded up by using the correct
5175 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
5176 if (pRect == NULL) {
5179 width = surface->currentDesc.Width;
5180 height = surface->currentDesc.Height;
5184 width = pRect->x2 - left;
5185 height = pRect->y2 - top;
5188 data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
5189 /* Create a 'line' of color color, in the correct format for the surface */
5190 for (u = 0 ; u < width ; u ++) {
5195 if (isRenderTarget == FALSE) {
5196 glDescriptor *glDesc;
5197 IWineD3DSurface_PreLoad(pSurface);
5199 /* draw a block of the coloured line on the sufrace */
5200 IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
5201 for (v = 0 ; v< height;v++) {
5202 glTexSubImage2D(glDesc->target
5203 ,glDesc->level /* level */
5213 checkGLcall("glTexSubImage2D");
5215 glDisable(glDesc->target);
5217 /** FIXME: Using GLClear may be faster **/
5218 glRasterPos2i(left, top);
5219 glPixelZoom((float)width ,(float)height);
5220 glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
5221 checkGLcall("glDrawPixels");
5223 HeapFree(GetProcessHeap(), 0, data);
5229 /* rendertarget and deptth stencil functions */
5230 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
5231 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5233 /* FIXME: Implelent RenderTargetIndex >0 */
5234 if(RenderTargetIndex > 0)
5235 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
5237 *ppRenderTarget = This->renderTarget;
5238 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
5239 /* Note inc ref on returned surface */
5240 if(*ppRenderTarget != NULL)
5241 IWineD3DSurface_AddRef(*ppRenderTarget);
5245 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5246 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5247 *ppZStencilSurface = This->depthStencilBuffer;
5248 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
5250 if(*ppZStencilSurface != NULL) {
5251 /* Note inc ref on returned surface */
5252 IWineD3DSurface_AddRef(*ppZStencilSurface);
5257 /* internal static helper functions */
5258 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5259 IWineD3DSurface *RenderSurface);
5261 HRESULT WINAPI static IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain);
5263 HRESULT WINAPI static IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context);
5265 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5266 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5267 HRESULT hr = D3D_OK;
5268 WINED3DVIEWPORT viewport;
5270 TRACE("(%p) Swapping rendertarget\n",This);
5271 if (RenderTargetIndex > 0) {
5272 FIXME("(%p) Render targets other than the first are not supported\n",This);
5273 RenderTargetIndex = 0;
5276 /* MSDN says that null disables the render target
5277 but a device must always be associated with a render target
5278 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5280 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5283 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5284 FIXME("Trying to set render target 0 to NULL\n");
5285 return D3DERR_INVALIDCALL;
5287 /* TODO: replace Impl* usage with interface usage */
5288 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & D3DUSAGE_RENDERTARGET) {
5289 FIXME("(%p)Trying to set the render target to a surface(%p) that wasn't created with a usage of D3DUSAGE_RENDERTARGET\n",This ,pRenderTarget);
5290 return D3DERR_INVALIDCALL;
5292 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
5293 * builds, but I think wine counts as a 'debug' build for now.
5294 ******************************/
5295 /* If we are trying to set what we already have, don't bother */
5296 if (pRenderTarget == This->renderTarget) {
5297 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5299 /* Otherwise, set the render target up */
5301 if (FALSE == This->sceneEnded) {
5302 IWineD3DDevice_EndScene(iface);
5304 TRACE("clearing renderer\n");
5305 /* IWineD3DDeviceImpl_CleanRender(iface); */
5306 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5307 depending on the renter target implementation being used.
5308 A shared context implementation will share all buffers between all rendertargets (including swapchains),
5309 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5310 stencil buffer and incure an extra memory overhead */
5311 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
5314 if (SUCCEEDED(hr)) {
5315 /* Finally, reset the viewport as the MSDN states. */
5316 /* TODO: Replace impl usage */
5317 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
5318 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
5321 viewport.MaxZ = 1.0f;
5322 viewport.MinZ = 0.0f;
5323 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
5325 FIXME("Unknown error setting the render target\n");
5327 This->sceneEnded = FALSE;
5331 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
5332 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5333 HRESULT hr = D3D_OK;
5334 IWineD3DSurface *tmp;
5336 TRACE("(%p) Swapping z-buffer\n",This);
5338 if (pNewZStencil == This->stencilBufferTarget) {
5339 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5341 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5342 * depending on the renter target implementation being used.
5343 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5344 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5345 * stencil buffer and incure an extra memory overhead
5346 ******************************************************/
5349 tmp = This->stencilBufferTarget;
5350 This->stencilBufferTarget = pNewZStencil;
5351 /* should we be calling the parent or the wined3d surface? */
5352 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
5353 if (NULL != tmp) IWineD3DSurface_Release(tmp);
5355 /** TODO: glEnable/glDisable on depth/stencil depending on
5356 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
5357 **********************************************************/
5364 /* Internal functions not in DirectX */
5365 /** TODO: move this off to the opengl context manager
5366 *(the swapchain doesn't need to know anything about offscreen rendering!)
5367 ****************************************************/
5369 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
5371 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5373 TRACE("(%p), %p\n", This, swapchain);
5375 if (swapchain->win != swapchain->drawable) {
5376 /* Set everything back the way it ws */
5377 swapchain->render_ctx = swapchain->glCtx;
5378 swapchain->drawable = swapchain->win;
5383 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
5384 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
5385 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5388 unsigned int height;
5389 WINED3DFORMAT format;
5390 WINED3DSURFACE_DESC surfaceDesc;
5391 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5392 surfaceDesc.Width = &width;
5393 surfaceDesc.Height = &height;
5394 surfaceDesc.Format = &format;
5395 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5397 /* I need a get width/height function (and should do something with the format) */
5398 for (i = 0; i < CONTEXT_CACHE; ++i) {
5399 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
5400 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
5401 the pSurface can be set to 0 allowing it to be reused from cache **/
5402 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
5403 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
5404 *context = &This->contextCache[i];
5407 if (This->contextCache[i].Width == 0) {
5408 This->contextCache[i].pSurface = pSurface;
5409 This->contextCache[i].Width = width;
5410 This->contextCache[i].Height = height;
5411 *context = &This->contextCache[i];
5415 if (i == CONTEXT_CACHE) {
5416 int minUsage = 0x7FFFFFFF; /* MAX_INT */
5417 glContext *dropContext = 0;
5418 for (i = 0; i < CONTEXT_CACHE; i++) {
5419 if (This->contextCache[i].usedcount < minUsage) {
5420 dropContext = &This->contextCache[i];
5421 minUsage = This->contextCache[i].usedcount;
5424 /* clean up the context (this doesn't work for ATI at the moment */
5426 glXDestroyContext(swapchain->display, dropContext->context);
5427 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
5430 dropContext->Width = 0;
5431 dropContext->pSurface = pSurface;
5432 *context = dropContext;
5434 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
5435 for (i = 0; i < CONTEXT_CACHE; i++) {
5436 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
5440 if (*context != NULL)
5443 return E_OUTOFMEMORY;
5446 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
5447 * the functionality needs splitting up so that we don't do more than we should do.
5448 * this only seems to impact performance a little.
5449 ******************************/
5450 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5451 IWineD3DSurface *RenderSurface) {
5452 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5454 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
5455 HRESULT ret = D3DERR_INVALIDCALL;
5456 IWineD3DSurface *tmp;
5458 * Currently only active for GLX >= 1.3
5459 * for others versions we'll have to use GLXPixmaps
5461 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
5462 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
5463 * so only check OpenGL version
5464 * ..........................
5465 * I don't believe that it is a problem with NVidia headers,
5466 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
5467 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
5469 * Your application will report GLX version 1.2 on glXQueryVersion.
5470 * However, it is safe to call the GLX 1.3 functions as described below.
5472 #if defined(GL_VERSION_1_3)
5474 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
5475 GLXFBConfig* cfgs = NULL;
5479 IWineD3DSwapChain *currentSwapchain;
5480 IWineD3DSwapChainImpl *swapchain;
5481 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
5482 * but switch them off if the StencilSurface is set to NULL
5483 ** *********************************************************/
5484 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
5485 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
5488 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
5489 it StencilSurface != NULL && zBufferTarget == NULL switch it on
5492 #define PUSH1(att) attribs[nAttribs++] = (att);
5493 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
5495 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
5497 /** TODO: remove the reff to Impl (context manager should fix this!) **/
5498 IWineD3DSwapChainImpl *impSwapChain;
5499 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
5500 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
5501 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
5506 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
5507 PUSH2(GLX_X_RENDERABLE, TRUE);
5508 PUSH2(GLX_DOUBLEBUFFER, TRUE);
5509 TRACE("calling makeglcfg\n");
5510 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
5513 TRACE("calling chooseFGConfig\n");
5514 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5517 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
5518 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
5519 why we failed and only show this message once! */
5520 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"); /**/
5522 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
5523 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
5524 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
5525 PUSH2(GLX_DOUBLEBUFFER, FALSE);
5526 TRACE("calling makeglcfg\n");
5527 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
5529 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5536 for (i = 0; i < nCfgs; ++i) {
5537 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
5538 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
5539 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
5542 if (NULL != This->renderTarget) {
5544 vcheckGLcall("glFlush");
5545 /** This is only useful if the old render target was a swapchain,
5546 * we need to supercede this with a function that displays
5547 * the current buffer on the screen. This is easy to do in glx1.3 but
5548 * we need to do copy-write pixels in glx 1.2.
5549 ************************************************/
5550 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
5552 printf("Hit Enter to get next frame ...\n");
5558 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain) != D3D_OK) {
5559 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
5560 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
5564 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
5565 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
5566 **********************************************************************/
5567 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == D3D_OK) {
5568 /* We also need to make sure that the lights &co are also in the context of the swapchains */
5569 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
5570 TRACE("making swapchain active\n");
5571 if (RenderSurface != This->renderTarget) {
5572 if (RenderSurface == swapchain->backBuffer) {
5574 /* This could be flagged so that some operations work directly with the front buffer */
5575 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
5577 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
5579 TRACE("Error in setting current context: context %p drawable %ld !\n",
5580 impSwapChain->glCtx, impSwapChain->win);
5583 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5585 checkGLcall("glXMakeContextCurrent");
5587 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5589 else if (pbuffer_support == TRUE && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
5591 /** ********************************************************************
5592 * This is a quickly hacked out implementation of offscreen textures.
5593 * It will work in most cases but there may be problems if the client
5594 * modifies the texture directly, or expects the contents of the rendertarget
5597 * There are some real speed vs compatibility issues here:
5598 * we should really use a new context for every texture, but that eats ram.
5599 * we should also be restoring the texture to the pbuffer but that eats CPU
5600 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
5601 * but if this means reusing the display backbuffer then we need to make sure that
5602 * states are correctly preserved.
5603 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
5604 * and gain a good performance increase at the cost of compatibility.
5605 * I would suggest that, when this is the case, a user configurable flag be made
5606 * available, allowing the user to choose the best emulated experience for them.
5607 *********************************************************************/
5609 XVisualInfo *visinfo;
5610 glContext *newContext;
5612 /* Here were using a shared context model */
5613 if (D3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
5614 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5617 /* If the context doesn't exist then create a new one */
5618 /* TODO: This should really be part of findGlContext */
5619 if (NULL == newContext->context) {
5621 TRACE("making new buffer\n");
5623 PUSH2(GLX_PBUFFER_WIDTH, newContext->Width);
5624 PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
5627 newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
5629 /** ****************************************
5630 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
5632 * In future releases, we may provide the calls glXCreateNewContext,
5633 * glXQueryDrawable and glXMakeContextCurrent.
5634 * so until then we have to use glXGetVisualFromFBConfig &co..
5635 ********************************************/
5638 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
5640 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
5642 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
5646 if (NULL == newContext || NULL == newContext->context) {
5647 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5649 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
5650 if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
5651 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
5654 /* Clean up the old context */
5655 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5656 /* Set the current context of the swapchain to the new context */
5657 impSwapChain->drawable = newContext->drawable;
5658 impSwapChain->render_ctx = newContext->context;
5662 #if 1 /* Apply the stateblock to the new context
5663 FIXME: This is a bit of a hack, each context should know it's own state,
5664 the directX current directX state should then be applied to the context */
5667 IWineD3DStateBlockImpl *oldUpdateStateBlock;
5668 oldUpdateStateBlock = This->updateStateBlock;
5669 oldRecording= This->isRecordingState;
5670 This->isRecordingState = FALSE;
5671 This->updateStateBlock = This->stateBlock;
5672 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
5674 This->isRecordingState = oldRecording;
5675 This->updateStateBlock = oldUpdateStateBlock;
5680 /* clean up the current rendertargets swapchain (if it belonged to one) */
5681 if (currentSwapchain != NULL) {
5682 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
5685 /* Were done with the opengl context management, setup the rendertargets */
5687 tmp = This->renderTarget;
5688 This->renderTarget = RenderSurface;
5689 IWineD3DSurface_AddRef(This->renderTarget);
5690 IWineD3DSurface_Release(tmp);
5696 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
5697 /* Check that the container is not a swapchain member */
5699 IWineD3DSwapChain *tmpSwapChain;
5700 if (D3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
5701 This->renderUpsideDown = TRUE;
5703 This->renderUpsideDown = FALSE;
5704 IWineD3DSwapChain_Release(tmpSwapChain);
5706 /* Force updating the cull mode */
5707 TRACE("setting render state\n");
5708 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
5709 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
5711 /* Force updating projection matrix */
5712 This->last_was_rhw = FALSE;
5713 This->proj_valid = FALSE;
5721 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
5722 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
5727 if ( NULL != impSwapChain) {
5728 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
5736 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
5737 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
5738 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5739 /* TODO: the use of Impl is deprecated. */
5740 /* some basic validation checks */
5741 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
5743 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
5745 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
5746 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
5747 return D3DERR_INVALIDCALL;
5749 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
5750 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
5751 return D3DERR_INVALIDCALL;
5753 /* TODO: make the cursor 'real' */
5755 This->xHotSpot = XHotSpot;
5756 This->yHotSpot = YHotSpot;
5761 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
5762 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5763 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
5765 This->xScreenSpace = XScreenSpace;
5766 This->yScreenSpace = YScreenSpace;
5772 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
5773 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5774 TRACE("(%p) : visible(%d)\n", This, bShow);
5776 This->bCursorVisible = bShow;
5781 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
5782 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5783 FIXME("(%p) : stub\n", This); /* No way of notifying yet! */
5788 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
5789 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5790 /** FIXME: Resource tracking needs to be done,
5791 * The closes we can do to this is set the priorities of all managed textures low
5792 * and then reset them.
5793 ***********************************************************/
5794 FIXME("(%p) : stub\n", This);
5798 HRESULT WINAPI IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
5799 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5800 /** FIXME: Resource trascking needs to be done.
5801 * in effect this pulls all non only default
5802 * textures out of video memory and deletes all glTextures (glDeleteTextures)
5803 * and should clear down the context and set it up according to pPresentationParameters
5804 ***********************************************************/
5805 FIXME("(%p) : stub\n", This);
5809 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
5810 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5811 /** FIXME: always true at the moment **/
5812 if(bEnableDialogs == FALSE) {
5813 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
5819 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
5820 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5822 FIXME("(%p) : stub\n", This);
5823 /* Setup some reasonable defaults */
5824 pParameters->AdapterOrdinal = 0; /* always for now */
5825 pParameters->DeviceType = D3DDEVTYPE_HAL; /* always for now */
5826 pParameters->hFocusWindow = 0;
5827 pParameters->BehaviorFlags =0;
5831 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
5832 IWineD3DSwapChain *swapchain;
5833 HRESULT hrc = D3D_OK;
5835 TRACE("Relaying to swapchain\n");
5837 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
5838 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (D3DGAMMARAMP *)pRamp);
5839 IWineD3DSwapChain_Release(swapchain);
5844 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
5845 IWineD3DSwapChain *swapchain;
5846 HRESULT hrc = D3D_OK;
5848 TRACE("Relaying to swapchain\n");
5850 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
5851 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
5852 IWineD3DSwapChain_Release(swapchain);
5858 /** ********************************************************
5859 * Notification functions
5860 ** ********************************************************/
5861 /** This function must be called in the release of a resource when ref == 0,
5862 * the contents of resource must still be correct,
5863 * any handels to other resource held by the caller must be closed
5864 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
5865 *****************************************************/
5866 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5867 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5868 ResourceList* resourceList;
5870 TRACE("(%p) : resource %p\n", This, resource);
5872 EnterCriticalSection(&resourceStoreCriticalSection);
5874 /* add a new texture to the frot of the linked list */
5875 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
5876 resourceList->resource = resource;
5878 /* Get the old head */
5879 resourceList->next = This->resources;
5881 This->resources = resourceList;
5882 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
5885 LeaveCriticalSection(&resourceStoreCriticalSection);
5890 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5891 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5892 ResourceList* resourceList = NULL;
5893 ResourceList* previousResourceList = NULL;
5895 TRACE("(%p) : resource %p\n", This, resource);
5898 EnterCriticalSection(&resourceStoreCriticalSection);
5900 resourceList = This->resources;
5902 while (resourceList != NULL) {
5903 if(resourceList->resource == resource) break;
5904 previousResourceList = resourceList;
5905 resourceList = resourceList->next;
5908 if (resourceList == NULL) {
5909 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
5911 LeaveCriticalSection(&resourceStoreCriticalSection);
5915 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
5917 /* make sure we don't leave a hole in the list */
5918 if (previousResourceList != NULL) {
5919 previousResourceList->next = resourceList->next;
5921 This->resources = resourceList->next;
5925 LeaveCriticalSection(&resourceStoreCriticalSection);
5931 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
5932 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5935 TRACE("(%p) : resource %p\n", This, resource);
5936 switch(IWineD3DResource_GetType(resource)){
5937 case D3DRTYPE_SURFACE:
5938 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
5940 case D3DRTYPE_TEXTURE:
5941 case D3DRTYPE_CUBETEXTURE:
5942 case D3DRTYPE_VOLUMETEXTURE:
5943 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
5944 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5945 IUnknown *textureParent;
5946 IWineD3DBaseTexture_GetParent(This->stateBlock->textures[counter], &textureParent);
5947 /* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
5948 FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter, resource, textureParent);
5949 IUnknown_Release(textureParent);
5950 This->stateBlock->textures[counter] = NULL;
5952 if (This->updateStateBlock != This->stateBlock ){
5953 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5954 IUnknown *textureParent;
5955 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[counter], &textureParent);
5956 /* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
5957 FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter, resource, textureParent);
5958 IUnknown_Release(textureParent);
5959 This->updateStateBlock->textures[counter] = NULL;
5964 case D3DRTYPE_VOLUME:
5965 /* TODO: nothing really? */
5967 case D3DRTYPE_VERTEXBUFFER:
5968 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
5971 TRACE("Cleaning up stream pointers\n");
5973 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
5974 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
5975 FINDOUT: should changes.streamSource[StreamNumber] be set ?
5977 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5978 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
5979 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
5980 This->updateStateBlock->streamSource[streamNumber] = 0;
5981 /* Set changed flag? */
5984 if (This->stateBlock != NULL ) { /* only happens if their is an error in the application, or on reset/release (because we don't manage internal tracknig properly) */
5985 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
5986 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
5987 This->stateBlock->streamSource[streamNumber] = 0;
5990 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
5991 else { /* This shouldn't happen */
5992 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
5999 case D3DRTYPE_INDEXBUFFER:
6000 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
6001 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6002 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6003 This->updateStateBlock->pIndexData = NULL;
6006 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
6007 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6008 This->stateBlock->pIndexData = NULL;
6014 FIXME("(%p) unknown resource type %p %u \n", This, resource, IWineD3DResource_GetType(resource));
6019 /* Remove the resoruce from the resourceStore */
6020 IWineD3DDeviceImpl_RemoveResource(iface, resource);
6022 TRACE("Resource released\n");
6027 /** This function is to be called by the swapchain when it is released and it's ref = 0
6028 *****************************************************/
6029 void WINAPI IWineD3DDeviceImpl_SwapChainReleased(IWineD3DDevice *iface, IWineD3DSwapChain *swapChain){
6030 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6031 SwapChainList **nextSwapchain;
6032 nextSwapchain = &This->swapchains;
6034 /* Check to see if the swapchian is being used as the render target */
6035 if (This->renderTarget != NULL) {
6036 IWineD3DSurface *swapchainBackBuffer;
6038 IWineD3DSwapChain_GetBackBuffer(swapChain, 0 ,( D3DBACKBUFFER_TYPE) 0, &swapchainBackBuffer);
6039 if (This->renderTarget == swapchainBackBuffer) {
6040 /* Don't know what to do, so warn and carry on as usual (which in this case leaves the renderterget in limbo) */
6041 FIXME("Atempting to release a swapchain that is currently beuing used as a render target, behaviour is undefined\n");
6045 /* Go through the swapchain list and try to find the swapchain being released */
6046 while(*nextSwapchain != NULL && (*nextSwapchain)->swapchain != swapChain) {
6047 nextSwapchain = &(*nextSwapchain)->next;
6050 /* Check to see if we found the swapchain */
6051 if (NULL != *nextSwapchain) {
6052 /* We found the swapchain so remove it from the list */
6053 TRACE("(%p) releasing swapchain(%p)\n", iface, swapChain);
6054 HeapFree(GetProcessHeap(), 0 , *nextSwapchain);
6055 *nextSwapchain = (*nextSwapchain)->next;
6057 /* We didn't find the swapchain on the list, this can only heppen because of a programming error in wined3d */
6058 FIXME("(%p) Attempting to release a swapchain (%p) that hasn't been stored\n", iface, swapChain);
6061 TRACE("swapchain (%p) released\n", swapChain);
6065 /**********************************************************
6066 * IWineD3DDevice VTbl follows
6067 **********************************************************/
6069 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
6071 /*** IUnknown methods ***/
6072 IWineD3DDeviceImpl_QueryInterface,
6073 IWineD3DDeviceImpl_AddRef,
6074 IWineD3DDeviceImpl_Release,
6075 /*** IWineD3DDevice methods ***/
6076 IWineD3DDeviceImpl_GetParent,
6077 /*** Creation methods**/
6078 IWineD3DDeviceImpl_CreateVertexBuffer,
6079 IWineD3DDeviceImpl_CreateIndexBuffer,
6080 IWineD3DDeviceImpl_CreateStateBlock,
6081 IWineD3DDeviceImpl_CreateSurface,
6082 IWineD3DDeviceImpl_CreateTexture,
6083 IWineD3DDeviceImpl_CreateVolumeTexture,
6084 IWineD3DDeviceImpl_CreateVolume,
6085 IWineD3DDeviceImpl_CreateCubeTexture,
6086 IWineD3DDeviceImpl_CreateQuery,
6087 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
6088 IWineD3DDeviceImpl_CreateVertexDeclaration,
6089 IWineD3DDeviceImpl_CreateVertexShader,
6090 IWineD3DDeviceImpl_CreatePixelShader,
6091 /*** Odd functions **/
6092 IWineD3DDeviceImpl_EvictManagedResources,
6093 IWineD3DDeviceImpl_GetAvailableTextureMem,
6094 IWineD3DDeviceImpl_GetBackBuffer,
6095 IWineD3DDeviceImpl_GetCreationParameters,
6096 IWineD3DDeviceImpl_GetDeviceCaps,
6097 IWineD3DDeviceImpl_GetDirect3D,
6098 IWineD3DDeviceImpl_GetDisplayMode,
6099 IWineD3DDeviceImpl_GetNumberOfSwapChains,
6100 IWineD3DDeviceImpl_GetRasterStatus,
6101 IWineD3DDeviceImpl_GetSwapChain,
6102 IWineD3DDeviceImpl_Reset,
6103 IWineD3DDeviceImpl_SetDialogBoxMode,
6104 IWineD3DDeviceImpl_SetCursorProperties,
6105 IWineD3DDeviceImpl_SetCursorPosition,
6106 IWineD3DDeviceImpl_ShowCursor,
6107 IWineD3DDeviceImpl_TestCooperativeLevel,
6108 /*** Getters and setters **/
6109 IWineD3DDeviceImpl_SetClipPlane,
6110 IWineD3DDeviceImpl_GetClipPlane,
6111 IWineD3DDeviceImpl_SetClipStatus,
6112 IWineD3DDeviceImpl_GetClipStatus,
6113 IWineD3DDeviceImpl_SetCurrentTexturePalette,
6114 IWineD3DDeviceImpl_GetCurrentTexturePalette,
6115 IWineD3DDeviceImpl_SetDepthStencilSurface,
6116 IWineD3DDeviceImpl_GetDepthStencilSurface,
6117 IWineD3DDeviceImpl_SetFVF,
6118 IWineD3DDeviceImpl_GetFVF,
6119 IWineD3DDeviceImpl_SetGammaRamp,
6120 IWineD3DDeviceImpl_GetGammaRamp,
6121 IWineD3DDeviceImpl_SetIndices,
6122 IWineD3DDeviceImpl_GetIndices,
6123 IWineD3DDeviceImpl_SetLight,
6124 IWineD3DDeviceImpl_GetLight,
6125 IWineD3DDeviceImpl_SetLightEnable,
6126 IWineD3DDeviceImpl_GetLightEnable,
6127 IWineD3DDeviceImpl_SetMaterial,
6128 IWineD3DDeviceImpl_GetMaterial,
6129 IWineD3DDeviceImpl_SetNPatchMode,
6130 IWineD3DDeviceImpl_GetNPatchMode,
6131 IWineD3DDeviceImpl_SetPaletteEntries,
6132 IWineD3DDeviceImpl_GetPaletteEntries,
6133 IWineD3DDeviceImpl_SetPixelShader,
6134 IWineD3DDeviceImpl_GetPixelShader,
6135 IWineD3DDeviceImpl_SetPixelShaderConstantB,
6136 IWineD3DDeviceImpl_GetPixelShaderConstantB,
6137 IWineD3DDeviceImpl_SetPixelShaderConstantI,
6138 IWineD3DDeviceImpl_GetPixelShaderConstantI,
6139 IWineD3DDeviceImpl_SetPixelShaderConstantF,
6140 IWineD3DDeviceImpl_GetPixelShaderConstantF,
6141 IWineD3DDeviceImpl_SetRenderState,
6142 IWineD3DDeviceImpl_GetRenderState,
6143 IWineD3DDeviceImpl_SetRenderTarget,
6144 IWineD3DDeviceImpl_GetRenderTarget,
6145 IWineD3DDeviceImpl_SetSamplerState,
6146 IWineD3DDeviceImpl_GetSamplerState,
6147 IWineD3DDeviceImpl_SetScissorRect,
6148 IWineD3DDeviceImpl_GetScissorRect,
6149 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
6150 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
6151 IWineD3DDeviceImpl_SetStreamSource,
6152 IWineD3DDeviceImpl_GetStreamSource,
6153 IWineD3DDeviceImpl_SetStreamSourceFreq,
6154 IWineD3DDeviceImpl_GetStreamSourceFreq,
6155 IWineD3DDeviceImpl_SetTexture,
6156 IWineD3DDeviceImpl_GetTexture,
6157 IWineD3DDeviceImpl_SetTextureStageState,
6158 IWineD3DDeviceImpl_GetTextureStageState,
6159 IWineD3DDeviceImpl_SetTransform,
6160 IWineD3DDeviceImpl_GetTransform,
6161 IWineD3DDeviceImpl_SetVertexDeclaration,
6162 IWineD3DDeviceImpl_GetVertexDeclaration,
6163 IWineD3DDeviceImpl_SetVertexShader,
6164 IWineD3DDeviceImpl_GetVertexShader,
6165 IWineD3DDeviceImpl_SetVertexShaderConstantB,
6166 IWineD3DDeviceImpl_GetVertexShaderConstantB,
6167 IWineD3DDeviceImpl_SetVertexShaderConstantI,
6168 IWineD3DDeviceImpl_GetVertexShaderConstantI,
6169 IWineD3DDeviceImpl_SetVertexShaderConstantF,
6170 IWineD3DDeviceImpl_GetVertexShaderConstantF,
6171 IWineD3DDeviceImpl_SetViewport,
6172 IWineD3DDeviceImpl_GetViewport,
6173 IWineD3DDeviceImpl_MultiplyTransform,
6174 IWineD3DDeviceImpl_ValidateDevice,
6175 IWineD3DDeviceImpl_ProcessVertices,
6176 /*** State block ***/
6177 IWineD3DDeviceImpl_BeginStateBlock,
6178 IWineD3DDeviceImpl_EndStateBlock,
6179 /*** Scene management ***/
6180 IWineD3DDeviceImpl_BeginScene,
6181 IWineD3DDeviceImpl_EndScene,
6182 IWineD3DDeviceImpl_Present,
6183 IWineD3DDeviceImpl_Clear,
6185 IWineD3DDeviceImpl_DrawPrimitive,
6186 IWineD3DDeviceImpl_DrawIndexedPrimitive,
6187 IWineD3DDeviceImpl_DrawPrimitiveUP,
6188 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
6189 IWineD3DDeviceImpl_DrawRectPatch,
6190 IWineD3DDeviceImpl_DrawTriPatch,
6191 IWineD3DDeviceImpl_DeletePatch,
6192 IWineD3DDeviceImpl_ColorFill,
6193 IWineD3DDeviceImpl_UpdateTexture,
6194 IWineD3DDeviceImpl_UpdateSurface,
6195 IWineD3DDeviceImpl_StretchRect,
6196 IWineD3DDeviceImpl_GetRenderTargetData,
6197 IWineD3DDeviceImpl_GetFrontBufferData,
6198 /*** Internal use IWineD3DDevice methods ***/
6199 IWineD3DDeviceImpl_SetupTextureStates,
6200 /*** object tracking ***/
6201 IWineD3DDeviceImpl_SwapChainReleased,
6202 IWineD3DDeviceImpl_ResourceReleased
6206 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
6207 WINED3DRS_ALPHABLENDENABLE ,
6208 WINED3DRS_ALPHAFUNC ,
6209 WINED3DRS_ALPHAREF ,
6210 WINED3DRS_ALPHATESTENABLE ,
6212 WINED3DRS_COLORWRITEENABLE ,
6213 WINED3DRS_DESTBLEND ,
6214 WINED3DRS_DITHERENABLE ,
6215 WINED3DRS_FILLMODE ,
6216 WINED3DRS_FOGDENSITY ,
6218 WINED3DRS_FOGSTART ,
6219 WINED3DRS_LASTPIXEL ,
6220 WINED3DRS_SHADEMODE ,
6221 WINED3DRS_SRCBLEND ,
6222 WINED3DRS_STENCILENABLE ,
6223 WINED3DRS_STENCILFAIL ,
6224 WINED3DRS_STENCILFUNC ,
6225 WINED3DRS_STENCILMASK ,
6226 WINED3DRS_STENCILPASS ,
6227 WINED3DRS_STENCILREF ,
6228 WINED3DRS_STENCILWRITEMASK ,
6229 WINED3DRS_STENCILZFAIL ,
6230 WINED3DRS_TEXTUREFACTOR ,
6241 WINED3DRS_ZWRITEENABLE
6244 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
6245 WINED3DTSS_ADDRESSW ,
6246 WINED3DTSS_ALPHAARG0 ,
6247 WINED3DTSS_ALPHAARG1 ,
6248 WINED3DTSS_ALPHAARG2 ,
6249 WINED3DTSS_ALPHAOP ,
6250 WINED3DTSS_BUMPENVLOFFSET ,
6251 WINED3DTSS_BUMPENVLSCALE ,
6252 WINED3DTSS_BUMPENVMAT00 ,
6253 WINED3DTSS_BUMPENVMAT01 ,
6254 WINED3DTSS_BUMPENVMAT10 ,
6255 WINED3DTSS_BUMPENVMAT11 ,
6256 WINED3DTSS_COLORARG0 ,
6257 WINED3DTSS_COLORARG1 ,
6258 WINED3DTSS_COLORARG2 ,
6259 WINED3DTSS_COLOROP ,
6260 WINED3DTSS_RESULTARG ,
6261 WINED3DTSS_TEXCOORDINDEX ,
6262 WINED3DTSS_TEXTURETRANSFORMFLAGS
6265 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
6266 WINED3DSAMP_ADDRESSU ,
6267 WINED3DSAMP_ADDRESSV ,
6268 WINED3DSAMP_ADDRESSW ,
6269 WINED3DSAMP_BORDERCOLOR ,
6270 WINED3DSAMP_MAGFILTER ,
6271 WINED3DSAMP_MINFILTER ,
6272 WINED3DSAMP_MIPFILTER ,
6273 WINED3DSAMP_MIPMAPLODBIAS ,
6274 WINED3DSAMP_MAXMIPLEVEL ,
6275 WINED3DSAMP_MAXANISOTROPY ,
6276 WINED3DSAMP_SRGBTEXTURE ,
6277 WINED3DSAMP_ELEMENTINDEX
6280 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
6282 WINED3DRS_AMBIENTMATERIALSOURCE ,
6283 WINED3DRS_CLIPPING ,
6284 WINED3DRS_CLIPPLANEENABLE ,
6285 WINED3DRS_COLORVERTEX ,
6286 WINED3DRS_DIFFUSEMATERIALSOURCE ,
6287 WINED3DRS_EMISSIVEMATERIALSOURCE ,
6288 WINED3DRS_FOGDENSITY ,
6290 WINED3DRS_FOGSTART ,
6291 WINED3DRS_FOGTABLEMODE ,
6292 WINED3DRS_FOGVERTEXMODE ,
6293 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
6294 WINED3DRS_LIGHTING ,
6295 WINED3DRS_LOCALVIEWER ,
6296 WINED3DRS_MULTISAMPLEANTIALIAS ,
6297 WINED3DRS_MULTISAMPLEMASK ,
6298 WINED3DRS_NORMALIZENORMALS ,
6299 WINED3DRS_PATCHEDGESTYLE ,
6300 WINED3DRS_POINTSCALE_A ,
6301 WINED3DRS_POINTSCALE_B ,
6302 WINED3DRS_POINTSCALE_C ,
6303 WINED3DRS_POINTSCALEENABLE ,
6304 WINED3DRS_POINTSIZE ,
6305 WINED3DRS_POINTSIZE_MAX ,
6306 WINED3DRS_POINTSIZE_MIN ,
6307 WINED3DRS_POINTSPRITEENABLE ,
6308 WINED3DRS_RANGEFOGENABLE ,
6309 WINED3DRS_SPECULARMATERIALSOURCE ,
6310 WINED3DRS_TWEENFACTOR ,
6311 WINED3DRS_VERTEXBLEND
6314 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
6315 WINED3DTSS_TEXCOORDINDEX ,
6316 WINED3DTSS_TEXTURETRANSFORMFLAGS
6319 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
6320 WINED3DSAMP_DMAPOFFSET