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 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
30 /* x11drv GDI escapes */
31 #define X11DRV_ESCAPE 6789
32 enum x11drv_escape_codes
34 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
35 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
36 X11DRV_GET_FONT, /* get current X font for a DC */
39 /* retrieve the X display to use on a given DC */
40 inline static Display *get_display( HDC hdc )
43 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
45 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
46 sizeof(display), (LPSTR)&display )) display = NULL;
50 /* Memory tracking and object counting */
51 static unsigned int emulated_textureram = 64*1024*1024;
53 /* TODO: setup some flags in the regestry to enable, disable pbuffer support */
54 /* enable pbuffer support for offscreen textures */
55 BOOL pbuffer_support = FALSE;
56 /* allocate one pbuffer per surface */
57 BOOL pbuffer_per_surface = FALSE;
59 /* static function declarations */
60 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
62 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type);
65 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return D3DERR_OUTOFVIDEOMEMORY;}
67 #define D3DCREATEOBJECTINSTANCE(object, type) { \
68 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
69 D3DMEMCHECK(object, pp##type); \
70 object->lpVtbl = &IWineD3D##type##_Vtbl; \
71 object->wineD3DDevice = This; \
72 object->parent = parent; \
74 *pp##type = (IWineD3D##type *) object; \
77 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
78 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
79 D3DMEMCHECK(object, pp##type); \
80 object->lpVtbl = &IWineD3D##type##_Vtbl; \
81 object->resource.wineD3DDevice = This; \
82 object->resource.parent = parent; \
83 object->resource.resourceType = d3dtype; \
84 object->resource.ref = 1; \
85 object->resource.pool = Pool; \
86 object->resource.format = Format; \
87 object->resource.usage = Usage; \
88 object->resource.size = _size; \
89 /* Check that we have enough video ram left */ \
90 if (Pool == D3DPOOL_DEFAULT) { \
91 if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
92 WARN("Out of 'bogus' video memory\n"); \
93 HeapFree(GetProcessHeap(), 0, object); \
95 return D3DERR_OUTOFVIDEOMEMORY; \
97 globalChangeGlRam(_size); \
99 object->resource.allocatedMemory = (0 == _size ? NULL : Pool == D3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
100 if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != D3DPOOL_DEFAULT) { \
101 FIXME("Out of memory!\n"); \
102 HeapFree(GetProcessHeap(), 0, object); \
104 return D3DERR_OUTOFVIDEOMEMORY; \
106 *pp##type = (IWineD3D##type *) object; \
107 IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
108 TRACE("(%p) : Created resource %p\n", This, object); \
111 #define D3DINITILIZEBASETEXTURE(_basetexture) { \
112 _basetexture.levels = Levels; \
113 _basetexture.filterType = (Usage & D3DUSAGE_AUTOGENMIPMAP) ? D3DTEXF_LINEAR : D3DTEXF_NONE; \
114 _basetexture.LOD = 0; \
115 _basetexture.dirty = TRUE; \
118 /**********************************************************
119 * Global variable / Constants follow
120 **********************************************************/
121 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
123 /**********************************************************
124 * Utility functions follow
125 **********************************************************/
126 /* Convert the D3DLIGHT properties into equivalent gl lights */
127 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
130 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
131 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
133 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
134 glMatrixMode(GL_MODELVIEW);
136 glLoadMatrixf((float *)&This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
139 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
140 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
141 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
142 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
143 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
144 checkGLcall("glLightfv");
147 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
148 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
149 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
150 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
151 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
152 checkGLcall("glLightfv");
155 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
156 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
157 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
158 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
159 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
160 checkGLcall("glLightfv");
162 /* Attenuation - Are these right? guessing... */
163 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
164 checkGLcall("glLightf");
165 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
166 checkGLcall("glLightf");
168 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) != 0) {
169 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
171 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
174 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
175 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
176 checkGLcall("glLightf");
178 switch (lightInfo->OriginalParms.Type) {
181 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
182 checkGLcall("glLightfv");
183 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
184 checkGLcall("glLightf");
190 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
191 checkGLcall("glLightfv");
193 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
194 checkGLcall("glLightfv");
195 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
196 checkGLcall("glLightf");
197 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
198 checkGLcall("glLightf");
202 case D3DLIGHT_DIRECTIONAL:
204 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
205 checkGLcall("glLightfv");
206 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
207 checkGLcall("glLightf");
208 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
209 checkGLcall("glLightf");
213 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
216 /* Restore the modelview matrix */
220 /* Apply the current values to the specified texture stage */
221 void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Sampler, DWORD Flags) {
222 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
230 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
231 clamping, MIPLOD, etc. This will work for up to 16 samplers.
234 if (Sampler >= GL_LIMITS(samplers)) {
235 FIXME("Trying to set the state of more samplers %ld than are supported %d by this openGL implementation\n", Sampler, GL_LIMITS(samplers));
238 VTRACE(("Activating appropriate texture state %ld\n", Sampler));
239 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
241 GLACTIVETEXTURE(Sampler);
243 /* Could we use bindTexture and then apply the states instead of GLACTIVETEXTURE */
244 } else if (Sampler > 0) {
245 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
249 /* TODO: change this to a lookup table
250 LOOKUP_TEXTURE_STATES lists all texture states that should be applied.
251 LOOKUP_CONTEXT_SATES list all context applicable states that can be applied
252 etc.... it's a lot cleaner, quicker and possibly easier to maintain than running a switch and setting a skip flag...
253 especially when there are a number of groups of states. */
255 TRACE("-----------------------> Updating the texture at Sampler %ld to have new texture state information\n", Sampler);
257 /* 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 */
258 #define APPLY_STATE(_state) IWineD3DDeviceImpl_ApplyTextureUnitState(iface, Sampler, _state)
259 /* these are the only two supported states that need to be applied */
260 APPLY_STATE(WINED3DTSS_TEXCOORDINDEX);
261 APPLY_STATE(WINED3DTSS_TEXTURETRANSFORMFLAGS);
262 #if 0 /* not supported at the moment */
263 APPLY_STATE(WINED3DTSS_BUMPENVMAT00);
264 APPLY_STATE(WINED3DTSS_BUMPENVMAT01);
265 APPLY_STATE(WINED3DTSS_BUMPENVMAT10);
266 APPLY_STATE(WINED3DTSS_BUMPENVMAT11);
267 APPLY_STATE(WINED3DTSS_BUMPENVLSCALE);
268 APPLY_STATE(WINED3DTSS_BUMPENVLOFFSET);
269 APPLY_STATE(WINED3DTSS_RESULTARG);
270 APPLY_STATE(WINED3DTSS_CONSTANT);
272 /* a quick sanity check in case someone forgot to update this function */
273 if (WINED3D_HIGHEST_TEXTURE_STATE > WINED3DTSS_CONSTANT) {
274 FIXME("(%p) : There are more texture states than expected, update device.c to match\n", This);
278 /* apply any sampler states that always need applying */
279 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
280 tmpvalue.d = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPMAPLODBIAS];
281 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
282 GL_TEXTURE_LOD_BIAS_EXT,
284 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
287 /* Note the D3DRS value applies to all textures, but GL has one
288 * per texture, so apply it now ready to be used!
290 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
291 /* Set the default alpha blend color */
292 glBlendColor(col[0], col[1], col[2], col[3]);
293 checkGLcall("glBlendColor");
295 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
296 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
297 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
299 /* TODO: NV_POINT_SPRITE */
300 if (GL_SUPPORT(ARB_POINT_SPRITE)) {
301 if (This->stateBlock->renderState[WINED3DRS_POINTSPRITEENABLE] != FALSE) {
302 /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
303 glDisable(GL_POINT_SMOOTH);
305 /* Centre the texture on the vertex */
306 VTRACE("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
307 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
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);
311 checkGLcall("glTexEnvf(...)");
312 VTRACE("glEnable( GL_POINT_SPRITE_ARB )\n");
313 glEnable( GL_POINT_SPRITE_ARB );
314 checkGLcall("glEnable(...)");
316 VTRACE("glDisable( GL_POINT_SPRITE_ARB )\n");
317 glDisable( GL_POINT_SPRITE_ARB );
318 checkGLcall("glEnable(...)");
322 TRACE("-----------------------> Updated the texture at Sampler %ld to have new texture state information\n", Sampler);
325 /**********************************************************
326 * IUnknown parts follows
327 **********************************************************/
329 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
331 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
332 /* FIXME: This needs to extend an IWineD3DBaseObject */
334 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
335 if (IsEqualGUID(riid, &IID_IUnknown)
336 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
337 IUnknown_AddRef(iface);
342 return E_NOINTERFACE;
345 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
346 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
347 ULONG refCount = InterlockedIncrement(&This->ref);
349 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
353 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
354 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
355 ULONG refCount = InterlockedDecrement(&This->ref);
357 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
360 /* TODO: Clean up all the surfaces and textures! */
361 /* FIXME: Create targets and state blocks in d3d8 */
362 if (((IWineD3DImpl *)This->wineD3D)->dxVersion > 8) { /*We don't create a state block in d3d8 yet*/
363 /* NOTE: You must release the parent if the object was created via a callback
364 ** ***************************/
365 /* TODO: this is exactly the same as required by _Reset.., so at some point we need to move the code so that is can be called by reset add release... */
366 /* Release all of the swapchains, except the implicit swapchain */
367 IUnknown* stencilBufferParent;
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); */
386 /* Release the buffers (with sanity checks)*/
387 if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
388 if(This->depthStencilBuffer != This->stencilBufferTarget)
389 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
391 This->stencilBufferTarget = NULL;
393 if(IWineD3DSurface_Release(This->renderTarget) >0){
394 /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
396 This->renderTarget = NULL;
398 IWineD3DSurface_GetParent(This->depthStencilBuffer, &stencilBufferParent);
399 IUnknown_Release(stencilBufferParent); /* once for the get parent */
400 if(IUnknown_Release(stencilBufferParent) >0){ /* the second time for when it was created */
401 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
403 This->depthStencilBuffer = NULL;
405 /* Release the update stateblock */
406 if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){
407 if(This->updateStateBlock != This->stateBlock)
408 FIXME("(%p) Something's still holding the Update stateblock\n",This);
410 This->updateStateBlock = NULL;
411 { /* because were not doing proper internal refcounts releasing the primary state block
412 causes recursion with the extra checks in ResourceReleased, to avoid this we have
413 to set this->stateBlock = NULL; first */
414 IWineD3DStateBlock *stateBlock = (IWineD3DStateBlock *)This->stateBlock;
415 This->stateBlock = NULL;
417 /* Release the stateblock */
418 if(IWineD3DStateBlock_Release(stateBlock) > 0){
419 FIXME("(%p) Something's still holding the Update stateblock\n",This);
423 if (This->swapchains != NULL) {
424 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
425 IWineD3DSwapChain_GetParent(This->swapchains->swapchain, &swapChainParent);
426 IUnknown_Release(swapChainParent); /* once for the get parent */
427 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
428 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
432 if (This->resources != NULL ) {
433 FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This);
435 #if 0 /* TODO: Dump a list of all the resources still bound */
436 dumpResources(This->resources);
438 /* TODO: set the resources to a lost state */
442 IWineD3D_Release(This->wineD3D);
443 This->wineD3D = NULL;
444 HeapFree(GetProcessHeap(), 0, This);
445 TRACE("Freed device %p \n",This);
451 /**********************************************************
452 * IWineD3DDevice implementation follows
453 **********************************************************/
454 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
455 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
456 *pParent = This->parent;
457 IUnknown_AddRef(This->parent);
461 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
462 DWORD FVF, D3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
464 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
465 IWineD3DVertexBufferImpl *object;
466 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
467 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, D3DRTYPE_VERTEXBUFFER, Size)
470 if (Pool == D3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
471 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
475 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
476 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
481 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
482 WINED3DFORMAT Format, D3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
483 HANDLE *sharedHandle, IUnknown *parent) {
484 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
485 IWineD3DIndexBufferImpl *object;
486 TRACE("(%p) Creating index buffer\n", This);
488 /* Allocate the storage for the device */
489 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,D3DRTYPE_INDEXBUFFER, Length)
492 if (Pool == D3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
493 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
496 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
497 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
498 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
503 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
505 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
506 IWineD3DStateBlockImpl *object;
509 D3DCREATEOBJECTINSTANCE(object, StateBlock)
510 object->blockType = Type;
512 /* Special case - Used during initialization to produce a placeholder stateblock
513 so other functions called can update a state block */
514 if (Type == WINED3DSBT_INIT) {
515 /* Don't bother increasing the reference count otherwise a device will never
516 be freed due to circular dependencies */
520 /* Otherwise, might as well set the whole state block to the appropriate values */
521 if ( This->stateBlock != NULL) {
522 memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
524 memset(object->streamFreq, 1, sizeof(object->streamFreq));
527 /* Reset the ref and type after kludging it */
528 object->wineD3DDevice = This;
530 object->blockType = Type;
532 TRACE("Updating changed flags appropriate for type %d\n", Type);
534 if (Type == WINED3DSBT_ALL) {
536 TRACE("ALL => Pretend everything has changed\n");
537 memset(&object->changed, TRUE, sizeof(This->stateBlock->changed));
538 } else if (Type == WINED3DSBT_PIXELSTATE) {
540 TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
541 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
543 object->changed.pixelShader = TRUE;
545 /* Pixel Shader Constants */
546 for (i = 0; i < MAX_PSHADER_CONSTANTS; ++i) {
547 object->changed.pixelShaderConstants[i] = TRUE;
549 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
550 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
552 for (j = 0; j < GL_LIMITS(textures); j++) {
553 for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
554 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
557 for (j = 0 ; j < 16; j++) {
558 for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
560 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
564 } else if (Type == WINED3DSBT_VERTEXSTATE) {
566 TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
567 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
569 object->changed.vertexShader = TRUE;
571 /* Vertex Shader Constants */
572 for (i = 0; i < MAX_VSHADER_CONSTANTS; ++i) {
573 object->changed.vertexShaderConstants[i] = TRUE;
575 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
576 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
578 for (j = 0; j < GL_LIMITS(textures); j++) {
579 for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
580 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
583 for (j = 0 ; j < 16; j++){
584 for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
585 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
589 /* Duplicate light chain */
591 PLIGHTINFOEL *src = NULL;
592 PLIGHTINFOEL *dst = NULL;
593 PLIGHTINFOEL *newEl = NULL;
594 src = This->stateBlock->lights;
595 object->lights = NULL;
599 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
600 if (newEl == NULL) return D3DERR_OUTOFVIDEOMEMORY;
601 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
603 newEl->changed = TRUE;
604 newEl->enabledChanged = TRUE;
606 object->lights = newEl;
617 FIXME("Unrecognized state block type %d\n", Type);
620 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
625 /* ************************************
627 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
630 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
632 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.
634 ******************************** */
636 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) {
637 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
638 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
639 unsigned int pow2Width, pow2Height;
640 unsigned int Size = 1;
641 TRACE("(%p) Create surface\n",This);
643 /** FIXME: Check ranges on the inputs are valid
646 * [in] Quality level. The valid range is between zero and one less than the level
647 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
648 * Passing a larger value returns the error D3DERR_INVALIDCALL. The MultisampleQuality
649 * values of paired render targets, depth stencil surfaces, and the MultiSample type
651 *******************************/
656 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
658 * If this flag is set, the contents of the depth stencil buffer will be
659 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
660 * with a different depth surface.
662 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
663 ***************************/
665 if(MultisampleQuality < 0) {
666 FIXME("Invalid multisample level %ld \n", MultisampleQuality);
667 return D3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
670 if(MultisampleQuality > 0) {
671 FIXME("MultisampleQuality set to %ld, substituting 0 \n" , MultisampleQuality);
672 MultisampleQuality=0;
675 /** FIXME: Check that the format is supported
677 *******************************/
679 /* Non-power2 support */
681 /* Find the nearest pow2 match */
682 pow2Width = pow2Height = 1;
683 while (pow2Width < Width) pow2Width <<= 1;
684 while (pow2Height < Height) pow2Height <<= 1;
686 if (pow2Width > Width || pow2Height > Height) {
687 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
688 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
689 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
690 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d) \n",
691 This, Width, Height);
692 return D3DERR_NOTAVAILABLE;
696 /** Check against the maximum texture sizes supported by the video card **/
697 if (pow2Width > GL_LIMITS(texture_size) || pow2Height > GL_LIMITS(texture_size)) {
698 /* one of three options
699 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)
700 2: Set the texture to the maxium size (bad idea)
701 3: WARN and return D3DERR_NOTAVAILABLE;
703 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));
704 return D3DERR_NOTAVAILABLE;
709 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
710 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
712 *********************************/
713 if (Format == WINED3DFMT_DXT1) {
714 /* DXT1 is half byte per pixel */
715 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4)) >> 1;
717 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
718 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
719 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4));
721 Size = (pow2Width * D3DFmtGetBpp(This, Format)) * pow2Height;
724 /** Create the and initilise surface resource **/
725 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,D3DRTYPE_SURFACE, Size)
726 object->container = (IUnknown*) This;
728 object->currentDesc.Width = Width;
729 object->currentDesc.Height = Height;
730 object->currentDesc.MultiSampleType = MultiSample;
731 object->currentDesc.MultiSampleQuality = MultisampleQuality;
733 /* Setup some glformat defaults */
734 object->glDescription.glFormat = D3DFmt2GLFmt(This, object->resource.format);
735 object->glDescription.glFormatInternal = D3DFmt2GLIntFmt(This, object->resource.format);
736 object->glDescription.glType = D3DFmt2GLType(This, object->resource.format);
737 object->glDescription.textureName = 0;
738 object->glDescription.level = Level;
739 object->glDescription.target = GL_TEXTURE_2D;
742 object->pow2Width = pow2Width;
743 object->pow2Height = pow2Height;
744 object->nonpow2 = (pow2Width != Width || pow2Height != Height) ? TRUE : FALSE;
745 object->discard = Discard;
746 object->activeLock = FALSE;
747 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
748 object->pow2Size = (pow2Width * object->bytesPerPixel) * pow2Height;
750 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
752 TRACE("Pool %d %d %d %d",Pool, D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM);
754 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
755 * this function is too deap to need to care about things like this.
756 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
757 * ****************************************/
759 case D3DPOOL_SCRATCH:
760 if(Lockable == FALSE)
761 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
762 which are mutually exclusive, setting lockable to true\n");
765 case D3DPOOL_SYSTEMMEM:
766 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
767 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
768 case D3DPOOL_MANAGED:
769 if(Usage == D3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
770 Usage of DYNAMIC which are mutually exclusive, not doing \
771 anything just telling you.\n");
773 case D3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
774 if(!(Usage & D3DUSAGE_DYNAMIC) && !(Usage & D3DUSAGE_RENDERTARGET)
775 && !(Usage && D3DUSAGE_DEPTHSTENCIL ) && Lockable == TRUE)
776 FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
779 FIXME("(%p) Unknown pool %d\n", This, Pool);
783 if (Usage & D3DUSAGE_RENDERTARGET && Pool != D3DPOOL_DEFAULT) {
784 FIXME("Trying to create a render target that isn't in the default pool\n");
788 object->locked = FALSE;
789 object->lockable = (WINED3DFMT_D16_LOCKABLE == Format) ? TRUE : Lockable;
791 /* mark the texture as dirty so that it get's loaded first time around*/
792 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
793 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
794 This, Width, Height, Format, debug_d3dformat(Format),
795 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
800 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
801 DWORD Usage, WINED3DFORMAT Format, D3DPOOL Pool,
802 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
803 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
805 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
806 IWineD3DTextureImpl *object;
811 unsigned int pow2Width = Width;
812 unsigned int pow2Height = Height;
815 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) .... \n", This, Width, Height, Levels, Usage);
817 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, D3DRTYPE_TEXTURE, 0);
818 D3DINITILIZEBASETEXTURE(object->baseTexture);
819 object->width = Width;
820 object->height = Height;
822 /** Non-power2 support **/
823 /* Find the nearest pow2 match */
824 pow2Width = pow2Height = 1;
825 while (pow2Width < Width) pow2Width <<= 1;
826 while (pow2Height < Height) pow2Height <<= 1;
828 /** FIXME: add support for real non-power-two if it's provided by the video card **/
829 /* Precalculated scaling for 'faked' non power of two texture coords */
830 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
831 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
832 TRACE(" xf(%f) yf(%f) \n", object->pow2scalingFactorX, object->pow2scalingFactorY);
834 /* Calculate levels for mip mapping */
836 TRACE("calculating levels %d\n", object->baseTexture.levels);
837 object->baseTexture.levels++;
840 while (tmpW > 1 && tmpH > 1) {
841 tmpW = max(1, tmpW >> 1);
842 tmpH = max(1, tmpH >> 1);
843 object->baseTexture.levels++;
845 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
848 /* Generate all the surfaces */
851 for (i = 0; i < object->baseTexture.levels; i++)
853 /* use the callback to create the texture surface */
854 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
857 FIXME("Failed to create surface %p \n",object);
859 for (j = 0 ; j < i ; j++) {
860 IWineD3DSurface_Release(object->surfaces[j]);
862 /* heap free object */
863 HeapFree(GetProcessHeap(), 0, object);
869 IWineD3DSurface_SetContainer(object->surfaces[i], (IUnknown *)object);
870 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
871 /* calculate the next mipmap level */
872 tmpW = max(1, tmpW >> 1);
873 tmpH = max(1, tmpH >> 1);
876 TRACE("(%p) : Created texture %p\n", This, object);
880 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
881 UINT Width, UINT Height, UINT Depth,
882 UINT Levels, DWORD Usage,
883 WINED3DFORMAT Format, D3DPOOL Pool,
884 IWineD3DVolumeTexture **ppVolumeTexture,
885 HANDLE *pSharedHandle, IUnknown *parent,
886 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
888 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
889 IWineD3DVolumeTextureImpl *object;
895 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, D3DRTYPE_VOLUMETEXTURE, 0);
896 D3DINITILIZEBASETEXTURE(object->baseTexture);
898 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
899 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
901 object->width = Width;
902 object->height = Height;
903 object->depth = Depth;
905 /* Calculate levels for mip mapping */
907 object->baseTexture.levels++;
911 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
912 tmpW = max(1, tmpW >> 1);
913 tmpH = max(1, tmpH >> 1);
914 tmpD = max(1, tmpD >> 1);
915 object->baseTexture.levels++;
917 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
920 /* Generate all the surfaces */
925 for (i = 0; i < object->baseTexture.levels; i++)
927 /* Create the volume */
928 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
929 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
931 /* Set it's container to this object */
932 IWineD3DVolume_SetContainer(object->volumes[i], (IUnknown *)object);
934 /* calcualte the next mipmap level */
935 tmpW = max(1, tmpW >> 1);
936 tmpH = max(1, tmpH >> 1);
937 tmpD = max(1, tmpD >> 1);
940 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
941 TRACE("(%p) : Created volume texture %p\n", This, object);
945 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
946 UINT Width, UINT Height, UINT Depth,
948 WINED3DFORMAT Format, D3DPOOL Pool,
949 IWineD3DVolume** ppVolume,
950 HANDLE* pSharedHandle, IUnknown *parent) {
952 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
953 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
955 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, D3DRTYPE_VOLUME, ((Width * D3DFmtGetBpp(This, Format)) * Height * Depth))
957 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
958 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
960 object->currentDesc.Width = Width;
961 object->currentDesc.Height = Height;
962 object->currentDesc.Depth = Depth;
963 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
965 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
966 object->lockable = TRUE;
967 object->locked = FALSE;
968 memset(&object->lockedBox, 0, sizeof(D3DBOX));
969 object->dirty = TRUE;
971 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
974 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
975 UINT Levels, DWORD Usage,
976 WINED3DFORMAT Format, D3DPOOL Pool,
977 IWineD3DCubeTexture **ppCubeTexture,
978 HANDLE *pSharedHandle, IUnknown *parent,
979 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
981 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
982 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
986 unsigned int pow2EdgeLength = EdgeLength;
988 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, D3DRTYPE_CUBETEXTURE, 0);
989 D3DINITILIZEBASETEXTURE(object->baseTexture);
991 TRACE("(%p) Create Cube Texture \n", This);
993 /** Non-power2 support **/
995 /* Find the nearest pow2 match */
997 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
999 object->edgeLength = EdgeLength;
1000 /* TODO: support for native non-power 2 */
1001 /* Precalculated scaling for 'faked' non power of two texture coords */
1002 object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
1004 /* Calculate levels for mip mapping */
1006 object->baseTexture.levels++;
1009 tmpW = max(1, tmpW >> 1);
1010 object->baseTexture.levels++;
1012 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1015 /* Generate all the surfaces */
1017 for (i = 0; i < object->baseTexture.levels; i++) {
1019 /* Create the 6 faces */
1020 for (j = 0; j < 6; j++) {
1022 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
1023 i /* Level */, &object->surfaces[j][i],pSharedHandle);
1029 for (l = 0; l < j; l++) {
1030 IWineD3DSurface_Release(object->surfaces[j][i]);
1032 for (k = 0; k < i; k++) {
1033 for (l = 0; l < 6; l++) {
1034 IWineD3DSurface_Release(object->surfaces[l][j]);
1038 FIXME("(%p) Failed to create surface\n",object);
1039 HeapFree(GetProcessHeap(),0,object);
1040 *ppCubeTexture = NULL;
1043 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IUnknown *)object);
1044 TRACE("Created surface level %d @ %p, \n", i, object->surfaces[j][i]);
1046 tmpW = max(1, tmpW >> 1);
1049 TRACE("(%p) : Created Cube Texture %p\n", This, object);
1050 *ppCubeTexture = (IWineD3DCubeTexture *) object;
1054 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1055 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1056 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1058 if (NULL == ppQuery) {
1059 /* Just a check to see if we support this type of query */
1060 HRESULT hr = D3DERR_NOTAVAILABLE;
1061 /* Lie and say everything is good (we can return ok fake data from a stub) */
1063 case WINED3DQUERYTYPE_VCACHE:
1064 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1065 case WINED3DQUERYTYPE_VERTEXSTATS:
1066 case WINED3DQUERYTYPE_EVENT:
1067 case WINED3DQUERYTYPE_TIMESTAMP:
1068 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1069 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1070 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1071 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1072 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1073 case WINED3DQUERYTYPE_PIXELTIMINGS:
1074 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1075 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1077 case WINED3DQUERYTYPE_OCCLUSION:
1078 TRACE("(%p) occlusion query\n", This);
1079 if (GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY))
1083 FIXME("(%p) Unhandled query type %d\n",This , Type);
1085 FIXME("(%p) : Stub request for query type %d returned %ld\n", This, Type, hr);
1089 D3DCREATEOBJECTINSTANCE(object, Query)
1090 object->type = Type;
1091 /* allocated the 'extended' data based on the type of query requested */
1093 case D3DQUERYTYPE_OCCLUSION:
1094 if(GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY)) {
1095 TRACE("(%p) Allocating data for an occlusion query\n", This);
1096 object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1099 case D3DQUERYTYPE_VCACHE:
1100 case D3DQUERYTYPE_RESOURCEMANAGER:
1101 case D3DQUERYTYPE_VERTEXSTATS:
1102 case D3DQUERYTYPE_EVENT:
1103 case D3DQUERYTYPE_TIMESTAMP:
1104 case D3DQUERYTYPE_TIMESTAMPDISJOINT:
1105 case D3DQUERYTYPE_TIMESTAMPFREQ:
1106 case D3DQUERYTYPE_PIPELINETIMINGS:
1107 case D3DQUERYTYPE_INTERFACETIMINGS:
1108 case D3DQUERYTYPE_VERTEXTIMINGS:
1109 case D3DQUERYTYPE_PIXELTIMINGS:
1110 case D3DQUERYTYPE_BANDWIDTHTIMINGS:
1111 case D3DQUERYTYPE_CACHEUTILIZATION:
1113 object->extendedData = 0;
1114 FIXME("(%p) Unhandled query type %d\n",This , Type);
1116 TRACE("(%p) : Created Query %p\n", This, object);
1120 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1121 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1123 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1124 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1125 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1128 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1130 XVisualInfo template;
1131 GLXContext oldContext;
1132 Drawable oldDrawable;
1133 HRESULT hr = D3D_OK;
1135 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1137 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1138 * does a device hold a reference to a swap chain giving them a lifetime of the device
1139 * or does the swap chain notify the device of it'd destruction.
1140 *******************************/
1142 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1144 /* Initialize other useful values */
1145 object->presentParms.BackBufferCount = 1; /* TODO:? support for gl_aux buffers */
1147 /*********************
1148 * Lookup the window Handle and the relating X window handle
1149 ********************/
1151 /* Setup hwnd we are using, plus which display this equates to */
1152 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1153 if (!object->win_handle) {
1154 object->win_handle = This->createParms.hFocusWindow;
1157 object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window" );
1158 hDc = GetDC(object->win_handle);
1159 object->display = get_display(hDc);
1160 ReleaseDC(object->win_handle, hDc);
1161 TRACE("Using a display of %p %p \n", object->display, hDc);
1163 if (NULL == object->display || NULL == hDc) {
1164 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1165 return D3DERR_NOTAVAILABLE;
1168 if (object->win == 0) {
1169 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1170 return D3DERR_NOTAVAILABLE;
1173 * Create an opengl context for the display visual
1174 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1175 * use different properties after that point in time. FIXME: How to handle when requested format
1176 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1177 * it chooses is identical to the one already being used!
1178 **********************************/
1180 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1183 /* Create a new context for this swapchain */
1184 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1185 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1186 (or the best possible if none is requested) */
1187 TRACE("Found x visual ID : %ld\n", template.visualid);
1189 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1190 if (NULL == object->visInfo) {
1191 ERR("cannot really get XVisual\n");
1193 return D3DERR_NOTAVAILABLE;
1196 /* Write out some debug info about the visual/s */
1197 TRACE("Using x visual ID : %ld\n", template.visualid);
1198 TRACE(" visual info: %p\n", object->visInfo);
1199 TRACE(" num items : %d\n", num);
1200 for (n = 0;n < num; n++) {
1201 TRACE("=====item=====: %d\n", n + 1);
1202 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1203 TRACE(" screen : %d\n", object->visInfo[n].screen);
1204 TRACE(" depth : %u\n", object->visInfo[n].depth);
1205 TRACE(" class : %d\n", object->visInfo[n].class);
1206 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1207 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1208 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1209 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1210 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1211 /* log some extra glx info */
1212 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1213 TRACE(" gl_aux_buffers : %d\n", value);
1214 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1215 TRACE(" gl_buffer_size : %d\n", value);
1216 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1217 TRACE(" gl_red_size : %d\n", value);
1218 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1219 TRACE(" gl_green_size : %d\n", value);
1220 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1221 TRACE(" gl_blue_size : %d\n", value);
1222 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1223 TRACE(" gl_alpha_size : %d\n", value);
1224 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1225 TRACE(" gl_depth_size : %d\n", value);
1226 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1227 TRACE(" gl_stencil_size : %d\n", value);
1229 /* Now choose a simila visual ID*/
1231 #ifdef USE_CONTEXT_MANAGER
1233 /** TODO: use a context mamager **/
1237 IWineD3DSwapChain *implSwapChain;
1238 if (D3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1239 /* The first time around we create the context that is shared with all other swapchains and render targets */
1240 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1241 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1244 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1245 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1246 /* and create a new context with the implicit swapchains context as the shared context */
1247 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1248 IWineD3DSwapChain_Release(implSwapChain);
1253 XFree(object->visInfo);
1254 object->visInfo = NULL;
1256 if (NULL == object->glCtx) {
1257 ERR("cannot create glxContext\n");
1259 return D3DERR_NOTAVAILABLE;
1263 if (object->glCtx == NULL) {
1264 ERR("Error in context creation !\n");
1265 return D3DERR_INVALIDCALL;
1267 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1268 object->win_handle, object->glCtx, object->win, object->visInfo);
1271 /*********************
1272 * Windowed / Fullscreen
1273 *******************/
1276 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1277 * so we should really check to see if their is a fullscreen swapchain already
1278 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1279 **************************************/
1281 if (!*(pPresentationParameters->Windowed)) {
1287 /* Get info on the current display setup */
1288 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1289 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1292 /* Change the display settings */
1293 memset(&devmode, 0, sizeof(DEVMODEW));
1294 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1295 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1296 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1297 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1298 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1299 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1301 /* Make popup window */
1302 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1303 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1304 *(pPresentationParameters->BackBufferWidth),
1305 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1311 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1312 * then the corresponding dimension of the client area of the hDeviceWindow
1313 * (or the focus window, if hDeviceWindow is NULL) is taken.
1314 **********************/
1316 if (*(pPresentationParameters->Windowed) &&
1317 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1318 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1321 GetClientRect(object->win_handle, &Rect);
1323 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1324 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1325 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1327 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1328 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1329 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1333 /*********************
1334 * finish off parameter initialization
1335 *******************/
1337 /* Put the correct figures in the presentation parameters */
1338 TRACE("Coppying accross presentaion paraneters\n");
1339 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1340 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1341 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1342 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1343 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1344 object->presentParms.MultiSampleQuality = *(pPresentationParameters->MultiSampleQuality);
1345 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1346 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1347 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1348 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1349 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1350 object->presentParms.Flags = *(pPresentationParameters->Flags);
1351 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1352 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1355 /*********************
1356 * Create the back, front and stencil buffers
1357 *******************/
1358 TRACE("calling rendertarget CB\n");
1359 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1360 object->presentParms.BackBufferWidth,
1361 object->presentParms.BackBufferHeight,
1362 object->presentParms.BackBufferFormat,
1363 object->presentParms.MultiSampleType,
1364 object->presentParms.MultiSampleQuality,
1365 TRUE /* Lockable */,
1366 &object->frontBuffer,
1367 NULL /* pShared (always null)*/);
1368 if (object->frontBuffer != NULL)
1369 IWineD3DSurface_SetContainer(object->frontBuffer, (IUnknown *)object);
1370 TRACE("calling rendertarget CB\n");
1371 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1372 object->presentParms.BackBufferWidth,
1373 object->presentParms.BackBufferHeight,
1374 object->presentParms.BackBufferFormat,
1375 object->presentParms.MultiSampleType,
1376 object->presentParms.MultiSampleQuality,
1377 TRUE /* Lockable */,
1378 &object->backBuffer,
1379 NULL /* pShared (always null)*/);
1380 if (object->backBuffer != NULL)
1381 IWineD3DSurface_SetContainer(object->backBuffer, (IUnknown *)object);
1383 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1384 if (pPresentationParameters->EnableAutoDepthStencil) {
1385 TRACE("Creating depth stencil buffer\n");
1386 if (This->depthStencilBuffer == NULL ) {
1387 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1388 object->presentParms.BackBufferWidth,
1389 object->presentParms.BackBufferHeight,
1390 object->presentParms.AutoDepthStencilFormat,
1391 object->presentParms.MultiSampleType,
1392 object->presentParms.MultiSampleQuality,
1393 FALSE /* FIXME: Discard */,
1394 &This->depthStencilBuffer,
1395 NULL /* pShared (always null)*/ );
1396 if (This->depthStencilBuffer != NULL)
1397 IWineD3DSurface_SetContainer(This->depthStencilBuffer, (IUnknown *)iface);
1400 /** TODO: A check on width, height and multisample types
1401 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1402 ****************************/
1403 object->wantsDepthStencilBuffer = TRUE;
1405 object->wantsDepthStencilBuffer = FALSE;
1408 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1411 /*********************
1412 * init the default renderTarget management
1413 *******************/
1414 object->drawable = object->win;
1415 object->render_ctx = object->glCtx;
1418 /*********************
1419 * Setup some defaults and clear down the buffers
1420 *******************/
1422 /** save current context and drawable **/
1423 oldContext = glXGetCurrentContext();
1424 oldDrawable = glXGetCurrentDrawable();
1426 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1427 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1428 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1430 checkGLcall("glXMakeCurrent");
1432 TRACE("Setting up the screen\n");
1433 /* Clear the screen */
1434 glClearColor(0.0, 0.0, 0.0, 0.0);
1435 checkGLcall("glClearColor");
1438 glClearStencil(0xffff);
1440 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1441 checkGLcall("glClear");
1443 glColor3f(1.0, 1.0, 1.0);
1444 checkGLcall("glColor3f");
1446 glEnable(GL_LIGHTING);
1447 checkGLcall("glEnable");
1449 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1450 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1452 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1453 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1455 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1456 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1458 /* switch back to the original context (if there was one)*/
1459 if (This->swapchains != NULL) {
1460 /** TODO: restore the context and drawable **/
1461 glXMakeCurrent(object->display, oldDrawable, oldContext);
1466 { /* Finally add the swapchain to the end of the devices' swapchain list */
1467 SwapChainList **nextSwapchain;
1468 nextSwapchain = &This->swapchains;
1469 while (*nextSwapchain != NULL) {
1470 nextSwapchain = &((*nextSwapchain)->next);
1472 (*nextSwapchain) = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->swapchains));
1473 (*nextSwapchain)->swapchain = (IWineD3DSwapChain *)object;
1475 TRACE("Set swapchain to %p\n", object);
1476 } else { /* something went wrong so clean up */
1477 IUnknown* bufferParent;
1478 if (object->frontBuffer) {
1479 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1480 IUnknown_Release(bufferParent); /* once for the get parent */
1481 if (IUnknown_Release(bufferParent) > 0) {
1482 FIXME("(%p) Something's still holding the front buffer\n",This);
1485 if (object->backBuffer) {
1486 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1487 IUnknown_Release(bufferParent); /* once for the get parent */
1488 if (IUnknown_Release(bufferParent) > 0) {
1489 FIXME("(%p) Something's still holding the back buffer\n",This);
1492 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1493 /* Clean up the context */
1494 /* check that we are the current context first (we shouldn't be though!) */
1495 if (object->glCtx != 0) {
1496 if(glXGetCurrentContext() == object->glCtx) {
1497 glXMakeCurrent(object->display, None, NULL);
1499 glXDestroyContext(object->display, object->glCtx);
1501 HeapFree(GetProcessHeap(), 0, object);
1508 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1509 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1510 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1511 unsigned int numberOfSwapChains = 0;
1512 SwapChainList *swapchain;
1514 swapchain = This->swapchains;
1515 /* itterate through the list to get a count */
1516 while (swapchain != NULL) {
1517 swapchain = swapchain->next;
1518 numberOfSwapChains++;
1521 TRACE("(%p) returning %d\n", This, numberOfSwapChains);
1522 return numberOfSwapChains;
1525 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1526 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1527 SwapChainList *swapchain;
1528 HRESULT hr = D3DERR_INVALIDCALL;
1529 swapchain = This->swapchains;
1530 TRACE("(%p) : swapchain %d \n", This, iSwapChain);
1533 TRACE("(%p) Finding swapchain %d\n", This, iSwapChain);
1534 while (iSwapChain > 0 && swapchain != NULL) {
1535 swapchain = swapchain->next;
1539 if (iSwapChain > 0 || swapchain == NULL) {
1540 FIXME("(%p) Unable to find swapchain %d\n", This, iSwapChain);
1543 /** TODO: move off to a linkesList implementation **/
1544 *pSwapChain = swapchain->swapchain;
1545 IWineD3DSwapChain_AddRef(*pSwapChain);
1549 TRACE("(%p) returning %p\n", This, *pSwapChain);
1553 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
1554 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1556 FIXME("(%p) : Stub\n",This);
1562 * Vertex Declaration
1564 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1565 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1566 IWineD3DVertexDeclarationImpl *object = NULL;
1567 HRESULT hr = D3D_OK;
1568 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1569 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1572 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1577 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1578 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DVertexShader** ppVertexShader, IUnknown *parent) {
1579 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1580 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1581 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1583 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1584 IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1589 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DPixelShader** ppPixelShader, IUnknown *parent) {
1590 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1591 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1593 D3DCREATEOBJECTINSTANCE(object, PixelShader)
1595 object->function = pFunction;
1596 #else /* TODO: pixel shader set function */
1597 IWineD3DPixelShaderImpl_SetFuction(*ppPixelShader, pFunction);
1599 FIXME("(%p) : STUB: Created Pixel shader %p\n", This, ppPixelShader);
1605 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice* iface, IWineD3D** ppD3D) {
1606 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1607 *ppD3D= This->wineD3D;
1608 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1609 IWineD3D_AddRef(*ppD3D);
1613 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1614 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1615 * Into the video ram as possible and seeing how many fit
1616 * you can also get the correct initial value from via X and ATI's driver
1617 *******************/
1618 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1619 static BOOL showfixmes = TRUE;
1621 FIXME("(%p) : stub, emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1622 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1625 TRACE("(%p) : emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1626 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1627 /* videomemory is simulated videomemory + AGP memory left */
1628 return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1636 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1637 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1639 /* Update the current state block */
1640 This->updateStateBlock->fvf = fvf;
1641 This->updateStateBlock->changed.fvf = TRUE;
1642 This->updateStateBlock->set.fvf = TRUE;
1644 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1645 /* clear down the vertex declaration
1646 NOTE: Axis and Allies doesn't work properly otherwise
1647 (may be a stateblock problem though!)
1649 /* No difference if recording or not */
1650 return IWineD3DDevice_SetVertexDeclaration(iface, NULL);
1655 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1656 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1657 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1658 *pfvf = This->stateBlock->fvf;
1663 * Get / Set Stream Source
1665 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1666 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1667 IWineD3DVertexBuffer *oldSrc;
1669 /**TODO: instance and index data, see
1670 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1672 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
1675 /* D3d9 only, but shouldn't hurt d3d8 */
1678 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1680 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1681 FIXME("stream index data not supported\n");
1683 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1684 FIXME("stream instance data not supported\n");
1688 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1690 if (StreamNumber >= MAX_STREAMS) {
1691 WARN("Stream out of range %d\n", StreamNumber);
1692 return D3DERR_INVALIDCALL;
1695 oldSrc = This->stateBlock->streamSource[StreamNumber];
1696 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1698 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
1699 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
1700 This->updateStateBlock->streamStride[StreamNumber] = Stride;
1701 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
1702 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
1703 This->updateStateBlock->streamFlags[StreamNumber] = streamFlags;
1705 /* Handle recording of state blocks */
1706 if (This->isRecordingState) {
1707 TRACE("Recording... not performing anything\n");
1711 /* Not recording... */
1712 /* Need to do a getParent and pass the reffs up */
1713 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
1714 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
1715 so for now, just count internally */
1716 if (pStreamData != NULL) {
1717 IUnknown *newVertexBufferParent;
1718 /* GetParent will add a ref, so leave it hanging until the vertex buffer is cleared */
1719 IWineD3DVertexBuffer_GetParent(pStreamData, &newVertexBufferParent);
1721 if (oldSrc != NULL) {
1722 IUnknown *oldVertexBufferParent;
1723 IWineD3DVertexBuffer_GetParent(oldSrc, &oldVertexBufferParent);
1724 IUnknown_Release(oldVertexBufferParent);
1725 IUnknown_Release(oldVertexBufferParent);
1731 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
1732 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1735 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
1736 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
1739 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1741 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1742 FIXME("stream index data not supported\n");
1744 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1745 FIXME("stream instance data not supported\n");
1749 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1751 if (StreamNumber >= MAX_STREAMS) {
1752 WARN("Stream out of range %d\n", StreamNumber);
1753 return D3DERR_INVALIDCALL;
1755 *pStream = This->stateBlock->streamSource[StreamNumber];
1756 *pStride = This->stateBlock->streamStride[StreamNumber];
1757 *pOffset = This->stateBlock->streamOffset[StreamNumber];
1759 if (*pStream == NULL) {
1760 FIXME("Attempting to get an empty stream %d, returning D3DERR_INVALIDCALL\n", StreamNumber);
1761 return D3DERR_INVALIDCALL;
1764 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
1768 /*Should be quite easy, just an extension of vertexdata
1770 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1772 The divider is a bit odd though
1774 VertexOffset = StartVertex / Divider * StreamStride +
1775 VertexIndex / Divider * StreamStride + StreamOffset
1778 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
1779 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1781 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
1782 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (D3DSTREAMSOURCE_INSTANCEDATA | D3DSTREAMSOURCE_INDEXEDDATA );
1784 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
1785 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
1786 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
1788 if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
1789 FIXME("Stream indexing not fully supported\n");
1795 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
1796 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1798 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
1799 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
1801 TRACE("(%p) : returning %d\n", This, *Divider);
1807 * Get / Set & Multiply Transform
1809 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1810 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1812 /* Most of this routine, comments included copied from ddraw tree initially: */
1813 TRACE("(%p) : Transform State=%d\n", This, d3dts);
1815 /* Handle recording of state blocks */
1816 if (This->isRecordingState) {
1817 TRACE("Recording... not performing anything\n");
1818 This->updateStateBlock->changed.transform[d3dts] = TRUE;
1819 This->updateStateBlock->set.transform[d3dts] = TRUE;
1820 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1825 * If the new matrix is the same as the current one,
1826 * we cut off any further processing. this seems to be a reasonable
1827 * optimization because as was noticed, some apps (warcraft3 for example)
1828 * tend towards setting the same matrix repeatedly for some reason.
1830 * From here on we assume that the new matrix is different, wherever it matters.
1832 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1833 TRACE("The app is setting the same matrix over again\n");
1836 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1840 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1841 where ViewMat = Camera space, WorldMat = world space.
1843 In OpenGL, camera and world space is combined into GL_MODELVIEW
1844 matrix. The Projection matrix stay projection matrix.
1847 /* Capture the times we can just ignore the change for now */
1848 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1849 This->modelview_valid = FALSE;
1852 } else if (d3dts == D3DTS_PROJECTION) {
1853 This->proj_valid = FALSE;
1856 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1857 /* Indexed Vertex Blending Matrices 256 -> 511 */
1858 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1859 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1863 /* Now we really are going to have to change a matrix */
1866 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1867 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
1868 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1871 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1872 * NOTE: We have to reset the positions even if the light/plane is not currently
1873 * enabled, since the call to enable it will not reset the position.
1874 * NOTE2: Apparently texture transforms do NOT need reapplying
1877 PLIGHTINFOEL *lightChain = NULL;
1878 This->modelview_valid = FALSE;
1879 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
1881 glMatrixMode(GL_MODELVIEW);
1882 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1884 glLoadMatrixf((float *)lpmatrix);
1885 checkGLcall("glLoadMatrixf(...)");
1888 lightChain = This->stateBlock->lights;
1889 while (lightChain && lightChain->glIndex != -1) {
1890 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1891 checkGLcall("glLightfv posn");
1892 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1893 checkGLcall("glLightfv dirn");
1894 lightChain = lightChain->next;
1897 /* Reset Clipping Planes if clipping is enabled */
1898 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1899 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1900 checkGLcall("glClipPlane");
1904 } else { /* What was requested!?? */
1905 WARN("invalid matrix specified: %i\n", d3dts);
1908 /* Release lock, all done */
1913 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1914 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1915 TRACE("(%p) : for Transform State %d\n", This, State);
1916 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1920 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1921 D3DMATRIX *mat = NULL;
1924 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1925 * below means it will be recorded in a state block change, but it
1926 * works regardless where it is recorded.
1927 * If this is found to be wrong, change to StateBlock.
1929 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1930 TRACE("(%p) : For state %u\n", This, State);
1932 if (State < HIGHEST_TRANSFORMSTATE)
1934 mat = &This->updateStateBlock->transforms[State];
1936 FIXME("Unhandled transform state!!\n");
1939 /* Copied from ddraw code: */
1940 temp.u.s._11 = (mat->u.s._11 * pMatrix->u.s._11) + (mat->u.s._21 * pMatrix->u.s._12) +
1941 (mat->u.s._31 * pMatrix->u.s._13) + (mat->u.s._41 * pMatrix->u.s._14);
1942 temp.u.s._21 = (mat->u.s._11 * pMatrix->u.s._21) + (mat->u.s._21 * pMatrix->u.s._22) +
1943 (mat->u.s._31 * pMatrix->u.s._23) + (mat->u.s._41 * pMatrix->u.s._24);
1944 temp.u.s._31 = (mat->u.s._11 * pMatrix->u.s._31) + (mat->u.s._21 * pMatrix->u.s._32) +
1945 (mat->u.s._31 * pMatrix->u.s._33) + (mat->u.s._41 * pMatrix->u.s._34);
1946 temp.u.s._41 = (mat->u.s._11 * pMatrix->u.s._41) + (mat->u.s._21 * pMatrix->u.s._42) +
1947 (mat->u.s._31 * pMatrix->u.s._43) + (mat->u.s._41 * pMatrix->u.s._44);
1949 temp.u.s._12 = (mat->u.s._12 * pMatrix->u.s._11) + (mat->u.s._22 * pMatrix->u.s._12) +
1950 (mat->u.s._32 * pMatrix->u.s._13) + (mat->u.s._42 * pMatrix->u.s._14);
1951 temp.u.s._22 = (mat->u.s._12 * pMatrix->u.s._21) + (mat->u.s._22 * pMatrix->u.s._22) +
1952 (mat->u.s._32 * pMatrix->u.s._23) + (mat->u.s._42 * pMatrix->u.s._24);
1953 temp.u.s._32 = (mat->u.s._12 * pMatrix->u.s._31) + (mat->u.s._22 * pMatrix->u.s._32) +
1954 (mat->u.s._32 * pMatrix->u.s._33) + (mat->u.s._42 * pMatrix->u.s._34);
1955 temp.u.s._42 = (mat->u.s._12 * pMatrix->u.s._41) + (mat->u.s._22 * pMatrix->u.s._42) +
1956 (mat->u.s._32 * pMatrix->u.s._43) + (mat->u.s._42 * pMatrix->u.s._44);
1958 temp.u.s._13 = (mat->u.s._13 * pMatrix->u.s._11) + (mat->u.s._23 * pMatrix->u.s._12) +
1959 (mat->u.s._33 * pMatrix->u.s._13) + (mat->u.s._43 * pMatrix->u.s._14);
1960 temp.u.s._23 = (mat->u.s._13 * pMatrix->u.s._21) + (mat->u.s._23 * pMatrix->u.s._22) +
1961 (mat->u.s._33 * pMatrix->u.s._23) + (mat->u.s._43 * pMatrix->u.s._24);
1962 temp.u.s._33 = (mat->u.s._13 * pMatrix->u.s._31) + (mat->u.s._23 * pMatrix->u.s._32) +
1963 (mat->u.s._33 * pMatrix->u.s._33) + (mat->u.s._43 * pMatrix->u.s._34);
1964 temp.u.s._43 = (mat->u.s._13 * pMatrix->u.s._41) + (mat->u.s._23 * pMatrix->u.s._42) +
1965 (mat->u.s._33 * pMatrix->u.s._43) + (mat->u.s._43 * pMatrix->u.s._44);
1967 temp.u.s._14 = (mat->u.s._14 * pMatrix->u.s._11) + (mat->u.s._24 * pMatrix->u.s._12) +
1968 (mat->u.s._34 * pMatrix->u.s._13) + (mat->u.s._44 * pMatrix->u.s._14);
1969 temp.u.s._24 = (mat->u.s._14 * pMatrix->u.s._21) + (mat->u.s._24 * pMatrix->u.s._22) +
1970 (mat->u.s._34 * pMatrix->u.s._23) + (mat->u.s._44 * pMatrix->u.s._24);
1971 temp.u.s._34 = (mat->u.s._14 * pMatrix->u.s._31) + (mat->u.s._24 * pMatrix->u.s._32) +
1972 (mat->u.s._34 * pMatrix->u.s._33) + (mat->u.s._44 * pMatrix->u.s._34);
1973 temp.u.s._44 = (mat->u.s._14 * pMatrix->u.s._41) + (mat->u.s._24 * pMatrix->u.s._42) +
1974 (mat->u.s._34 * pMatrix->u.s._43) + (mat->u.s._44 * pMatrix->u.s._44);
1976 /* Apply change via set transform - will reapply to eg. lights this way */
1977 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
1982 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
1984 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1985 you can reference any indexes you want as long as that number max are enabled at any
1986 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1987 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1988 but when recording, just build a chain pretty much of commands to be replayed. */
1990 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
1992 PLIGHTINFOEL *object, *temp;
1994 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1995 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1997 /* If recording state block, just add to end of lights chain */
1998 if (This->isRecordingState) {
1999 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2000 if (NULL == object) {
2001 return D3DERR_OUTOFVIDEOMEMORY;
2003 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2004 object->OriginalIndex = Index;
2005 object->glIndex = -1;
2006 object->changed = TRUE;
2008 /* Add to the END of the chain of lights changes to be replayed */
2009 if (This->updateStateBlock->lights == NULL) {
2010 This->updateStateBlock->lights = object;
2012 temp = This->updateStateBlock->lights;
2013 while (temp->next != NULL) temp=temp->next;
2014 temp->next = object;
2016 TRACE("Recording... not performing anything more\n");
2020 /* Ok, not recording any longer so do real work */
2021 object = This->stateBlock->lights;
2022 while (object != NULL && object->OriginalIndex != Index) object = object->next;
2024 /* If we didn't find it in the list of lights, time to add it */
2025 if (object == NULL) {
2026 PLIGHTINFOEL *insertAt,*prevPos;
2028 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2029 if (NULL == object) {
2030 return D3DERR_OUTOFVIDEOMEMORY;
2032 object->OriginalIndex = Index;
2033 object->glIndex = -1;
2035 /* Add it to the front of list with the idea that lights will be changed as needed
2036 BUT after any lights currently assigned GL indexes */
2037 insertAt = This->stateBlock->lights;
2039 while (insertAt != NULL && insertAt->glIndex != -1) {
2041 insertAt = insertAt->next;
2044 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2045 This->stateBlock->lights = object;
2046 } else if (insertAt == NULL) { /* End of list */
2047 prevPos->next = object;
2048 object->prev = prevPos;
2049 } else { /* Middle of chain */
2050 if (prevPos == NULL) {
2051 This->stateBlock->lights = object;
2053 prevPos->next = object;
2055 object->prev = prevPos;
2056 object->next = insertAt;
2057 insertAt->prev = object;
2061 /* Initialze the object */
2062 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,
2063 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2064 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2065 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2066 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2067 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2068 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2070 /* Save away the information */
2071 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2073 switch (pLight->Type) {
2074 case D3DLIGHT_POINT:
2076 object->lightPosn[0] = pLight->Position.x;
2077 object->lightPosn[1] = pLight->Position.y;
2078 object->lightPosn[2] = pLight->Position.z;
2079 object->lightPosn[3] = 1.0f;
2080 object->cutoff = 180.0f;
2084 case D3DLIGHT_DIRECTIONAL:
2086 object->lightPosn[0] = -pLight->Direction.x;
2087 object->lightPosn[1] = -pLight->Direction.y;
2088 object->lightPosn[2] = -pLight->Direction.z;
2089 object->lightPosn[3] = 0.0;
2090 object->exponent = 0.0f;
2091 object->cutoff = 180.0f;
2096 object->lightPosn[0] = pLight->Position.x;
2097 object->lightPosn[1] = pLight->Position.y;
2098 object->lightPosn[2] = pLight->Position.z;
2099 object->lightPosn[3] = 1.0;
2102 object->lightDirn[0] = pLight->Direction.x;
2103 object->lightDirn[1] = pLight->Direction.y;
2104 object->lightDirn[2] = pLight->Direction.z;
2105 object->lightDirn[3] = 1.0;
2108 * opengl-ish and d3d-ish spot lights use too different models for the
2109 * light "intensity" as a function of the angle towards the main light direction,
2110 * so we only can approximate very roughly.
2111 * however spot lights are rather rarely used in games (if ever used at all).
2112 * furthermore if still used, probably nobody pays attention to such details.
2114 if (pLight->Falloff == 0) {
2117 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2119 if (rho < 0.0001) rho = 0.0001f;
2120 object->exponent = -0.3/log(cos(rho/2));
2121 object->cutoff = pLight->Phi*90/M_PI;
2127 FIXME("Unrecognized light type %d\n", pLight->Type);
2130 /* Update the live definitions if the light is currently assigned a glIndex */
2131 if (object->glIndex != -1) {
2132 setup_light(iface, object->glIndex, object);
2137 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2138 PLIGHTINFOEL *lightInfo = NULL;
2139 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2140 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2142 /* Locate the light in the live lights */
2143 lightInfo = This->stateBlock->lights;
2144 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2146 if (lightInfo == NULL) {
2147 TRACE("Light information requested but light not defined\n");
2148 return D3DERR_INVALIDCALL;
2151 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
2156 * Get / Set Light Enable
2157 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2159 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2160 PLIGHTINFOEL *lightInfo = NULL;
2161 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2162 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2164 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2165 if (This->isRecordingState) {
2166 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2167 if (NULL == lightInfo) {
2168 return D3DERR_OUTOFVIDEOMEMORY;
2170 lightInfo->OriginalIndex = Index;
2171 lightInfo->glIndex = -1;
2172 lightInfo->enabledChanged = TRUE;
2174 /* Add to the END of the chain of lights changes to be replayed */
2175 if (This->updateStateBlock->lights == NULL) {
2176 This->updateStateBlock->lights = lightInfo;
2178 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2179 while (temp->next != NULL) temp=temp->next;
2180 temp->next = lightInfo;
2182 TRACE("Recording... not performing anything more\n");
2186 /* Not recording... So, locate the light in the live lights */
2187 lightInfo = This->stateBlock->lights;
2188 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2190 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2191 if (lightInfo == NULL) {
2192 D3DLIGHT9 lightParms;
2193 /* Warning - untested code :-) Prob safe to change fixme to a trace but
2194 wait until someone confirms it seems to work! */
2195 TRACE("Light enabled requested but light not defined, so defining one!\n");
2196 lightParms.Type = D3DLIGHT_DIRECTIONAL;
2197 lightParms.Diffuse.r = 1.0;
2198 lightParms.Diffuse.g = 1.0;
2199 lightParms.Diffuse.b = 1.0;
2200 lightParms.Diffuse.a = 0.0;
2201 lightParms.Specular.r = 0.0;
2202 lightParms.Specular.g = 0.0;
2203 lightParms.Specular.b = 0.0;
2204 lightParms.Specular.a = 0.0;
2205 lightParms.Ambient.r = 0.0;
2206 lightParms.Ambient.g = 0.0;
2207 lightParms.Ambient.b = 0.0;
2208 lightParms.Ambient.a = 0.0;
2209 lightParms.Position.x = 0.0;
2210 lightParms.Position.y = 0.0;
2211 lightParms.Position.z = 0.0;
2212 lightParms.Direction.x = 0.0;
2213 lightParms.Direction.y = 0.0;
2214 lightParms.Direction.z = 1.0;
2215 lightParms.Range = 0.0;
2216 lightParms.Falloff = 0.0;
2217 lightParms.Attenuation0 = 0.0;
2218 lightParms.Attenuation1 = 0.0;
2219 lightParms.Attenuation2 = 0.0;
2220 lightParms.Theta = 0.0;
2221 lightParms.Phi = 0.0;
2222 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
2224 /* Search for it again! Should be fairly quick as near head of list */
2225 lightInfo = This->stateBlock->lights;
2226 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2227 if (lightInfo == NULL) {
2228 FIXME("Adding default lights has failed dismally\n");
2229 return D3DERR_INVALIDCALL;
2233 /* OK, we now have a light... */
2234 if (Enable == FALSE) {
2236 /* If we are disabling it, check it was enabled, and
2237 still only do something if it has assigned a glIndex (which it should have!) */
2238 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2239 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2241 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2242 checkGLcall("glDisable GL_LIGHT0+Index");
2245 TRACE("Nothing to do as light was not enabled\n");
2247 lightInfo->lightEnabled = FALSE;
2250 /* We are enabling it. If it is enabled, it's really simple */
2251 if (lightInfo->lightEnabled) {
2253 TRACE("Nothing to do as light was enabled\n");
2255 /* If it already has a glIndex, it's still simple */
2256 } else if (lightInfo->glIndex != -1) {
2257 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2258 lightInfo->lightEnabled = TRUE;
2260 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2261 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2264 /* Otherwise got to find space - lights are ordered gl indexes first */
2266 PLIGHTINFOEL *bsf = NULL;
2267 PLIGHTINFOEL *pos = This->stateBlock->lights;
2268 PLIGHTINFOEL *prev = NULL;
2272 /* Try to minimize changes as much as possible */
2273 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2275 /* Try to remember which index can be replaced if necessary */
2276 if (bsf==NULL && pos->lightEnabled == FALSE) {
2277 /* Found a light we can replace, save as best replacement */
2281 /* Step to next space */
2287 /* If we have too many active lights, fail the call */
2288 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2289 FIXME("Program requests too many concurrent lights\n");
2290 return D3DERR_INVALIDCALL;
2292 /* If we have allocated all lights, but not all are enabled,
2293 reuse one which is not enabled */
2294 } else if (Index == This->maxConcurrentLights) {
2295 /* use bsf - Simply swap the new light and the BSF one */
2296 PLIGHTINFOEL *bsfNext = bsf->next;
2297 PLIGHTINFOEL *bsfPrev = bsf->prev;
2300 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2301 if (bsf->prev != NULL) {
2302 bsf->prev->next = lightInfo;
2304 This->stateBlock->lights = lightInfo;
2307 /* If not side by side, lots of chains to update */
2308 if (bsf->next != lightInfo) {
2309 lightInfo->prev->next = bsf;
2310 bsf->next->prev = lightInfo;
2311 bsf->next = lightInfo->next;
2312 bsf->prev = lightInfo->prev;
2313 lightInfo->next = bsfNext;
2314 lightInfo->prev = bsfPrev;
2318 bsf->prev = lightInfo;
2319 bsf->next = lightInfo->next;
2320 lightInfo->next = bsf;
2321 lightInfo->prev = bsfPrev;
2326 glIndex = bsf->glIndex;
2328 lightInfo->glIndex = glIndex;
2329 lightInfo->lightEnabled = TRUE;
2331 /* Finally set up the light in gl itself */
2332 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2334 setup_light(iface, glIndex, lightInfo);
2335 glEnable(GL_LIGHT0 + glIndex);
2336 checkGLcall("glEnable GL_LIGHT0 new setup");
2339 /* If we reached the end of the allocated lights, with space in the
2340 gl lights, setup a new light */
2341 } else if (pos->glIndex == -1) {
2343 /* We reached the end of the allocated gl lights, so already
2344 know the index of the next one! */
2346 lightInfo->glIndex = glIndex;
2347 lightInfo->lightEnabled = TRUE;
2349 /* In an ideal world, it's already in the right place */
2350 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2351 /* No need to move it */
2353 /* Remove this light from the list */
2354 lightInfo->prev->next = lightInfo->next;
2355 if (lightInfo->next != NULL) {
2356 lightInfo->next->prev = lightInfo->prev;
2359 /* Add in at appropriate place (inbetween prev and pos) */
2360 lightInfo->prev = prev;
2361 lightInfo->next = pos;
2363 This->stateBlock->lights = lightInfo;
2365 prev->next = lightInfo;
2368 pos->prev = lightInfo;
2372 /* Finally set up the light in gl itself */
2373 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2375 setup_light(iface, glIndex, lightInfo);
2376 glEnable(GL_LIGHT0 + glIndex);
2377 checkGLcall("glEnable GL_LIGHT0 new setup");
2386 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2388 PLIGHTINFOEL *lightInfo = NULL;
2389 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2390 TRACE("(%p) : for idx(%ld)\n", This, Index);
2392 /* Locate the light in the live lights */
2393 lightInfo = This->stateBlock->lights;
2394 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2396 if (lightInfo == NULL) {
2397 TRACE("Light enabled state requested but light not defined\n");
2398 return D3DERR_INVALIDCALL;
2400 *pEnable = lightInfo->lightEnabled;
2405 * Get / Set Clip Planes
2407 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2408 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2409 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2411 /* Validate Index */
2412 if (Index >= GL_LIMITS(clipplanes)) {
2413 TRACE("Application has requested clipplane this device doesn't support\n");
2414 return D3DERR_INVALIDCALL;
2417 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2418 This->updateStateBlock->set.clipplane[Index] = TRUE;
2419 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2420 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2421 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2422 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2424 /* Handle recording of state blocks */
2425 if (This->isRecordingState) {
2426 TRACE("Recording... not performing anything\n");
2434 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2435 glMatrixMode(GL_MODELVIEW);
2437 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2439 TRACE("Clipplane [%f,%f,%f,%f]\n",
2440 This->updateStateBlock->clipplane[Index][0],
2441 This->updateStateBlock->clipplane[Index][1],
2442 This->updateStateBlock->clipplane[Index][2],
2443 This->updateStateBlock->clipplane[Index][3]);
2444 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2445 checkGLcall("glClipPlane");
2453 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2454 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2455 TRACE("(%p) : for idx %ld\n", This, Index);
2457 /* Validate Index */
2458 if (Index >= GL_LIMITS(clipplanes)) {
2459 TRACE("Application has requested clipplane this device doesn't support\n");
2460 return D3DERR_INVALIDCALL;
2463 pPlane[0] = This->stateBlock->clipplane[Index][0];
2464 pPlane[1] = This->stateBlock->clipplane[Index][1];
2465 pPlane[2] = This->stateBlock->clipplane[Index][2];
2466 pPlane[3] = This->stateBlock->clipplane[Index][3];
2471 * Get / Set Clip Plane Status
2472 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2474 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2475 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2476 FIXME("(%p) : stub\n", This);
2477 if (NULL == pClipStatus) {
2478 return D3DERR_INVALIDCALL;
2480 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2481 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2485 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2486 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2487 FIXME("(%p) : stub\n", This);
2488 if (NULL == pClipStatus) {
2489 return D3DERR_INVALIDCALL;
2491 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2492 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2497 * Get / Set Material
2498 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2500 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2501 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2503 This->updateStateBlock->changed.material = TRUE;
2504 This->updateStateBlock->set.material = TRUE;
2505 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2507 /* Handle recording of state blocks */
2508 if (This->isRecordingState) {
2509 TRACE("Recording... not performing anything\n");
2514 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2515 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2516 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2517 pMaterial->Ambient.b, pMaterial->Ambient.a);
2518 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2519 pMaterial->Specular.b, pMaterial->Specular.a);
2520 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2521 pMaterial->Emissive.b, pMaterial->Emissive.a);
2522 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2524 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2525 checkGLcall("glMaterialfv(GL_AMBIENT)");
2526 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2527 checkGLcall("glMaterialfv(GL_DIFFUSE)");
2529 /* Only change material color if specular is enabled, otherwise it is set to black */
2530 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2531 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2532 checkGLcall("glMaterialfv(GL_SPECULAR");
2534 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2535 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2536 checkGLcall("glMaterialfv(GL_SPECULAR");
2538 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2539 checkGLcall("glMaterialfv(GL_EMISSION)");
2540 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2541 checkGLcall("glMaterialf(GL_SHININESS");
2547 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2548 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2549 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2550 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2551 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2552 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2553 pMaterial->Ambient.b, pMaterial->Ambient.a);
2554 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2555 pMaterial->Specular.b, pMaterial->Specular.a);
2556 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2557 pMaterial->Emissive.b, pMaterial->Emissive.a);
2558 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2566 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2567 UINT BaseVertexIndex) {
2568 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2569 IWineD3DIndexBuffer *oldIdxs;
2571 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2572 oldIdxs = This->updateStateBlock->pIndexData;
2574 This->updateStateBlock->changed.indices = TRUE;
2575 This->updateStateBlock->set.indices = TRUE;
2576 This->updateStateBlock->pIndexData = pIndexData;
2577 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2579 /* Handle recording of state blocks */
2580 if (This->isRecordingState) {
2581 TRACE("Recording... not performing anything\n");
2586 IUnknown *indexBufferParent;
2587 /* Getting the parent causes a addRef... it gets released when the indicies are clear */
2588 IWineD3DIndexBuffer_GetParent(pIndexData, &indexBufferParent);
2591 IUnknown *indexBufferParent;
2592 IWineD3DIndexBuffer_GetParent(oldIdxs, &indexBufferParent);
2593 IUnknown_Release(indexBufferParent);
2594 IUnknown_Release(indexBufferParent);
2599 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2600 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2602 *ppIndexData = This->stateBlock->pIndexData;
2604 /* up ref count on ppindexdata */
2606 IWineD3DIndexBuffer_AddRef(*ppIndexData);
2607 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2608 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
2610 TRACE("(%p) No index data set\n", This);
2612 TRACE("Returning %p %d \n",*ppIndexData, *pBaseVertexIndex);
2618 * Get / Set Viewports
2620 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2621 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2623 TRACE("(%p)\n", This);
2624 This->updateStateBlock->changed.viewport = TRUE;
2625 This->updateStateBlock->set.viewport = TRUE;
2626 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2628 /* Handle recording of state blocks */
2629 if (This->isRecordingState) {
2630 TRACE("Recording... not performing anything\n");
2636 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2637 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2639 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2640 checkGLcall("glDepthRange");
2641 /* Note: GL requires lower left, DirectX supplies upper left */
2642 /* TODO: replace usage of renderTarget with context management */
2643 glViewport(pViewport->X,
2644 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2645 pViewport->Width, pViewport->Height);
2647 checkGLcall("glViewport");
2655 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2656 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2657 TRACE("(%p)\n", This);
2658 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2663 * Get / Set Render States
2664 * TODO: Verify against dx9 definitions
2666 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2668 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2669 DWORD OldValue = This->stateBlock->renderState[State];
2671 /* Simple way of referring to either a DWORD or a 4 byte float */
2677 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2678 This->updateStateBlock->changed.renderState[State] = TRUE;
2679 This->updateStateBlock->set.renderState[State] = TRUE;
2680 This->updateStateBlock->renderState[State] = Value;
2682 /* Handle recording of state blocks */
2683 if (This->isRecordingState) {
2684 TRACE("Recording... not performing anything\n");
2691 case WINED3DRS_FILLMODE :
2692 switch ((D3DFILLMODE) Value) {
2693 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2694 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2695 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2697 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
2699 checkGLcall("glPolygonMode (fillmode)");
2702 case WINED3DRS_LIGHTING :
2704 glEnable(GL_LIGHTING);
2705 checkGLcall("glEnable GL_LIGHTING");
2707 glDisable(GL_LIGHTING);
2708 checkGLcall("glDisable GL_LIGHTING");
2712 case WINED3DRS_ZENABLE :
2713 switch ((D3DZBUFFERTYPE) Value) {
2715 glDisable(GL_DEPTH_TEST);
2716 checkGLcall("glDisable GL_DEPTH_TEST");
2719 glEnable(GL_DEPTH_TEST);
2720 checkGLcall("glEnable GL_DEPTH_TEST");
2723 glEnable(GL_DEPTH_TEST);
2724 checkGLcall("glEnable GL_DEPTH_TEST");
2725 FIXME("W buffer is not well handled\n");
2728 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2732 case WINED3DRS_CULLMODE :
2734 /* If we are culling "back faces with clockwise vertices" then
2735 set front faces to be counter clockwise and enable culling
2737 switch ((D3DCULL) Value) {
2739 glDisable(GL_CULL_FACE);
2740 checkGLcall("glDisable GL_CULL_FACE");
2743 glEnable(GL_CULL_FACE);
2744 checkGLcall("glEnable GL_CULL_FACE");
2745 if (This->renderUpsideDown) {
2747 checkGLcall("glFrontFace GL_CW");
2749 glFrontFace(GL_CCW);
2750 checkGLcall("glFrontFace GL_CCW");
2752 glCullFace(GL_BACK);
2755 glEnable(GL_CULL_FACE);
2756 checkGLcall("glEnable GL_CULL_FACE");
2757 if (This->renderUpsideDown) {
2758 glFrontFace(GL_CCW);
2759 checkGLcall("glFrontFace GL_CCW");
2762 checkGLcall("glFrontFace GL_CW");
2764 glCullFace(GL_BACK);
2767 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2771 case WINED3DRS_SHADEMODE :
2772 switch ((D3DSHADEMODE) Value) {
2774 glShadeModel(GL_FLAT);
2775 checkGLcall("glShadeModel");
2777 case D3DSHADE_GOURAUD:
2778 glShadeModel(GL_SMOOTH);
2779 checkGLcall("glShadeModel");
2781 case D3DSHADE_PHONG:
2782 FIXME("D3DSHADE_PHONG isn't supported?\n");
2785 return D3DERR_INVALIDCALL;
2787 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2791 case WINED3DRS_DITHERENABLE :
2793 glEnable(GL_DITHER);
2794 checkGLcall("glEnable GL_DITHER");
2796 glDisable(GL_DITHER);
2797 checkGLcall("glDisable GL_DITHER");
2801 case WINED3DRS_ZWRITEENABLE :
2804 checkGLcall("glDepthMask");
2807 checkGLcall("glDepthMask");
2811 case WINED3DRS_ZFUNC :
2813 int glParm = GL_LESS;
2815 switch ((D3DCMPFUNC) Value) {
2816 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2817 case D3DCMP_LESS: glParm=GL_LESS; break;
2818 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2819 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2820 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2821 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2822 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2823 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2825 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2827 glDepthFunc(glParm);
2828 checkGLcall("glDepthFunc");
2832 case WINED3DRS_AMBIENT :
2835 D3DCOLORTOGLFLOAT4(Value, col);
2836 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2837 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2838 checkGLcall("glLightModel for MODEL_AMBIENT");
2843 case WINED3DRS_ALPHABLENDENABLE :
2846 checkGLcall("glEnable GL_BLEND");
2848 glDisable(GL_BLEND);
2849 checkGLcall("glDisable GL_BLEND");
2853 case WINED3DRS_SRCBLEND :
2854 case WINED3DRS_DESTBLEND :
2856 int newVal = GL_ZERO;
2858 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2859 case D3DBLEND_ONE : newVal = GL_ONE; break;
2860 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2861 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2862 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2863 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2864 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2865 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2866 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2867 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2868 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2870 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2871 This->srcBlend = newVal;
2872 This->dstBlend = newVal;
2875 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2876 This->srcBlend = newVal;
2877 This->dstBlend = newVal;
2880 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2883 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2884 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2885 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2886 glBlendFunc(This->srcBlend, This->dstBlend);
2888 checkGLcall("glBlendFunc");
2892 case WINED3DRS_ALPHATESTENABLE :
2894 glEnable(GL_ALPHA_TEST);
2895 checkGLcall("glEnable GL_ALPHA_TEST");
2897 glDisable(GL_ALPHA_TEST);
2898 checkGLcall("glDisable GL_ALPHA_TEST");
2902 case WINED3DRS_ALPHAFUNC :
2904 int glParm = GL_LESS;
2905 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2907 switch ((D3DCMPFUNC) Value) {
2908 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2909 case D3DCMP_LESS: glParm = GL_LESS; break;
2910 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2911 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2912 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2913 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2914 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2915 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2917 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2919 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2920 glAlphaFunc(glParm, ref);
2921 This->alphafunc = glParm;
2922 checkGLcall("glAlphaFunc");
2926 case WINED3DRS_ALPHAREF :
2928 int glParm = This->alphafunc;
2931 ref = ((float) Value) / 255.0f;
2932 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2933 glAlphaFunc(glParm, ref);
2934 checkGLcall("glAlphaFunc");
2938 case WINED3DRS_CLIPPLANEENABLE :
2939 case WINED3DRS_CLIPPING :
2941 /* Ensure we only do the changed clip planes */
2942 DWORD enable = 0xFFFFFFFF;
2943 DWORD disable = 0x00000000;
2945 /* If enabling / disabling all */
2946 if (State == WINED3DRS_CLIPPING) {
2948 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2951 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2955 enable = Value & ~OldValue;
2956 disable = ~Value & OldValue;
2959 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2960 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2961 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2962 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2963 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2964 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2966 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2967 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2968 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2969 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2970 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2971 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2973 /** update clipping status */
2975 This->stateBlock->clip_status.ClipUnion = 0;
2976 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
2978 This->stateBlock->clip_status.ClipUnion = 0;
2979 This->stateBlock->clip_status.ClipIntersection = 0;
2984 case WINED3DRS_BLENDOP :
2986 int glParm = GL_FUNC_ADD;
2988 switch ((D3DBLENDOP) Value) {
2989 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2990 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2991 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2992 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2993 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2995 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2997 TRACE("glBlendEquation(%x)\n", glParm);
2998 glBlendEquation(glParm);
2999 checkGLcall("glBlendEquation");
3003 case WINED3DRS_TEXTUREFACTOR :
3007 /* Note the texture color applies to all textures whereas
3008 GL_TEXTURE_ENV_COLOR applies to active only */
3010 D3DCOLORTOGLFLOAT4(Value, col);
3011 /* Set the default alpha blend color */
3012 glBlendColor(col[0], col[1], col[2], col[3]);
3013 checkGLcall("glBlendColor");
3015 /* And now the default texture color as well */
3016 for (i = 0; i < GL_LIMITS(textures); i++) {
3018 /* Note the D3DRS value applies to all textures, but GL has one
3019 per texture, so apply it now ready to be used! */
3020 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3023 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3026 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3027 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3032 case WINED3DRS_SPECULARENABLE :
3034 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3035 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3036 specular color. This is wrong:
3037 Separate specular color means the specular colour is maintained separately, whereas
3038 single color means it is merged in. However in both cases they are being used to
3040 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3041 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3045 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3046 checkGLcall("glMaterialfv");
3047 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3048 glEnable(GL_COLOR_SUM_EXT);
3050 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3052 checkGLcall("glEnable(GL_COLOR_SUM)");
3054 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3056 /* for the case of enabled lighting: */
3057 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3058 checkGLcall("glMaterialfv");
3060 /* for the case of disabled lighting: */
3061 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3062 glDisable(GL_COLOR_SUM_EXT);
3064 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3066 checkGLcall("glDisable(GL_COLOR_SUM)");
3071 case WINED3DRS_STENCILENABLE :
3073 glEnable(GL_STENCIL_TEST);
3074 checkGLcall("glEnable GL_STENCIL_TEST");
3076 glDisable(GL_STENCIL_TEST);
3077 checkGLcall("glDisable GL_STENCIL_TEST");
3081 case WINED3DRS_STENCILFUNC :
3083 int glParm = GL_ALWAYS;
3084 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3085 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3087 switch ((D3DCMPFUNC) Value) {
3088 case D3DCMP_NEVER: glParm=GL_NEVER; break;
3089 case D3DCMP_LESS: glParm=GL_LESS; break;
3090 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
3091 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
3092 case D3DCMP_GREATER: glParm=GL_GREATER; break;
3093 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
3094 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
3095 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
3097 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3099 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3100 This->stencilfunc = glParm;
3101 glStencilFunc(glParm, ref, mask);
3102 checkGLcall("glStencilFunc");
3106 case WINED3DRS_STENCILREF :
3108 int glParm = This->stencilfunc;
3110 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3113 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3114 glStencilFunc(glParm, ref, mask);
3115 checkGLcall("glStencilFunc");
3119 case WINED3DRS_STENCILMASK :
3121 int glParm = This->stencilfunc;
3122 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3123 GLuint mask = Value;
3125 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3126 glStencilFunc(glParm, ref, mask);
3127 checkGLcall("glStencilFunc");
3131 case WINED3DRS_STENCILFAIL :
3137 fail = StencilOp(Value);
3138 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
3139 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
3140 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
3141 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
3143 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3144 glStencilOp(fail, zfail, zpass);
3145 checkGLcall("glStencilOp(fail, zfail, zpass);");
3148 case WINED3DRS_STENCILZFAIL :
3154 glGetIntegerv(GL_STENCIL_FAIL, &fail);
3155 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
3156 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
3157 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
3158 zfail = StencilOp(Value);
3160 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3161 glStencilOp(fail, zfail, zpass);
3162 checkGLcall("glStencilOp(fail, zfail, zpass);");
3165 case WINED3DRS_STENCILPASS :
3171 glGetIntegerv(GL_STENCIL_FAIL, &fail);
3172 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
3173 zpass = StencilOp(Value);
3174 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
3175 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
3177 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3178 glStencilOp(fail, zfail, zpass);
3179 checkGLcall("glStencilOp(fail, zfail, zpass);");
3183 case WINED3DRS_STENCILWRITEMASK :
3185 glStencilMask(Value);
3186 TRACE("glStencilMask(%lu)\n", Value);
3187 checkGLcall("glStencilMask");
3191 case WINED3DRS_FOGENABLE :
3193 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
3195 checkGLcall("glEnable GL_FOG");
3198 checkGLcall("glDisable GL_FOG");
3203 case WINED3DRS_RANGEFOGENABLE :
3206 TRACE("Enabled RANGEFOG");
3208 TRACE("Disabled RANGEFOG");
3213 case WINED3DRS_FOGCOLOR :
3216 D3DCOLORTOGLFLOAT4(Value, col);
3217 /* Set the default alpha blend color */
3218 glFogfv(GL_FOG_COLOR, &col[0]);
3219 checkGLcall("glFog GL_FOG_COLOR");
3223 case WINED3DRS_FOGTABLEMODE :
3225 glHint(GL_FOG_HINT, GL_NICEST);
3227 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3228 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3229 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3230 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3232 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3234 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3235 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3240 case WINED3DRS_FOGVERTEXMODE :
3242 glHint(GL_FOG_HINT, GL_FASTEST);
3244 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3245 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3246 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3247 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3249 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3251 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3252 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
3257 case WINED3DRS_FOGSTART :
3260 glFogfv(GL_FOG_START, &tmpvalue.f);
3261 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3262 TRACE("Fog Start == %f\n", tmpvalue.f);
3266 case WINED3DRS_FOGEND :
3269 glFogfv(GL_FOG_END, &tmpvalue.f);
3270 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3271 TRACE("Fog End == %f\n", tmpvalue.f);
3275 case WINED3DRS_FOGDENSITY :
3278 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3279 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3283 case WINED3DRS_VERTEXBLEND :
3285 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3286 TRACE("Vertex Blending state to %ld\n", Value);
3290 case WINED3DRS_TWEENFACTOR :
3293 This->updateStateBlock->tween_factor = tmpvalue.f;
3294 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3298 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
3300 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3304 case WINED3DRS_COLORVERTEX :
3305 case WINED3DRS_DIFFUSEMATERIALSOURCE :
3306 case WINED3DRS_SPECULARMATERIALSOURCE :
3307 case WINED3DRS_AMBIENTMATERIALSOURCE :
3308 case WINED3DRS_EMISSIVEMATERIALSOURCE :
3310 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3312 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3313 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3314 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3315 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3316 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3317 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3319 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3320 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3321 Parm = GL_AMBIENT_AND_DIFFUSE;
3325 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3327 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3329 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3336 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3338 This->tracking_color = NEEDS_TRACKING;
3339 This->tracking_parm = Parm;
3343 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3348 case WINED3DRS_LINEPATTERN :
3354 tmppattern.d = Value;
3356 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3358 if (tmppattern.lp.wRepeatFactor) {
3359 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3360 checkGLcall("glLineStipple(repeat, linepattern)");
3361 glEnable(GL_LINE_STIPPLE);
3362 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3364 glDisable(GL_LINE_STIPPLE);
3365 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3370 case WINED3DRS_ZBIAS : /* D3D8 only */
3374 TRACE("ZBias value %f\n", tmpvalue.f);
3375 glPolygonOffset(0, -tmpvalue.f);
3376 checkGLcall("glPolygonOffset(0, -Value)");
3377 glEnable(GL_POLYGON_OFFSET_FILL);
3378 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3379 glEnable(GL_POLYGON_OFFSET_LINE);
3380 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3381 glEnable(GL_POLYGON_OFFSET_POINT);
3382 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3384 glDisable(GL_POLYGON_OFFSET_FILL);
3385 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3386 glDisable(GL_POLYGON_OFFSET_LINE);
3387 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3388 glDisable(GL_POLYGON_OFFSET_POINT);
3389 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3394 case WINED3DRS_NORMALIZENORMALS :
3396 glEnable(GL_NORMALIZE);
3397 checkGLcall("glEnable(GL_NORMALIZE);");
3399 glDisable(GL_NORMALIZE);
3400 checkGLcall("glDisable(GL_NORMALIZE);");
3404 case WINED3DRS_POINTSIZE :
3405 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
3407 TRACE("Set point size to %f\n", tmpvalue.f);
3408 glPointSize(tmpvalue.f);
3409 checkGLcall("glPointSize(...);");
3412 case WINED3DRS_POINTSIZE_MIN :
3413 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3415 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3416 checkGLcall("glPointParameterfEXT(...);");
3418 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3422 case WINED3DRS_POINTSIZE_MAX :
3423 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3425 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3426 checkGLcall("glPointParameterfEXT(...);");
3428 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3432 case WINED3DRS_POINTSCALE_A :
3433 case WINED3DRS_POINTSCALE_B :
3434 case WINED3DRS_POINTSCALE_C :
3435 case WINED3DRS_POINTSCALEENABLE :
3437 /* If enabled, supply the parameters, otherwise fall back to defaults */
3438 if (This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3439 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3440 /* TODO: Correct the scaling (this hack seems to be good enough for every demo that uses point sprites!) */
3441 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A])/ This->stateBlock->viewport.Width;
3442 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B])/ This->stateBlock->viewport.Height;
3443 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) *
3444 2.0f /(This->stateBlock->viewport.Width * This->stateBlock->viewport.Height);
3446 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3447 TRACE("glPointParameterfvARB %f %f %f\n", att[0], att[1], att[2]);
3448 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3449 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3451 TRACE("WINED3DRS_POINTSCALEENABLE not supported on this opengl\n");
3454 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3455 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3456 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3457 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3459 TRACE("WINED3DRS_POINTSCALEENABLE not supported, but not on either\n");
3465 case WINED3DRS_COLORWRITEENABLE :
3467 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3468 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3469 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3470 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3471 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3472 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3473 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3474 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3475 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3476 checkGLcall("glColorMask(...)");
3480 case WINED3DRS_LOCALVIEWER :
3482 GLint state = (Value) ? 1 : 0;
3483 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3484 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3488 case WINED3DRS_LASTPIXEL :
3491 TRACE("Last Pixel Drawing Enabled\n");
3493 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3498 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3501 TRACE("Software Processing Enabled\n");
3503 TRACE("Software Processing Disabled\n");
3508 /** not supported */
3509 case WINED3DRS_ZVISIBLE :
3512 return D3DERR_INVALIDCALL;
3514 case WINED3DRS_POINTSPRITEENABLE :
3515 /* TODO: NV_POINT_SPRITE */
3516 if (GL_SUPPORT(ARB_POINT_SPRITE)) {
3517 if (Value != FALSE) {
3518 /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
3519 glDisable(GL_POINT_SMOOTH);
3520 /* Centre the texture on the vertex */
3521 VTRACE("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
3522 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
3524 VTRACE("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
3525 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
3526 checkGLcall("glTexEnvf(...)");
3527 VTRACE("glEnable( GL_POINT_SPRITE_ARB )\n");
3528 glEnable( GL_POINT_SPRITE_ARB );
3529 checkGLcall("glEnable(...)");
3531 VTRACE("glDisable( GL_POINT_SPRITE_ARB )\n");
3532 glDisable( GL_POINT_SPRITE_ARB );
3533 checkGLcall("glEnable(...)");
3537 /* Unhandled yet...! */
3538 case WINED3DRS_EDGEANTIALIAS :
3539 case WINED3DRS_WRAP0 :
3540 case WINED3DRS_WRAP1 :
3541 case WINED3DRS_WRAP2 :
3542 case WINED3DRS_WRAP3 :
3543 case WINED3DRS_WRAP4 :
3544 case WINED3DRS_WRAP5 :
3545 case WINED3DRS_WRAP6 :
3546 case WINED3DRS_WRAP7 :
3548 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
3549 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
3550 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
3551 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
3552 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
3554 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
3556 TRACE("(%p)->(%d,%ld) Texture wraping not yet supported\n",This, State, Value);
3558 case WINED3DRS_MULTISAMPLEANTIALIAS :
3559 case WINED3DRS_MULTISAMPLEMASK :
3560 case WINED3DRS_PATCHEDGESTYLE :
3561 case WINED3DRS_PATCHSEGMENTS :
3562 case WINED3DRS_DEBUGMONITORTOKEN :
3563 case WINED3DRS_POSITIONORDER :
3564 case WINED3DRS_NORMALORDER :
3565 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3566 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3569 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3577 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3578 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3579 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3580 *pValue = This->stateBlock->renderState[State];
3585 * Get / Set Sampler States
3586 * TODO: Verify against dx9 definitions
3589 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3590 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3592 * SetSampler is designed to allow for more than the standard up to 8 textures
3593 * and Geforce has stopped supporting more than 6 standard textures in openGL.
3594 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3596 * http://developer.nvidia.com/object/General_FAQ.html#t6
3598 * There are two new settings for GForce
3600 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3601 * and the texture one:
3602 * GL_MAX_TEXTURE_COORDS_ARB.
3603 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3605 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
3606 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
3608 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
3609 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE, Sampler, Type);
3610 return D3DERR_INVALIDCALL;
3612 TRACE("Setting sampler %ld %d to %ld \n", Sampler, Type, Value);
3613 This->updateStateBlock->samplerState[Sampler][Type] = Value;
3614 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
3615 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
3617 /* Handle recording of state blocks */
3618 if (This->isRecordingState) {
3619 TRACE("Recording... not performing anything\n");
3626 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3627 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3628 /** TODO: check that sampler is in range **/
3629 *Value = This->updateStateBlock->samplerState[Sampler][Type];
3630 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
3635 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3636 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3639 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3640 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3641 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3647 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3648 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3649 GLint scissorBox[4];
3652 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3653 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
3654 pRect->left = scissorBox[1];
3655 pRect->top = scissorBox[2];
3656 pRect->right = scissorBox[1] + scissorBox[3];
3657 pRect->bottom = scissorBox[2] + scissorBox[4];
3658 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3663 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3664 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3666 TRACE("(%p) : pDecl=%p\n", This, pDecl);
3668 /* TODO: what about recording stateblocks? */
3669 if (NULL != pDecl) {
3670 IWineD3DVertexDeclaration_AddRef(pDecl);
3672 if (NULL != This->updateStateBlock->vertexDecl) {
3673 IWineD3DVertexDeclaration_Release(This->updateStateBlock->vertexDecl);
3675 This->updateStateBlock->vertexDecl = pDecl;
3676 This->updateStateBlock->changed.vertexDecl = TRUE;
3677 This->updateStateBlock->set.vertexDecl = TRUE;
3681 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3682 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3684 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3686 *ppDecl = This->updateStateBlock->vertexDecl;
3687 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3691 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
3692 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3693 IWineD3DVertexShader *oldShader = This->updateStateBlock->vertexShader;
3695 This->updateStateBlock->vertexShader = pShader;
3696 This->updateStateBlock->changed.vertexShader = TRUE;
3697 This->updateStateBlock->set.vertexShader = TRUE;
3699 if (This->isRecordingState) {
3700 TRACE("Recording... not performing anything\n");
3704 if (pShader != NULL) {
3705 IUnknown *newVertexShaderParent;
3706 /* GetParent will add a ref, so leave it hanging until the vertex buffer is cleared */
3707 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3708 IWineD3DVertexShader_GetParent(pShader, &newVertexShaderParent);
3710 TRACE("Clear down the shader\n");
3712 if (oldShader != NULL) {
3713 IUnknown *oldVertexShaderParent;
3714 IWineD3DVertexShader_GetParent(oldShader, &oldVertexShaderParent);
3715 IUnknown_Release(oldVertexShaderParent);
3716 IUnknown_Release(oldVertexShaderParent);
3719 * TODO: merge HAL shaders context switching from prototype
3724 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
3725 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3727 if (NULL == ppShader) {
3728 return D3DERR_INVALIDCALL;
3730 *ppShader = This->stateBlock->vertexShader;
3731 if( NULL != *ppShader)
3732 IWineD3DVertexShader_AddRef(*ppShader);
3734 TRACE("(%p) : returning %p\n", This, *ppShader);
3738 #define GET_SHADER_CONSTANT(_vertexshaderconstant, _count, _sizecount) \
3739 count = min(_count, MAX_VSHADER_CONSTANTS - (StartRegister + 1)); \
3740 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3741 return D3DERR_INVALIDCALL; \
3742 memcpy(pConstantData, This->updateStateBlock->_vertexshaderconstant + (StartRegister * _sizecount), count * (sizeof(*pConstantData) * _sizecount));
3744 #define SET_SHADER_CONSTANT(_vertexshaderconstant, _count, _sizecount) \
3745 int count = min(_count, MAX_VSHADER_CONSTANTS - (StartRegister + 1)); \
3746 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3747 return D3DERR_INVALIDCALL; \
3748 memcpy(This->updateStateBlock->_vertexshaderconstant + (StartRegister * _sizecount), pConstantData, count * (sizeof(*pConstantData) * _sizecount)); \
3749 This->updateStateBlock->changed.vertexShader = TRUE; \
3750 This->updateStateBlock->set.vertexShader = TRUE;
3752 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
3753 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3755 SET_SHADER_CONSTANT(vertexShaderConstantB, BoolCount, 1);
3757 /* populate the bitmap that says which constant type we should load */
3758 for (i = StartRegister; i < BoolCount + StartRegister; ++i) {
3759 This->updateStateBlock->changed.vertexShaderConstants[i] = TRUE;
3760 This->updateStateBlock->set.vertexShaderConstants[i] = TRUE;
3761 This->updateStateBlock->vertexShaderConstantT[i] = WINESHADERCNST_BOOL;
3762 TRACE("(%p) : Setting vsb %d to %d\n", This->updateStateBlock, i, pConstantData[i - StartRegister]);
3768 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
3769 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3772 /* verify that the requested shader constant was populated with a boolean */
3773 for (i = StartRegister; i < BoolCount; ++i) {
3774 if (This->updateStateBlock->vertexShaderConstantT[i] != WINESHADERCNST_BOOL) {
3776 /* the constant for this register isn't a boolean */
3777 WARN("(%p) : Caller requested a boolean where stateblock (%p) entry is a %s. Returning D3DERR_INVALIDCALL\n", This,This->updateStateBlock,
3778 This->updateStateBlock->vertexShaderConstantT[i] == WINESHADERCNST_INTEGER ? "integer" : "float");
3779 return D3DERR_INVALIDCALL;
3783 GET_SHADER_CONSTANT(vertexShaderConstantB, BoolCount, 1);
3787 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
3788 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3791 SET_SHADER_CONSTANT(vertexShaderConstantI, Vector4iCount, 4);
3793 /* populate the bitmap that says which constant type we should load */
3794 for (i = StartRegister; i < StartRegister + Vector4iCount; ++i) {
3795 This->updateStateBlock->changed.vertexShaderConstants[i] = TRUE;
3796 This->updateStateBlock->set.vertexShaderConstants[i] = TRUE;
3797 This->updateStateBlock->vertexShaderConstantT[i] = WINESHADERCNST_INTEGER;
3798 TRACE("(%p) : Setting vsi %d to %d\n", This->updateStateBlock, i, pConstantData[i - StartRegister]);
3804 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
3805 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3808 /* verify that the requested shader constant was populated with a integer */
3809 for (i = StartRegister; i < Vector4iCount; ++i) {
3810 if (This->updateStateBlock->vertexShaderConstantT[i] != WINESHADERCNST_INTEGER) {
3812 /* the constant for this register isn't a integer */
3813 WARN("(%p) : Caller requested a integer where stateblock (%p) entry is a %s. Returning D3DERR_INVALIDCALL\n", This, This->updateStateBlock,
3814 This->updateStateBlock->vertexShaderConstantT[i] == WINESHADERCNST_BOOL ? "boolean" : "float");
3815 return D3DERR_INVALIDCALL;
3819 GET_SHADER_CONSTANT(vertexShaderConstantI, Vector4iCount, 4);
3824 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
3825 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3828 SET_SHADER_CONSTANT(vertexShaderConstantF, Vector4fCount, 4);
3830 /* populate the bitmap that says which constant type we should load */
3831 for (i = StartRegister; i < StartRegister + Vector4fCount; ++i) {
3832 This->updateStateBlock->changed.vertexShaderConstants[i] = TRUE;
3833 This->updateStateBlock->set.vertexShaderConstants[i] = TRUE;
3834 This->updateStateBlock->vertexShaderConstantT[i] = WINESHADERCNST_FLOAT;
3835 TRACE("(%p) : Setting vsf %d to %f\n", This->updateStateBlock, i, pConstantData[i - StartRegister]);
3840 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
3841 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3844 /* verify that the requested shader constant was populated with a float */
3845 for (i = StartRegister; i < Vector4fCount; ++i) {
3846 if (This->updateStateBlock->vertexShaderConstantT[i] != WINESHADERCNST_FLOAT) {
3848 /* the constant for this register isn't a float */
3849 WARN("(%p) : Caller requested a float where stateblock (%p) entry is a %s. Returning D3DERR_INVALIDCALL\n", This, This->updateStateBlock,
3850 This->updateStateBlock->vertexShaderConstantT[i] == WINESHADERCNST_BOOL ? "boolean" : "integer");
3851 return D3DERR_INVALIDCALL;
3857 GET_SHADER_CONSTANT(vertexShaderConstantF, Vector4fCount, 4);
3862 #undef SET_SHADER_CONSTANT
3863 #undef GET_SHADER_CONSTANT
3866 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
3868 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3869 IWineD3DPixelShader *oldpShader = This->updateStateBlock->pixelShader;
3870 static BOOL showFixmes = TRUE;
3872 This->updateStateBlock->pixelShader = pShader;
3873 This->updateStateBlock->changed.pixelShader = TRUE;
3874 This->updateStateBlock->set.pixelShader = TRUE;
3876 if (pShader == NULL) {
3877 /* clear down the shader */
3878 TRACE("Clear down the shader\n");
3881 FIXME("(%p) : stub pShader(%p)\n", This, pShader);
3886 /* Handle recording of state blocks */
3887 if (This->isRecordingState) {
3888 TRACE("Recording... not performing anything\n");
3892 * TODO: merge HAL shaders context switching from prototype
3895 /* manage reference counting. */
3896 if (pShader != NULL) {
3897 IWineD3DPixelShader_GetParent(pShader, &parent); /* get parent adds a ref for us*/
3900 if (oldpShader != NULL) {
3901 IWineD3DPixelShader_GetParent(oldpShader, &parent);
3902 IUnknown_Release(parent); /* once for the getparent */
3903 IUnknown_Release(parent); /* and once for the ref */
3909 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3910 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3912 if (ppShader == NULL) {
3913 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
3914 return D3DERR_INVALIDCALL;
3917 *ppShader = This->updateStateBlock->pixelShader;
3918 if (NULL != ppShader) {
3919 IWineD3DPixelShader_AddRef(*ppShader);
3921 TRACE("(%p) : returning %p\n", This, *ppShader);
3925 #define GET_SHADER_CONSTANT(_pixelshaderconstant, _count, _sizecount) \
3926 count = min(_count, MAX_PSHADER_CONSTANTS - (StartRegister + 1)); \
3927 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3928 return D3DERR_INVALIDCALL; \
3929 memcpy(pConstantData, This->updateStateBlock->_pixelshaderconstant + (StartRegister * _sizecount), count * (sizeof(*pConstantData) * _sizecount)); \
3932 #define SET_SHADER_CONSTANT(_pixelshaderconstant, _count, _sizecount) \
3933 int count = min(_count, MAX_PSHADER_CONSTANTS - (StartRegister + 1)); \
3934 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3935 return D3DERR_INVALIDCALL; \
3936 memcpy(This->updateStateBlock->_pixelshaderconstant + (StartRegister * _sizecount), pConstantData, count * (sizeof(*pConstantData) * _sizecount)); \
3937 This->updateStateBlock->changed.pixelShader = TRUE; \
3938 This->updateStateBlock->set.pixelShader = TRUE;
3941 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
3942 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3945 SET_SHADER_CONSTANT(pixelShaderConstantB, BoolCount, 1);
3947 /* populate the bitmap that says which constant type we should load */
3948 for (i = StartRegister; i < BoolCount + StartRegister; ++i) {
3949 This->updateStateBlock->changed.pixelShaderConstants[i] = TRUE;
3950 This->updateStateBlock->set.pixelShaderConstants[i] = TRUE;
3951 This->updateStateBlock->pixelShaderConstantT[i] = WINESHADERCNST_BOOL;
3952 TRACE("(%p) : Setting psb %d to %d\n", This->updateStateBlock, i, pConstantData[i - StartRegister]);
3959 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
3960 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3963 /* populate the bitmap that says which constant type we should load */
3964 for (i = StartRegister; i < BoolCount + StartRegister; ++i) {
3965 This->updateStateBlock->changed.pixelShaderConstants[i] = TRUE;
3966 This->updateStateBlock->set.pixelShaderConstants[i] = TRUE;
3967 This->updateStateBlock->pixelShaderConstantT[i] = WINESHADERCNST_BOOL;
3968 TRACE("(%p) : Setting psb %d to %d\n", This->updateStateBlock, i, pConstantData[i - StartRegister]);
3971 GET_SHADER_CONSTANT(pixelShaderConstantB, BoolCount, 1);
3976 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
3977 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3980 SET_SHADER_CONSTANT(pixelShaderConstantI, Vector4iCount, 4);
3982 /* populate the bitmap that says which constant type we should load */
3983 for (i = StartRegister; i < Vector4iCount + StartRegister; ++i) {
3984 This->updateStateBlock->changed.pixelShaderConstants[i] = TRUE;
3985 This->updateStateBlock->set.pixelShaderConstants[i] = TRUE;
3986 This->updateStateBlock->pixelShaderConstantT[i] = WINESHADERCNST_INTEGER;
3987 TRACE("(%p) : Setting psb %d to %d\n", This->updateStateBlock, i, pConstantData[i - StartRegister]);
3993 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
3994 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3997 /* verify that the requested shader constant was populated with a integer */
3998 for (i = StartRegister; i < Vector4iCount; ++i) {
3999 if (WINESHADERCNST_INTEGER != This->updateStateBlock->pixelShaderConstantT[i]) {
4001 /* the constant for this register isn't a integer */
4002 WARN("(%p) : Caller requested a integer where stateblock (%p) entry is a %s. Returning D3DERR_INVALIDCALL\n", This, This->updateStateBlock,
4003 WINESHADERCNST_BOOL == This->updateStateBlock->vertexShaderConstantT[i] ? "boolean" : "float");
4004 return D3DERR_INVALIDCALL;
4008 GET_SHADER_CONSTANT(pixelShaderConstantI, Vector4iCount, 4);
4013 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
4014 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4016 SET_SHADER_CONSTANT(pixelShaderConstantF, Vector4fCount, 4);
4018 /* populate the bitmap that says which constant type we should load */
4019 for (i = StartRegister; i < Vector4fCount + StartRegister; ++i) {
4020 This->updateStateBlock->changed.pixelShaderConstants[i] = TRUE;
4021 This->updateStateBlock->set.pixelShaderConstants[i] = TRUE;
4022 This->updateStateBlock->pixelShaderConstantT[i] = WINESHADERCNST_FLOAT;
4023 TRACE("(%p) : Setting psb %d to %f\n", This->updateStateBlock, i, pConstantData[i - StartRegister]);
4029 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
4030 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4033 /* verify that the requested shader constant was populated with a integer */
4034 for (i = StartRegister; i < Vector4fCount; ++i) {
4035 if (WINESHADERCNST_FLOAT != This->updateStateBlock->pixelShaderConstantT[i]) {
4037 /* the constant for this register isn't a float */
4038 WARN("(%p) : Caller requested a integer where stateblock (%p) entry is a %s. Returning D3DERR_INVALIDCALL\n", This, This->updateStateBlock,
4039 WINESHADERCNST_BOOL == This->updateStateBlock->vertexShaderConstantT[i] ? "boolean" : "integer");
4040 return D3DERR_INVALIDCALL;
4044 GET_SHADER_CONSTANT(pixelShaderConstantF, Vector4fCount, 4);
4049 #undef SET_SHADER_CONSTANT
4050 #undef GET_SHADER_CONSTANT
4052 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
4053 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4054 FIXME("(%p) : stub\n", This);
4059 * Apply / Get / Set Texture Stage States
4060 * TODO: Verify against dx9 definitions
4063 /* 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 */
4064 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
4065 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4066 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
4067 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4069 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4071 /* Check that the stage is within limits */
4072 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4073 TRACE("Attempt to access invalid texture rejected\n");
4080 case WINED3DTSS_ALPHAOP :
4081 case WINED3DTSS_COLOROP :
4082 /* nothing to do as moved to drawprim for now */
4084 case WINED3DTSS_ADDRESSW :
4085 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
4086 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
4087 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
4090 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
4091 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
4092 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
4093 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
4096 case WINED3DTSS_TEXCOORDINDEX :
4098 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
4100 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
4101 one flag, you can still specify an index value, which the system uses to
4102 determine the texture wrapping mode.
4103 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
4104 means use the vertex position (camera-space) as the input texture coordinates
4105 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
4106 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
4107 to the TEXCOORDINDEX value */
4110 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
4112 switch (Value & 0xFFFF0000) {
4113 case D3DTSS_TCI_PASSTHRU:
4114 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
4115 glDisable(GL_TEXTURE_GEN_S);
4116 glDisable(GL_TEXTURE_GEN_T);
4117 glDisable(GL_TEXTURE_GEN_R);
4118 glDisable(GL_TEXTURE_GEN_Q);
4119 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
4122 case D3DTSS_TCI_CAMERASPACEPOSITION:
4123 /* CameraSpacePosition means use the vertex position, transformed to camera space,
4124 as the input texture coordinates for this stage's texture transformation. This
4125 equates roughly to EYE_LINEAR */
4127 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4128 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4129 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4130 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4131 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4133 glMatrixMode(GL_MODELVIEW);
4136 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4137 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4138 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4139 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4142 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
4143 glEnable(GL_TEXTURE_GEN_S);
4144 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4145 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4146 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4147 glEnable(GL_TEXTURE_GEN_T);
4148 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4149 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4150 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4151 glEnable(GL_TEXTURE_GEN_R);
4152 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4153 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4154 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4158 case D3DTSS_TCI_CAMERASPACENORMAL:
4160 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4161 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4162 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4163 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4164 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4165 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
4167 glMatrixMode(GL_MODELVIEW);
4170 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4171 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4172 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4173 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4176 glEnable(GL_TEXTURE_GEN_S);
4177 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4178 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4179 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4180 glEnable(GL_TEXTURE_GEN_T);
4181 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4182 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4183 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4184 glEnable(GL_TEXTURE_GEN_R);
4185 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4186 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4187 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4192 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
4194 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4195 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4196 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4197 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4198 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4199 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
4201 glMatrixMode(GL_MODELVIEW);
4204 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4205 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4206 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4207 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4210 glEnable(GL_TEXTURE_GEN_S);
4211 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4212 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4213 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4214 glEnable(GL_TEXTURE_GEN_T);
4215 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4216 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4217 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4218 glEnable(GL_TEXTURE_GEN_R);
4219 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4220 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4221 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4226 /* Unhandled types: */
4229 /* ? disable GL_TEXTURE_GEN_n ? */
4230 glDisable(GL_TEXTURE_GEN_S);
4231 glDisable(GL_TEXTURE_GEN_T);
4232 glDisable(GL_TEXTURE_GEN_R);
4233 glDisable(GL_TEXTURE_GEN_Q);
4234 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
4241 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
4242 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);
4245 case WINED3DTSS_BUMPENVMAT00 :
4246 case WINED3DTSS_BUMPENVMAT01 :
4247 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
4249 case WINED3DTSS_BUMPENVMAT10 :
4250 case WINED3DTSS_BUMPENVMAT11 :
4251 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
4254 case WINED3DTSS_BUMPENVLSCALE :
4255 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4258 case WINED3DTSS_BUMPENVLOFFSET :
4259 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4262 case WINED3DTSS_RESULTARG :
4263 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4267 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
4268 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4277 * Get / Set Texture Stage States
4278 * TODO: Verify against dx9 definitions
4280 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
4281 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4283 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4285 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4287 /* Reject invalid texture units */
4288 if (Stage >= GL_LIMITS(textures)) {
4289 TRACE("Attempt to access invalid texture rejected\n");
4290 return D3DERR_INVALIDCALL;
4293 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
4294 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
4295 This->updateStateBlock->textureState[Stage][Type] = Value;
4300 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4301 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4302 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4303 *pValue = This->updateStateBlock->textureState[Stage][Type];
4310 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4312 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4313 IWineD3DBaseTexture *oldTexture;
4315 oldTexture = This->updateStateBlock->textures[Stage];
4316 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
4318 #if 0 /* TODO: check so vertex textures */
4319 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
4320 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
4325 /* Reject invalid texture units */
4326 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4327 WARN("Attempt to access invalid texture rejected\n");
4328 return D3DERR_INVALIDCALL;
4331 oldTexture = This->updateStateBlock->textures[Stage];
4332 TRACE("GL_LIMITS %d\n",GL_LIMITS(textures));
4333 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
4335 This->updateStateBlock->set.textures[Stage] = TRUE;
4336 This->updateStateBlock->changed.textures[Stage] = TRUE;
4337 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
4338 This->updateStateBlock->textures[Stage] = pTexture;
4340 /* Handle recording of state blocks */
4341 if (This->isRecordingState) {
4342 TRACE("Recording... not performing anything\n");
4346 /** NOTE: MSDN says that setTexture increases the reference count,
4347 * and the the application nust set the texture back to null (or have a leaky application),
4348 * This means we should pass the refcount upto the parent
4349 *******************************/
4350 if (NULL != This->updateStateBlock->textures[Stage]) {
4351 IUnknown *textureParent;
4352 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[Stage], (IUnknown **)&textureParent);
4353 /** NOTE: GetParent will increase the ref count for me, I won't clean up until the texture is set to NULL **/
4356 if (NULL != oldTexture) {
4357 IUnknown *textureParent;
4358 IWineD3DBaseTexture_GetParent(oldTexture, (IUnknown **)&textureParent);
4359 IUnknown_Release(textureParent);
4360 IUnknown_Release(textureParent); /** NOTE: Twice because GetParent adds a ref **/
4367 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4368 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4369 TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */) \n", This, Stage, ppTexture);
4371 /* Reject invalid texture units */
4372 if (Stage >= GL_LIMITS(textures)) {
4373 TRACE("Attempt to access invalid texture rejected\n");
4374 return D3DERR_INVALIDCALL;
4376 *ppTexture=This->updateStateBlock->textures[Stage];
4378 IWineD3DBaseTexture_AddRef(*ppTexture);
4380 return D3DERR_INVALIDCALL;
4387 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type,
4388 IWineD3DSurface **ppBackBuffer) {
4389 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4390 IWineD3DSwapChain *swapChain;
4393 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4395 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4397 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4398 IWineD3DSwapChain_Release(swapChain);
4400 *ppBackBuffer = NULL;
4405 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4406 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4407 WARN("(%p) : stub, calling idirect3d for now\n", This);
4408 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4411 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
4412 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4413 IWineD3DSwapChain *swapChain;
4416 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4418 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4419 IWineD3DSwapChain_Release(swapChain);
4421 FIXME("(%p) Error getting display mode\n", This);
4426 * Stateblock related functions
4429 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4430 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4431 IWineD3DStateBlockImpl *object;
4432 TRACE("(%p)", This);
4433 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4434 if (NULL == object ) {
4435 FIXME("(%p)Error allocating memory for stateblock\n", This);
4436 return E_OUTOFMEMORY;
4438 TRACE("(%p) creted object %p\n", This, object);
4439 object->wineD3DDevice= This;
4440 /** FIXME: object->parent = parent; **/
4441 object->parent = NULL;
4442 object->blockType = WINED3DSBT_ALL;
4444 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
4446 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4447 This->updateStateBlock = object;
4448 This->isRecordingState = TRUE;
4450 TRACE("(%p) recording stateblock %p\n",This , object);
4454 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4455 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4457 if (!This->isRecordingState) {
4458 FIXME("(%p) not recording! returning error\n", This);
4459 *ppStateBlock = NULL;
4460 return D3DERR_INVALIDCALL;
4463 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4464 This->isRecordingState = FALSE;
4465 This->updateStateBlock = This->stateBlock;
4466 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4467 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4468 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4473 * Scene related functions
4475 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4476 /* At the moment we have no need for any functionality at the beginning
4478 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4479 TRACE("(%p) : stub\n", This);
4483 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4484 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4485 TRACE("(%p)\n", This);
4487 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4489 checkGLcall("glFlush");
4491 TRACE("End Scene\n");
4492 if(This->renderTarget != NULL) {
4494 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4495 IUnknown *targetContainer = NULL;
4496 if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
4497 || D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
4498 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
4499 /** always dirtify for now. we must find a better way to see that surface have been modified
4500 (Modifications should will only occur via draw-primitive, but we do need better locking
4501 switching to render-to-texture should remove the overhead though.
4503 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4504 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
4505 IWineD3DSurface_PreLoad(This->renderTarget);
4506 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4507 IUnknown_Release(targetContainer);
4510 This->sceneEnded = TRUE;
4515 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4516 CONST RECT* pSourceRect, CONST RECT* pDestRect,
4517 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4518 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4519 IWineD3DSwapChain *swapChain = NULL;
4521 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4523 TRACE("(%p) Presenting the frame\n", This);
4525 for(i = 0 ; i < swapchains ; i ++) {
4527 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4528 TRACE("presentinng chain %d, %p\n", i, swapChain);
4529 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4530 IWineD3DSwapChain_Release(swapChain);
4536 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4537 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4538 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4540 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4541 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4542 when the depth-buffer format does not contain stencil buffer information, this method fails. */
4543 GLbitfield glMask = 0;
4544 GLboolean old_ztest;
4545 GLfloat old_z_clear_value;
4546 GLint old_stencil_clear_value;
4547 GLfloat old_color_clear_value[4];
4549 CONST D3DRECT* curRect;
4551 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4552 Count, pRects, Flags, Z, Stencil);
4556 glEnable(GL_SCISSOR_TEST);
4557 checkGLcall("glEnable GL_SCISSOR_TEST");
4559 if (Count > 0 && pRects) {
4565 /* Only set the values up once, as they are not changing */
4566 if (Flags & D3DCLEAR_STENCIL) {
4567 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4568 glClearStencil(Stencil);
4569 checkGLcall("glClearStencil");
4570 glMask = glMask | GL_STENCIL_BUFFER_BIT;
4571 glStencilMask(0xFFFFFFFF);
4574 if (Flags & D3DCLEAR_ZBUFFER) {
4575 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4576 glDepthMask(GL_TRUE);
4577 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4579 checkGLcall("glClearDepth");
4580 glMask = glMask | GL_DEPTH_BUFFER_BIT;
4583 if (Flags & D3DCLEAR_TARGET) {
4584 TRACE("Clearing screen with glClear to color %lx\n", Color);
4585 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4586 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
4587 ((Color >> 8) & 0xFF) / 255.0f,
4588 ((Color >> 0) & 0xFF) / 255.0f,
4589 ((Color >> 24) & 0xFF) / 255.0f);
4590 checkGLcall("glClearColor");
4592 /* Clear ALL colors! */
4593 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4594 glMask = glMask | GL_COLOR_BUFFER_BIT;
4597 /* Now process each rect in turn */
4598 for (i = 0; i < Count || i == 0; i++) {
4601 /* Note gl uses lower left, width/height */
4602 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4603 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4604 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4605 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4606 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4607 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4608 checkGLcall("glScissor");
4610 glScissor(This->stateBlock->viewport.X,
4611 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
4612 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4613 This->stateBlock->viewport.Width,
4614 This->stateBlock->viewport.Height);
4615 checkGLcall("glScissor");
4618 /* Clear the selected rectangle (or full screen) */
4620 checkGLcall("glClear");
4622 /* Step to the next rectangle */
4623 if (curRect) curRect = curRect + sizeof(D3DRECT);
4626 /* Restore the old values (why..?) */
4627 if (Flags & D3DCLEAR_STENCIL) {
4628 glClearStencil(old_stencil_clear_value);
4629 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4631 if (Flags & D3DCLEAR_ZBUFFER) {
4632 glDepthMask(old_ztest);
4633 glClearDepth(old_z_clear_value);
4635 if (Flags & D3DCLEAR_TARGET) {
4636 glClearColor(old_color_clear_value[0],
4637 old_color_clear_value[1],
4638 old_color_clear_value[2],
4639 old_color_clear_value[3]);
4640 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4641 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4642 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4643 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4646 glDisable(GL_SCISSOR_TEST);
4647 checkGLcall("glDisable");
4656 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4657 UINT PrimitiveCount) {
4659 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4660 This->stateBlock->streamIsUP = FALSE;
4662 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4663 debug_d3dprimitivetype(PrimitiveType),
4664 StartVertex, PrimitiveCount);
4665 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
4666 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
4672 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4673 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4674 D3DPRIMITIVETYPE PrimitiveType,
4675 INT baseVIndex, UINT minIndex,
4676 UINT NumVertices, UINT startIndex, UINT primCount) {
4678 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4680 IWineD3DIndexBuffer *pIB;
4681 D3DINDEXBUFFER_DESC IdxBufDsc;
4683 pIB = This->stateBlock->pIndexData;
4684 This->stateBlock->streamIsUP = FALSE;
4686 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d \n", This,
4687 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4688 minIndex, NumVertices, startIndex, baseVIndex, primCount);
4690 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4691 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4697 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
4698 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
4703 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4704 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4705 UINT VertexStreamZeroStride) {
4706 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4708 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4709 debug_d3dprimitivetype(PrimitiveType),
4710 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4712 if (This->stateBlock->streamSource[0] != NULL) {
4713 IUnknown *vertexBufferParent;
4714 IWineD3DVertexBuffer_GetParent(This->stateBlock->streamSource[0], &vertexBufferParent);
4715 IUnknown_Release(vertexBufferParent);
4716 IUnknown_Release(vertexBufferParent);
4719 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4720 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4721 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4722 This->stateBlock->streamIsUP = TRUE;
4724 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
4725 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
4726 /* stream zero settings set to null at end, as per the msdn
4727 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
4729 This->stateBlock->streamStride[0] = 0;
4730 This->stateBlock->streamSource[0] = NULL;
4732 /*stream zero settings set to null at end, as per the msdn */
4736 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4737 UINT MinVertexIndex, UINT NumVertices,
4738 UINT PrimitiveCount, CONST void* pIndexData,
4739 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4740 UINT VertexStreamZeroStride) {
4742 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4744 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4745 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4746 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
4747 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4749 if (IndexDataFormat == WINED3DFMT_INDEX16) {
4755 if (This->stateBlock->streamSource[0] != NULL) {
4756 IUnknown *vertexBufferParent;
4757 IWineD3DVertexBuffer_GetParent(This->stateBlock->streamSource[0], &vertexBufferParent);
4758 This->stateBlock->streamSource[0] = NULL;
4759 IUnknown_Release(vertexBufferParent);
4760 IUnknown_Release(vertexBufferParent);
4763 if (This->stateBlock->pIndexData) {
4764 IUnknown *indexBufferParent;
4765 IWineD3DIndexBuffer_GetParent(This->stateBlock->pIndexData, &indexBufferParent);
4766 This->stateBlock->pIndexData = NULL;
4767 IUnknown_Release(indexBufferParent);
4768 IUnknown_Release(indexBufferParent);
4771 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4772 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4773 This->stateBlock->streamIsUP = TRUE;
4774 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4776 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
4777 /* stream zero settings set to null at end as per the msdn
4778 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
4781 /* stream zero settings set to null at end as per the msdn */
4782 This->stateBlock->streamSource[0] = NULL;
4783 This->stateBlock->streamStride[0] = 0;
4788 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4789 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
4790 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4791 D3DRESOURCETYPE sourceType;
4792 D3DRESOURCETYPE destinationType;
4793 IWineD3DTextureImpl *pDestTexture = (IWineD3DTextureImpl *)pDestinationTexture;
4794 IWineD3DTextureImpl *pSrcTexture = (IWineD3DTextureImpl *)pSourceTexture;
4797 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
4798 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
4799 if(sourceType != D3DRTYPE_TEXTURE && destinationType != D3DRTYPE_TEXTURE){
4800 FIXME("(%p) Only D3DRTYPE_TEXTURE to D3DRTYPE_TEXTURE supported\n", This);
4801 return D3DERR_INVALIDCALL;
4803 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
4805 /** TODO: Get rid of the casts to IWineD3DBaseTextureImpl
4806 repalce surfaces[x] with GetSurfaceLevel, or GetCubeMapSurface etc..
4807 think about moving the code into texture, and adding a member to base texture to occomplish this **/
4809 /* Make sure that the destination texture is loaded */
4810 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
4811 TRACE("Loading source texture\n");
4813 if(pSrcTexture->surfaces[0] == NULL || pDestTexture->surfaces[0] == NULL){
4814 FIXME("(%p) Texture src %p or dest %p has not surface %p %p\n", This, pSrcTexture, pDestTexture,
4815 pSrcTexture->surfaces[0], pDestTexture->surfaces[0]);
4818 if(((IWineD3DSurfaceImpl *)pSrcTexture->surfaces[0])->resource.pool != D3DPOOL_SYSTEMMEM ||
4819 ((IWineD3DSurfaceImpl *)pDestTexture->surfaces[0])->resource.pool != D3DPOOL_DEFAULT){
4821 FIXME("(%p) source %p must be SYSTEMMEM and dest %p must be DEFAULT\n",This, pSrcTexture, pDestTexture);
4822 return D3DERR_INVALIDCALL;
4824 /** TODO: check that both textures have the same number of levels **/
4826 if(IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) !=IWineD3DBaseTexture_GetLevelCount(pSourceTexture))
4827 return D3DERR_INVALIDCALL;
4829 /** TODO: move this code into baseTexture? device should never touch impl*'s **/
4830 for(i = 0 ; i < IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) ; i++){
4831 IWineD3DDevice_UpdateSurface(iface, pSrcTexture->surfaces[i], NULL, pDestTexture->surfaces[i], NULL);
4837 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
4838 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
4839 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
4840 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4842 TRACE("(%p) : stub\n", This);
4845 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
4846 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4847 /** TODO: remove remove casts to IWineD3DSurfaceImpl *
4848 * NOTE It may be best to move the code into surface to occomplish this
4849 ****************************************/
4851 WINED3DSURFACE_DESC surfaceDesc;
4852 unsigned int surfaceWidth, surfaceHeight;
4853 glDescriptor *targetGlDescription = NULL;
4854 glDescriptor *surfaceGlDescription = NULL;
4855 IWineD3DSwapChainImpl *container = NULL;
4857 IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
4858 IWineD3DSurface_GetGlDesc(pSurface, &surfaceGlDescription);
4859 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
4861 surfaceDesc.Width = &surfaceWidth;
4862 surfaceDesc.Height = &surfaceHeight;
4863 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
4864 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sureteh data is upto date)*/
4866 /* Ok, I may need to setup some kind of active swapchain reference on the device */
4867 IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
4869 /* TODO: opengl Context switching for swapchains etc... */
4870 if (NULL != container || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
4871 if (NULL != container && (pRenderTarget == container->backBuffer)) {
4872 glReadBuffer(GL_BACK);
4873 vcheckGLcall("glReadBuffer(GL_BACK)");
4874 } else if ((NULL != container && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
4875 glReadBuffer(GL_FRONT);
4876 vcheckGLcall("glReadBuffer(GL_FRONT)");
4877 } else if (pRenderTarget == This->depthStencilBuffer) {
4878 FIXME("Reading of depthstencil not yet supported\n");
4881 glReadPixels(surfaceGlDescription->target,
4882 surfaceGlDescription->level,
4885 surfaceGlDescription->glFormat,
4886 surfaceGlDescription->glType,
4887 (void *)IWineD3DSurface_GetData(pSurface));
4888 vcheckGLcall("glReadPixels(...)");
4889 if(NULL != container ){
4890 IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
4893 IWineD3DBaseTexture *container;
4894 GLenum textureDimensions = GL_TEXTURE_2D;
4896 if (D3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
4897 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
4898 IWineD3DBaseTexture_Release(container);
4900 /* TODO: 2D -> Cube surface coppies etc.. */
4901 if (surfaceGlDescription->target != textureDimensions) {
4902 FIXME("(%p) : Texture dimension mismatch\n", This);
4904 glEnable(textureDimensions);
4905 vcheckGLcall("glEnable(GL_TEXTURE_...)");
4906 /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
4907 glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
4908 vcheckGLcall("glBindTexture");
4909 glGetTexImage(surfaceGlDescription->target,
4910 surfaceGlDescription->level,
4911 surfaceGlDescription->glFormat,
4912 surfaceGlDescription->glType,
4913 (void *)IWineD3DSurface_GetData(pSurface));
4914 glDisable(textureDimensions);
4915 vcheckGLcall("glDisable(GL_TEXTURE_...)");
4922 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
4923 IWineD3DSwapChain *swapChain;
4925 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4927 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
4928 IWineD3DSwapChain_Release(swapChain);
4933 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4934 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4935 /* return a sensible default */
4937 /* TODO: If the window is minimized then validate device shold return something other than d3d_ok */
4938 FIXME("(%p) : stub\n", This);
4942 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4943 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4945 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4946 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4947 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4948 return D3DERR_INVALIDCALL;
4950 for (j = 0; j < 256; ++j) {
4951 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
4952 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
4953 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
4954 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
4956 TRACE("(%p) : returning\n", This);
4960 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4961 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4963 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4964 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4965 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4966 return D3DERR_INVALIDCALL;
4968 for (j = 0; j < 256; ++j) {
4969 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
4970 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
4971 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
4972 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
4974 TRACE("(%p) : returning\n", This);
4978 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4979 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4980 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4981 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4982 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4983 return D3DERR_INVALIDCALL;
4985 /*TODO: stateblocks */
4986 This->currentPalette = PaletteNumber;
4987 TRACE("(%p) : returning\n", This);
4991 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4992 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4993 if (PaletteNumber == NULL) {
4994 WARN("(%p) : returning Invalid Call\n", This);
4995 return D3DERR_INVALIDCALL;
4997 /*TODO: stateblocks */
4998 *PaletteNumber = This->currentPalette;
4999 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
5003 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
5004 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5005 static BOOL showFixmes = TRUE;
5007 FIXME("(%p) : stub\n", This);
5011 This->updateStateBlock->softwareVertexProcessing = bSoftware;
5016 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
5017 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5018 static BOOL showFixmes = TRUE;
5020 FIXME("(%p) : stub\n", This);
5023 return This->updateStateBlock->softwareVertexProcessing;
5027 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
5028 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5029 IWineD3DSwapChain *swapChain;
5032 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
5034 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5036 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
5037 IWineD3DSwapChain_Release(swapChain);
5039 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error \n", This);
5045 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
5046 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5047 static BOOL showfixmes = TRUE;
5048 if(nSegments != 0.0f) {
5050 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
5057 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
5058 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5059 static BOOL showfixmes = TRUE;
5061 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
5068 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
5069 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5070 /** TODO: remove casts to IWineD3DSurfaceImpl
5071 * NOTE: move code to surface to accomplish this
5072 ****************************************/
5073 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
5074 int srcWidth, srcHeight;
5075 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
5076 WINED3DFORMAT destFormat, srcFormat;
5078 int destLeft, destTop;
5079 D3DPOOL srcPool, destPool;
5081 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
5082 glDescriptor *glDescription = NULL;
5083 GLenum textureDimensions = GL_TEXTURE_2D;
5084 IWineD3DBaseTexture *baseTexture;
5086 WINED3DSURFACE_DESC winedesc;
5088 memset(&winedesc, 0, sizeof(winedesc));
5089 winedesc.Width = &srcSurfaceWidth;
5090 winedesc.Height = &srcSurfaceHeight;
5091 winedesc.Pool = &srcPool;
5092 winedesc.Format = &srcFormat;
5094 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5096 winedesc.Width = &destSurfaceWidth;
5097 winedesc.Height = &destSurfaceHeight;
5098 winedesc.Pool = &destPool;
5099 winedesc.Format = &destFormat;
5100 winedesc.Size = &destSize;
5102 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5104 if(srcPool != D3DPOOL_SYSTEMMEM || destPool != D3DPOOL_DEFAULT){
5105 FIXME("source %p must be SYSTEMMEM and dest %p must be DEFAULT\n", pSourceSurface, pDestinationSurface);
5106 return D3DERR_INVALIDCALL;
5108 /* TODO: change this to use bindTexture */
5109 /* Make sure the surface is loaded and upto date */
5110 IWineD3DSurface_PreLoad(pDestinationSurface);
5112 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
5116 /* this needs to be done in lines if the sourceRect != the sourceWidth */
5117 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
5118 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
5119 destLeft = pDestPoint ? pDestPoint->x : 0;
5120 destTop = pDestPoint ? pDestPoint->y : 0;
5123 /* This function doesn't support compressed textures
5124 the pitch is just bytesPerPixel * width */
5126 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
5127 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
5128 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
5129 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
5131 /* TODO DXT formats */
5133 if(pSourceRect != NULL && pSourceRect->top != 0){
5134 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
5136 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
5138 ,glDescription->level
5143 ,glDescription->glFormat
5144 ,glDescription->glType
5145 ,IWineD3DSurface_GetData(pSourceSurface)
5149 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
5150 /* need to lock the surface to get the data */
5151 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5153 /* TODO: Cube and volume support */
5155 /* not a whole row so we have to do it a line at a time */
5157 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
5158 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5160 for(j = destTop ; j < (srcHeight + destTop) ; j++){
5162 glTexSubImage2D(glDescription->target
5163 ,glDescription->level
5168 ,glDescription->glFormat
5169 ,glDescription->glType
5170 ,data/* could be quicker using */
5175 } else { /* Full width, so just write out the whole texture */
5177 if (WINED3DFMT_DXT1 == destFormat ||
5178 WINED3DFMT_DXT2 == destFormat ||
5179 WINED3DFMT_DXT3 == destFormat ||
5180 WINED3DFMT_DXT4 == destFormat ||
5181 WINED3DFMT_DXT5 == destFormat) {
5182 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
5183 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
5184 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
5185 FIXME("Updating part of a compressed texture is not supported at the moment\n");
5186 } if (destFormat != srcFormat) {
5187 FIXME("Updating mixed format compressed texture is not curretly support\n");
5189 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
5190 glDescription->level,
5191 glDescription->glFormatInternal,
5196 IWineD3DSurface_GetData(pSourceSurface));
5199 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
5204 if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
5205 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
5206 to repack the data from pow2Width/Height to expected Width,Height, this makes the
5207 data returned by GetData non-power2 width/height with hardware non-power2
5208 pow2Width/height are set to surface width height, repacking isn't needed so it
5209 doesn't matter which function gets called. */
5210 glTexSubImage2D(glDescription->target
5211 ,glDescription->level
5216 ,glDescription->glFormat
5217 ,glDescription->glType
5218 ,IWineD3DSurface_GetData(pSourceSurface)
5221 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
5222 glTexSubImage2D(glDescription->target
5223 ,glDescription->level
5226 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
5227 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
5228 ,glDescription->glFormat
5229 ,glDescription->glType
5230 ,IWineD3DSurface_GetData(pSourceSurface)
5236 checkGLcall("glTexSubImage2D");
5237 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
5238 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
5239 * surface bigger than it needs to be hmm.. */
5240 if (D3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
5241 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
5242 IWineD3DBaseTexture_Release(baseTexture);
5245 glDisable(textureDimensions); /* This needs to be managed better.... */
5251 /* Implementation details at http://developer.nvidia.com/attach/6494
5253 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
5254 hmm.. no longer supported use
5255 OpenGL evaluators or tessellate surfaces within your application.
5258 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
5259 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
5260 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5261 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p) \n", This, Handle, pNumSegs, pRectPatchInfo);
5262 FIXME("(%p) : Stub\n", This);
5267 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
5268 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
5269 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5270 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p) \n", This, Handle, pNumSegs, pTriPatchInfo);
5271 FIXME("(%p) : Stub\n", This);
5275 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5276 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5277 TRACE("(%p) Handle(%d)\n", This, Handle);
5278 FIXME("(%p) : Stub\n", This);
5282 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
5283 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
5284 fill a surface with a block of color! */
5285 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5286 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
5287 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
5288 IWineD3DSwapChainImpl *container = NULL;
5289 BOOL isRenderTarget = FALSE;
5290 unsigned int width, height;
5291 unsigned int top, left;
5294 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
5296 if (surface->resource.pool != D3DPOOL_DEFAULT) {
5297 FIXME("call to colorfill with non D3DPOOL_DEFAULT surface\n");
5298 return D3DERR_INVALIDCALL;
5301 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
5302 if (D3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
5303 if (D3DUSAGE_RENDERTARGET & surface->resource.usage) {
5304 /* TODO: make sure we set everything back to the way it was, and context management!
5305 glGetIntegerv(GL_READ_BUFFER, &prev_read);
5306 vcheckGLcall("glIntegerv");
5307 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
5308 vcheckGLcall("glIntegerv");
5310 TRACE("Color fill to render targets may cause some graphics issues\n");
5311 if (pSurface == container->frontBuffer) {
5312 glDrawBuffer(GL_FRONT);
5314 glDrawBuffer(GL_BACK);
5317 if (D3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
5318 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld \n", surface, surface->resource.usage);
5320 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
5322 if (container != NULL) {
5323 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5325 /* we can use GL_STENCIL_INDEX etc...*/
5328 if (container != NULL) {
5329 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5331 isRenderTarget = TRUE;
5333 /* TODO: drawing to GL_FRONT and GL_BACK */
5334 /* TODO: see if things can be speeded up by using the correct
5335 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
5336 if (pRect == NULL) {
5339 width = surface->currentDesc.Width;
5340 height = surface->currentDesc.Height;
5344 width = pRect->x2 - left;
5345 height = pRect->y2 - top;
5348 data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
5349 /* Create a 'line' of color color, in the correct format for the surface */
5350 for (u = 0 ; u < width ; u ++) {
5355 if (isRenderTarget == FALSE) {
5356 glDescriptor *glDesc;
5357 IWineD3DSurface_PreLoad(pSurface);
5359 /* draw a block of the coloured line on the sufrace */
5360 IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
5361 for (v = 0 ; v< height;v++) {
5362 glTexSubImage2D(glDesc->target
5363 ,glDesc->level /* level */
5373 checkGLcall("glTexSubImage2D");
5375 glDisable(glDesc->target);
5377 /** FIXME: Using GLClear may be faster **/
5378 glRasterPos2i(left, top);
5379 glPixelZoom((float)width ,(float)height);
5380 glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
5381 checkGLcall("glDrawPixels");
5383 HeapFree(GetProcessHeap(), 0, data);
5389 /* rendertarget and deptth stencil functions */
5390 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
5391 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5393 /* FIXME: Implelent RenderTargetIndex >0 */
5394 if(RenderTargetIndex > 0)
5395 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
5397 *ppRenderTarget = This->renderTarget;
5398 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
5399 /* Note inc ref on returned surface */
5400 if(*ppRenderTarget != NULL)
5401 IWineD3DSurface_AddRef(*ppRenderTarget);
5405 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5406 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5407 *ppZStencilSurface = This->depthStencilBuffer;
5408 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
5410 if(*ppZStencilSurface != NULL) {
5411 /* Note inc ref on returned surface */
5412 IWineD3DSurface_AddRef(*ppZStencilSurface);
5417 /* internal static helper functions */
5418 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5419 IWineD3DSurface *RenderSurface);
5421 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5422 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5423 HRESULT hr = D3D_OK;
5424 WINED3DVIEWPORT viewport;
5426 TRACE("(%p) Swapping rendertarget\n",This);
5427 if (RenderTargetIndex > 0) {
5428 FIXME("(%p) Render targets other than the first are not supported\n",This);
5429 RenderTargetIndex = 0;
5432 /* MSDN says that null disables the render target
5433 but a device must always be associated with a render target
5434 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5436 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5439 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5440 FIXME("Trying to set render target 0 to NULL\n");
5441 return D3DERR_INVALIDCALL;
5443 /* TODO: replace Impl* usage with interface usage */
5444 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & D3DUSAGE_RENDERTARGET) {
5445 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);
5446 return D3DERR_INVALIDCALL;
5448 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
5449 * builds, but I think wine counts as a 'debug' build for now.
5450 ******************************/
5451 /* If we are trying to set what we already have, don't bother */
5452 if (pRenderTarget == This->renderTarget) {
5453 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5455 /* Otherwise, set the render target up */
5457 if (FALSE == This->sceneEnded) {
5458 IWineD3DDevice_EndScene(iface);
5460 TRACE("clearing renderer\n");
5461 /* IWineD3DDeviceImpl_CleanRender(iface); */
5462 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5463 depending on the renter target implementation being used.
5464 A shared context implementation will share all buffers between all rendertargets (including swapchains),
5465 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5466 stencil buffer and incure an extra memory overhead */
5467 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
5470 if (SUCCEEDED(hr)) {
5471 /* Finally, reset the viewport as the MSDN states. */
5472 /* TODO: Replace impl usage */
5473 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
5474 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
5477 viewport.MaxZ = 1.0f;
5478 viewport.MinZ = 0.0f;
5479 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
5481 FIXME("Unknown error setting the render target\n");
5483 This->sceneEnded = FALSE;
5487 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
5488 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5489 HRESULT hr = D3D_OK;
5490 IWineD3DSurface *tmp;
5492 TRACE("(%p) Swapping z-buffer\n",This);
5494 if (pNewZStencil == This->stencilBufferTarget) {
5495 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5497 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5498 * depending on the renter target implementation being used.
5499 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5500 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5501 * stencil buffer and incure an extra memory overhead
5502 ******************************************************/
5505 tmp = This->stencilBufferTarget;
5506 This->stencilBufferTarget = pNewZStencil;
5507 /* should we be calling the parent or the wined3d surface? */
5508 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
5509 if (NULL != tmp) IWineD3DSurface_Release(tmp);
5511 /** TODO: glEnable/glDisable on depth/stencil depending on
5512 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
5513 **********************************************************/
5520 #ifdef GL_VERSION_1_3
5521 /* Internal functions not in DirectX */
5522 /** TODO: move this off to the opengl context manager
5523 *(the swapchain doesn't need to know anything about offscreen rendering!)
5524 ****************************************************/
5526 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
5528 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5530 TRACE("(%p), %p\n", This, swapchain);
5532 if (swapchain->win != swapchain->drawable) {
5533 /* Set everything back the way it ws */
5534 swapchain->render_ctx = swapchain->glCtx;
5535 swapchain->drawable = swapchain->win;
5540 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
5541 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
5542 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5545 unsigned int height;
5546 WINED3DFORMAT format;
5547 WINED3DSURFACE_DESC surfaceDesc;
5548 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5549 surfaceDesc.Width = &width;
5550 surfaceDesc.Height = &height;
5551 surfaceDesc.Format = &format;
5552 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5554 /* I need a get width/height function (and should do something with the format) */
5555 for (i = 0; i < CONTEXT_CACHE; ++i) {
5556 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
5557 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
5558 the pSurface can be set to 0 allowing it to be reused from cache **/
5559 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
5560 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
5561 *context = &This->contextCache[i];
5564 if (This->contextCache[i].Width == 0) {
5565 This->contextCache[i].pSurface = pSurface;
5566 This->contextCache[i].Width = width;
5567 This->contextCache[i].Height = height;
5568 *context = &This->contextCache[i];
5572 if (i == CONTEXT_CACHE) {
5573 int minUsage = 0x7FFFFFFF; /* MAX_INT */
5574 glContext *dropContext = 0;
5575 for (i = 0; i < CONTEXT_CACHE; i++) {
5576 if (This->contextCache[i].usedcount < minUsage) {
5577 dropContext = &This->contextCache[i];
5578 minUsage = This->contextCache[i].usedcount;
5581 /* clean up the context (this doesn't work for ATI at the moment */
5583 glXDestroyContext(swapchain->display, dropContext->context);
5584 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
5587 dropContext->Width = 0;
5588 dropContext->pSurface = pSurface;
5589 *context = dropContext;
5591 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
5592 for (i = 0; i < CONTEXT_CACHE; i++) {
5593 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
5597 if (*context != NULL)
5600 return E_OUTOFMEMORY;
5604 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
5605 * the functionality needs splitting up so that we don't do more than we should do.
5606 * this only seems to impact performance a little.
5607 ******************************/
5608 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5609 IWineD3DSurface *RenderSurface) {
5610 HRESULT ret = D3DERR_INVALIDCALL;
5613 * Currently only active for GLX >= 1.3
5614 * for others versions we'll have to use GLXPixmaps
5616 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
5617 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
5618 * so only check OpenGL version
5619 * ..........................
5620 * I don't believe that it is a problem with NVidia headers,
5621 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
5622 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
5624 * Your application will report GLX version 1.2 on glXQueryVersion.
5625 * However, it is safe to call the GLX 1.3 functions as described below.
5627 #if defined(GL_VERSION_1_3)
5629 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5630 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
5631 IWineD3DSurface *tmp;
5632 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
5633 GLXFBConfig* cfgs = NULL;
5637 IWineD3DSwapChain *currentSwapchain;
5638 IWineD3DSwapChainImpl *swapchain;
5639 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
5640 * but switch them off if the StencilSurface is set to NULL
5641 ** *********************************************************/
5642 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
5643 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
5646 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
5647 it StencilSurface != NULL && zBufferTarget == NULL switch it on
5650 #define PUSH1(att) attribs[nAttribs++] = (att);
5651 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
5653 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
5655 /** TODO: remove the reff to Impl (context manager should fix this!) **/
5656 IWineD3DSwapChainImpl *impSwapChain;
5657 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
5658 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
5659 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
5664 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
5665 PUSH2(GLX_X_RENDERABLE, TRUE);
5666 PUSH2(GLX_DOUBLEBUFFER, TRUE);
5667 TRACE("calling makeglcfg\n");
5668 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
5671 TRACE("calling chooseFGConfig\n");
5672 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5675 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
5676 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
5677 why we failed and only show this message once! */
5678 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"); /**/
5680 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
5681 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
5682 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
5683 PUSH2(GLX_DOUBLEBUFFER, FALSE);
5684 TRACE("calling makeglcfg\n");
5685 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
5687 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5694 for (i = 0; i < nCfgs; ++i) {
5695 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
5696 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
5697 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
5700 if (NULL != This->renderTarget) {
5702 vcheckGLcall("glFlush");
5703 /** This is only useful if the old render target was a swapchain,
5704 * we need to supercede this with a function that displays
5705 * the current buffer on the screen. This is easy to do in glx1.3 but
5706 * we need to do copy-write pixels in glx 1.2.
5707 ************************************************/
5708 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
5710 printf("Hit Enter to get next frame ...\n");
5716 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain) != D3D_OK) {
5717 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
5718 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
5722 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
5723 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
5724 **********************************************************************/
5725 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == D3D_OK) {
5726 /* We also need to make sure that the lights &co are also in the context of the swapchains */
5727 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
5728 TRACE("making swapchain active\n");
5729 if (RenderSurface != This->renderTarget) {
5730 if (RenderSurface == swapchain->backBuffer) {
5732 /* This could be flagged so that some operations work directly with the front buffer */
5733 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
5735 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
5737 TRACE("Error in setting current context: context %p drawable %ld !\n",
5738 impSwapChain->glCtx, impSwapChain->win);
5741 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5743 checkGLcall("glXMakeContextCurrent");
5745 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5747 else if (pbuffer_support == TRUE && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
5749 /** ********************************************************************
5750 * This is a quickly hacked out implementation of offscreen textures.
5751 * It will work in most cases but there may be problems if the client
5752 * modifies the texture directly, or expects the contents of the rendertarget
5755 * There are some real speed vs compatibility issues here:
5756 * we should really use a new context for every texture, but that eats ram.
5757 * we should also be restoring the texture to the pbuffer but that eats CPU
5758 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
5759 * but if this means reusing the display backbuffer then we need to make sure that
5760 * states are correctly preserved.
5761 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
5762 * and gain a good performance increase at the cost of compatibility.
5763 * I would suggest that, when this is the case, a user configurable flag be made
5764 * available, allowing the user to choose the best emulated experience for them.
5765 *********************************************************************/
5767 XVisualInfo *visinfo;
5768 glContext *newContext;
5770 /* Here were using a shared context model */
5771 if (D3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
5772 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5775 /* If the context doesn't exist then create a new one */
5776 /* TODO: This should really be part of findGlContext */
5777 if (NULL == newContext->context) {
5779 TRACE("making new buffer\n");
5781 PUSH2(GLX_PBUFFER_WIDTH, newContext->Width);
5782 PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
5785 newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
5787 /** ****************************************
5788 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
5790 * In future releases, we may provide the calls glXCreateNewContext,
5791 * glXQueryDrawable and glXMakeContextCurrent.
5792 * so until then we have to use glXGetVisualFromFBConfig &co..
5793 ********************************************/
5796 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
5798 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
5800 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
5804 if (NULL == newContext || NULL == newContext->context) {
5805 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5807 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
5808 if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
5809 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
5812 /* Clean up the old context */
5813 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5814 /* Set the current context of the swapchain to the new context */
5815 impSwapChain->drawable = newContext->drawable;
5816 impSwapChain->render_ctx = newContext->context;
5820 #if 1 /* Apply the stateblock to the new context
5821 FIXME: This is a bit of a hack, each context should know it's own state,
5822 the directX current directX state should then be applied to the context */
5825 IWineD3DStateBlockImpl *oldUpdateStateBlock;
5826 oldUpdateStateBlock = This->updateStateBlock;
5827 oldRecording= This->isRecordingState;
5828 This->isRecordingState = FALSE;
5829 This->updateStateBlock = This->stateBlock;
5830 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
5832 This->isRecordingState = oldRecording;
5833 This->updateStateBlock = oldUpdateStateBlock;
5838 /* clean up the current rendertargets swapchain (if it belonged to one) */
5839 if (currentSwapchain != NULL) {
5840 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
5843 /* Were done with the opengl context management, setup the rendertargets */
5845 tmp = This->renderTarget;
5846 This->renderTarget = RenderSurface;
5847 IWineD3DSurface_AddRef(This->renderTarget);
5848 IWineD3DSurface_Release(tmp);
5854 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
5855 /* Check that the container is not a swapchain member */
5857 IWineD3DSwapChain *tmpSwapChain;
5858 if (D3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
5859 This->renderUpsideDown = TRUE;
5861 This->renderUpsideDown = FALSE;
5862 IWineD3DSwapChain_Release(tmpSwapChain);
5864 /* Force updating the cull mode */
5865 TRACE("setting render state\n");
5866 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
5867 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
5869 /* Force updating projection matrix */
5870 This->last_was_rhw = FALSE;
5871 This->proj_valid = FALSE;
5879 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
5880 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
5885 if ( NULL != impSwapChain) {
5886 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
5894 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
5895 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
5896 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5897 /* TODO: the use of Impl is deprecated. */
5898 /* some basic validation checks */
5899 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
5901 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
5903 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
5904 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
5905 return D3DERR_INVALIDCALL;
5907 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
5908 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
5909 return D3DERR_INVALIDCALL;
5911 /* TODO: make the cursor 'real' */
5913 This->xHotSpot = XHotSpot;
5914 This->yHotSpot = YHotSpot;
5919 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
5920 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5921 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
5923 This->xScreenSpace = XScreenSpace;
5924 This->yScreenSpace = YScreenSpace;
5930 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
5931 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5932 TRACE("(%p) : visible(%d)\n", This, bShow);
5934 This->bCursorVisible = bShow;
5939 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
5940 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5941 TRACE("(%p) : state (%lu)\n", This, This->state);
5942 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
5943 switch (This->state) {
5946 case D3DERR_DEVICELOST:
5948 ResourceList *resourceList = This->resources;
5949 while (NULL != resourceList) {
5950 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == D3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
5951 return D3DERR_DEVICENOTRESET;
5952 resourceList = resourceList->next;
5954 return D3DERR_DEVICELOST;
5956 case D3DERR_DRIVERINTERNALERROR:
5957 return D3DERR_DRIVERINTERNALERROR;
5961 return D3DERR_DRIVERINTERNALERROR;
5965 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
5966 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5967 /** FIXME: Resource tracking needs to be done,
5968 * The closes we can do to this is set the priorities of all managed textures low
5969 * and then reset them.
5970 ***********************************************************/
5971 FIXME("(%p) : stub\n", This);
5975 HRESULT WINAPI IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
5976 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5977 /** FIXME: Resource trascking needs to be done.
5978 * in effect this pulls all non only default
5979 * textures out of video memory and deletes all glTextures (glDeleteTextures)
5980 * and should clear down the context and set it up according to pPresentationParameters
5981 ***********************************************************/
5982 FIXME("(%p) : stub\n", This);
5986 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
5987 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5988 /** FIXME: always true at the moment **/
5989 if(bEnableDialogs == FALSE) {
5990 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
5996 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
5997 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5999 FIXME("(%p) : stub\n", This);
6000 /* Setup some reasonable defaults */
6001 pParameters->AdapterOrdinal = 0; /* always for now */
6002 pParameters->DeviceType = D3DDEVTYPE_HAL; /* always for now */
6003 pParameters->hFocusWindow = 0;
6004 pParameters->BehaviorFlags =0;
6008 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
6009 IWineD3DSwapChain *swapchain;
6010 HRESULT hrc = D3D_OK;
6012 TRACE("Relaying to swapchain\n");
6014 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
6015 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (D3DGAMMARAMP *)pRamp);
6016 IWineD3DSwapChain_Release(swapchain);
6021 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
6022 IWineD3DSwapChain *swapchain;
6023 HRESULT hrc = D3D_OK;
6025 TRACE("Relaying to swapchain\n");
6027 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
6028 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
6029 IWineD3DSwapChain_Release(swapchain);
6035 /** ********************************************************
6036 * Notification functions
6037 ** ********************************************************/
6038 /** This function must be called in the release of a resource when ref == 0,
6039 * the contents of resource must still be correct,
6040 * any handels to other resource held by the caller must be closed
6041 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
6042 *****************************************************/
6043 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6044 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6045 ResourceList* resourceList;
6047 TRACE("(%p) : resource %p\n", This, resource);
6049 EnterCriticalSection(&resourceStoreCriticalSection);
6051 /* add a new texture to the frot of the linked list */
6052 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
6053 resourceList->resource = resource;
6055 /* Get the old head */
6056 resourceList->next = This->resources;
6058 This->resources = resourceList;
6059 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
6062 LeaveCriticalSection(&resourceStoreCriticalSection);
6067 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6068 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6069 ResourceList* resourceList = NULL;
6070 ResourceList* previousResourceList = NULL;
6072 TRACE("(%p) : resource %p\n", This, resource);
6075 EnterCriticalSection(&resourceStoreCriticalSection);
6077 resourceList = This->resources;
6079 while (resourceList != NULL) {
6080 if(resourceList->resource == resource) break;
6081 previousResourceList = resourceList;
6082 resourceList = resourceList->next;
6085 if (resourceList == NULL) {
6086 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
6088 LeaveCriticalSection(&resourceStoreCriticalSection);
6092 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
6094 /* make sure we don't leave a hole in the list */
6095 if (previousResourceList != NULL) {
6096 previousResourceList->next = resourceList->next;
6098 This->resources = resourceList->next;
6102 LeaveCriticalSection(&resourceStoreCriticalSection);
6108 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
6109 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6112 TRACE("(%p) : resource %p\n", This, resource);
6113 switch(IWineD3DResource_GetType(resource)){
6114 case D3DRTYPE_SURFACE:
6115 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
6117 case D3DRTYPE_TEXTURE:
6118 case D3DRTYPE_CUBETEXTURE:
6119 case D3DRTYPE_VOLUMETEXTURE:
6120 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
6121 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6122 IUnknown *textureParent;
6123 IWineD3DBaseTexture_GetParent(This->stateBlock->textures[counter], &textureParent);
6124 /* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
6125 FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter, resource, textureParent);
6126 IUnknown_Release(textureParent);
6127 This->stateBlock->textures[counter] = NULL;
6129 if (This->updateStateBlock != This->stateBlock ){
6130 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6131 IUnknown *textureParent;
6132 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[counter], &textureParent);
6133 /* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
6134 FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter, resource, textureParent);
6135 IUnknown_Release(textureParent);
6136 This->updateStateBlock->textures[counter] = NULL;
6141 case D3DRTYPE_VOLUME:
6142 /* TODO: nothing really? */
6144 case D3DRTYPE_VERTEXBUFFER:
6145 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
6148 TRACE("Cleaning up stream pointers\n");
6150 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
6151 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
6152 FINDOUT: should changes.streamSource[StreamNumber] be set ?
6154 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6155 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
6156 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
6157 This->updateStateBlock->streamSource[streamNumber] = 0;
6158 /* Set changed flag? */
6161 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) */
6162 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
6163 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
6164 This->stateBlock->streamSource[streamNumber] = 0;
6167 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
6168 else { /* This shouldn't happen */
6169 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
6176 case D3DRTYPE_INDEXBUFFER:
6177 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
6178 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6179 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6180 This->updateStateBlock->pIndexData = NULL;
6183 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
6184 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6185 This->stateBlock->pIndexData = NULL;
6191 FIXME("(%p) unknown resource type %p %u \n", This, resource, IWineD3DResource_GetType(resource));
6196 /* Remove the resoruce from the resourceStore */
6197 IWineD3DDeviceImpl_RemoveResource(iface, resource);
6199 TRACE("Resource released\n");
6204 /** This function is to be called by the swapchain when it is released and it's ref = 0
6205 *****************************************************/
6206 void WINAPI IWineD3DDeviceImpl_SwapChainReleased(IWineD3DDevice *iface, IWineD3DSwapChain *swapChain){
6207 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6208 SwapChainList **nextSwapchain;
6209 nextSwapchain = &This->swapchains;
6211 /* Check to see if the swapchian is being used as the render target */
6212 if (This->renderTarget != NULL) {
6213 IWineD3DSurface *swapchainBackBuffer;
6215 IWineD3DSwapChain_GetBackBuffer(swapChain, 0 ,( D3DBACKBUFFER_TYPE) 0, &swapchainBackBuffer);
6216 if (This->renderTarget == swapchainBackBuffer) {
6217 /* Don't know what to do, so warn and carry on as usual (which in this case leaves the renderterget in limbo) */
6218 FIXME("Atempting to release a swapchain that is currently beuing used as a render target, behaviour is undefined\n");
6222 /* Go through the swapchain list and try to find the swapchain being released */
6223 while(*nextSwapchain != NULL && (*nextSwapchain)->swapchain != swapChain) {
6224 nextSwapchain = &(*nextSwapchain)->next;
6227 /* Check to see if we found the swapchain */
6228 if (NULL != *nextSwapchain) {
6229 /* We found the swapchain so remove it from the list */
6230 TRACE("(%p) releasing swapchain(%p)\n", iface, swapChain);
6231 HeapFree(GetProcessHeap(), 0 , *nextSwapchain);
6232 *nextSwapchain = (*nextSwapchain)->next;
6234 /* We didn't find the swapchain on the list, this can only heppen because of a programming error in wined3d */
6235 FIXME("(%p) Attempting to release a swapchain (%p) that hasn't been stored\n", iface, swapChain);
6238 TRACE("swapchain (%p) released\n", swapChain);
6242 /**********************************************************
6243 * IWineD3DDevice VTbl follows
6244 **********************************************************/
6246 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
6248 /*** IUnknown methods ***/
6249 IWineD3DDeviceImpl_QueryInterface,
6250 IWineD3DDeviceImpl_AddRef,
6251 IWineD3DDeviceImpl_Release,
6252 /*** IWineD3DDevice methods ***/
6253 IWineD3DDeviceImpl_GetParent,
6254 /*** Creation methods**/
6255 IWineD3DDeviceImpl_CreateVertexBuffer,
6256 IWineD3DDeviceImpl_CreateIndexBuffer,
6257 IWineD3DDeviceImpl_CreateStateBlock,
6258 IWineD3DDeviceImpl_CreateSurface,
6259 IWineD3DDeviceImpl_CreateTexture,
6260 IWineD3DDeviceImpl_CreateVolumeTexture,
6261 IWineD3DDeviceImpl_CreateVolume,
6262 IWineD3DDeviceImpl_CreateCubeTexture,
6263 IWineD3DDeviceImpl_CreateQuery,
6264 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
6265 IWineD3DDeviceImpl_CreateVertexDeclaration,
6266 IWineD3DDeviceImpl_CreateVertexShader,
6267 IWineD3DDeviceImpl_CreatePixelShader,
6268 /*** Odd functions **/
6269 IWineD3DDeviceImpl_EvictManagedResources,
6270 IWineD3DDeviceImpl_GetAvailableTextureMem,
6271 IWineD3DDeviceImpl_GetBackBuffer,
6272 IWineD3DDeviceImpl_GetCreationParameters,
6273 IWineD3DDeviceImpl_GetDeviceCaps,
6274 IWineD3DDeviceImpl_GetDirect3D,
6275 IWineD3DDeviceImpl_GetDisplayMode,
6276 IWineD3DDeviceImpl_GetNumberOfSwapChains,
6277 IWineD3DDeviceImpl_GetRasterStatus,
6278 IWineD3DDeviceImpl_GetSwapChain,
6279 IWineD3DDeviceImpl_Reset,
6280 IWineD3DDeviceImpl_SetDialogBoxMode,
6281 IWineD3DDeviceImpl_SetCursorProperties,
6282 IWineD3DDeviceImpl_SetCursorPosition,
6283 IWineD3DDeviceImpl_ShowCursor,
6284 IWineD3DDeviceImpl_TestCooperativeLevel,
6285 /*** Getters and setters **/
6286 IWineD3DDeviceImpl_SetClipPlane,
6287 IWineD3DDeviceImpl_GetClipPlane,
6288 IWineD3DDeviceImpl_SetClipStatus,
6289 IWineD3DDeviceImpl_GetClipStatus,
6290 IWineD3DDeviceImpl_SetCurrentTexturePalette,
6291 IWineD3DDeviceImpl_GetCurrentTexturePalette,
6292 IWineD3DDeviceImpl_SetDepthStencilSurface,
6293 IWineD3DDeviceImpl_GetDepthStencilSurface,
6294 IWineD3DDeviceImpl_SetFVF,
6295 IWineD3DDeviceImpl_GetFVF,
6296 IWineD3DDeviceImpl_SetGammaRamp,
6297 IWineD3DDeviceImpl_GetGammaRamp,
6298 IWineD3DDeviceImpl_SetIndices,
6299 IWineD3DDeviceImpl_GetIndices,
6300 IWineD3DDeviceImpl_SetLight,
6301 IWineD3DDeviceImpl_GetLight,
6302 IWineD3DDeviceImpl_SetLightEnable,
6303 IWineD3DDeviceImpl_GetLightEnable,
6304 IWineD3DDeviceImpl_SetMaterial,
6305 IWineD3DDeviceImpl_GetMaterial,
6306 IWineD3DDeviceImpl_SetNPatchMode,
6307 IWineD3DDeviceImpl_GetNPatchMode,
6308 IWineD3DDeviceImpl_SetPaletteEntries,
6309 IWineD3DDeviceImpl_GetPaletteEntries,
6310 IWineD3DDeviceImpl_SetPixelShader,
6311 IWineD3DDeviceImpl_GetPixelShader,
6312 IWineD3DDeviceImpl_SetPixelShaderConstantB,
6313 IWineD3DDeviceImpl_GetPixelShaderConstantB,
6314 IWineD3DDeviceImpl_SetPixelShaderConstantI,
6315 IWineD3DDeviceImpl_GetPixelShaderConstantI,
6316 IWineD3DDeviceImpl_SetPixelShaderConstantF,
6317 IWineD3DDeviceImpl_GetPixelShaderConstantF,
6318 IWineD3DDeviceImpl_SetRenderState,
6319 IWineD3DDeviceImpl_GetRenderState,
6320 IWineD3DDeviceImpl_SetRenderTarget,
6321 IWineD3DDeviceImpl_GetRenderTarget,
6322 IWineD3DDeviceImpl_SetSamplerState,
6323 IWineD3DDeviceImpl_GetSamplerState,
6324 IWineD3DDeviceImpl_SetScissorRect,
6325 IWineD3DDeviceImpl_GetScissorRect,
6326 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
6327 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
6328 IWineD3DDeviceImpl_SetStreamSource,
6329 IWineD3DDeviceImpl_GetStreamSource,
6330 IWineD3DDeviceImpl_SetStreamSourceFreq,
6331 IWineD3DDeviceImpl_GetStreamSourceFreq,
6332 IWineD3DDeviceImpl_SetTexture,
6333 IWineD3DDeviceImpl_GetTexture,
6334 IWineD3DDeviceImpl_SetTextureStageState,
6335 IWineD3DDeviceImpl_GetTextureStageState,
6336 IWineD3DDeviceImpl_SetTransform,
6337 IWineD3DDeviceImpl_GetTransform,
6338 IWineD3DDeviceImpl_SetVertexDeclaration,
6339 IWineD3DDeviceImpl_GetVertexDeclaration,
6340 IWineD3DDeviceImpl_SetVertexShader,
6341 IWineD3DDeviceImpl_GetVertexShader,
6342 IWineD3DDeviceImpl_SetVertexShaderConstantB,
6343 IWineD3DDeviceImpl_GetVertexShaderConstantB,
6344 IWineD3DDeviceImpl_SetVertexShaderConstantI,
6345 IWineD3DDeviceImpl_GetVertexShaderConstantI,
6346 IWineD3DDeviceImpl_SetVertexShaderConstantF,
6347 IWineD3DDeviceImpl_GetVertexShaderConstantF,
6348 IWineD3DDeviceImpl_SetViewport,
6349 IWineD3DDeviceImpl_GetViewport,
6350 IWineD3DDeviceImpl_MultiplyTransform,
6351 IWineD3DDeviceImpl_ValidateDevice,
6352 IWineD3DDeviceImpl_ProcessVertices,
6353 /*** State block ***/
6354 IWineD3DDeviceImpl_BeginStateBlock,
6355 IWineD3DDeviceImpl_EndStateBlock,
6356 /*** Scene management ***/
6357 IWineD3DDeviceImpl_BeginScene,
6358 IWineD3DDeviceImpl_EndScene,
6359 IWineD3DDeviceImpl_Present,
6360 IWineD3DDeviceImpl_Clear,
6362 IWineD3DDeviceImpl_DrawPrimitive,
6363 IWineD3DDeviceImpl_DrawIndexedPrimitive,
6364 IWineD3DDeviceImpl_DrawPrimitiveUP,
6365 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
6366 IWineD3DDeviceImpl_DrawRectPatch,
6367 IWineD3DDeviceImpl_DrawTriPatch,
6368 IWineD3DDeviceImpl_DeletePatch,
6369 IWineD3DDeviceImpl_ColorFill,
6370 IWineD3DDeviceImpl_UpdateTexture,
6371 IWineD3DDeviceImpl_UpdateSurface,
6372 IWineD3DDeviceImpl_StretchRect,
6373 IWineD3DDeviceImpl_GetRenderTargetData,
6374 IWineD3DDeviceImpl_GetFrontBufferData,
6375 /*** Internal use IWineD3DDevice methods ***/
6376 IWineD3DDeviceImpl_SetupTextureStates,
6377 /*** object tracking ***/
6378 IWineD3DDeviceImpl_SwapChainReleased,
6379 IWineD3DDeviceImpl_ResourceReleased
6383 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
6384 WINED3DRS_ALPHABLENDENABLE ,
6385 WINED3DRS_ALPHAFUNC ,
6386 WINED3DRS_ALPHAREF ,
6387 WINED3DRS_ALPHATESTENABLE ,
6389 WINED3DRS_COLORWRITEENABLE ,
6390 WINED3DRS_DESTBLEND ,
6391 WINED3DRS_DITHERENABLE ,
6392 WINED3DRS_FILLMODE ,
6393 WINED3DRS_FOGDENSITY ,
6395 WINED3DRS_FOGSTART ,
6396 WINED3DRS_LASTPIXEL ,
6397 WINED3DRS_SHADEMODE ,
6398 WINED3DRS_SRCBLEND ,
6399 WINED3DRS_STENCILENABLE ,
6400 WINED3DRS_STENCILFAIL ,
6401 WINED3DRS_STENCILFUNC ,
6402 WINED3DRS_STENCILMASK ,
6403 WINED3DRS_STENCILPASS ,
6404 WINED3DRS_STENCILREF ,
6405 WINED3DRS_STENCILWRITEMASK ,
6406 WINED3DRS_STENCILZFAIL ,
6407 WINED3DRS_TEXTUREFACTOR ,
6418 WINED3DRS_ZWRITEENABLE
6421 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
6422 WINED3DTSS_ADDRESSW ,
6423 WINED3DTSS_ALPHAARG0 ,
6424 WINED3DTSS_ALPHAARG1 ,
6425 WINED3DTSS_ALPHAARG2 ,
6426 WINED3DTSS_ALPHAOP ,
6427 WINED3DTSS_BUMPENVLOFFSET ,
6428 WINED3DTSS_BUMPENVLSCALE ,
6429 WINED3DTSS_BUMPENVMAT00 ,
6430 WINED3DTSS_BUMPENVMAT01 ,
6431 WINED3DTSS_BUMPENVMAT10 ,
6432 WINED3DTSS_BUMPENVMAT11 ,
6433 WINED3DTSS_COLORARG0 ,
6434 WINED3DTSS_COLORARG1 ,
6435 WINED3DTSS_COLORARG2 ,
6436 WINED3DTSS_COLOROP ,
6437 WINED3DTSS_RESULTARG ,
6438 WINED3DTSS_TEXCOORDINDEX ,
6439 WINED3DTSS_TEXTURETRANSFORMFLAGS
6442 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
6443 WINED3DSAMP_ADDRESSU ,
6444 WINED3DSAMP_ADDRESSV ,
6445 WINED3DSAMP_ADDRESSW ,
6446 WINED3DSAMP_BORDERCOLOR ,
6447 WINED3DSAMP_MAGFILTER ,
6448 WINED3DSAMP_MINFILTER ,
6449 WINED3DSAMP_MIPFILTER ,
6450 WINED3DSAMP_MIPMAPLODBIAS ,
6451 WINED3DSAMP_MAXMIPLEVEL ,
6452 WINED3DSAMP_MAXANISOTROPY ,
6453 WINED3DSAMP_SRGBTEXTURE ,
6454 WINED3DSAMP_ELEMENTINDEX
6457 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
6459 WINED3DRS_AMBIENTMATERIALSOURCE ,
6460 WINED3DRS_CLIPPING ,
6461 WINED3DRS_CLIPPLANEENABLE ,
6462 WINED3DRS_COLORVERTEX ,
6463 WINED3DRS_DIFFUSEMATERIALSOURCE ,
6464 WINED3DRS_EMISSIVEMATERIALSOURCE ,
6465 WINED3DRS_FOGDENSITY ,
6467 WINED3DRS_FOGSTART ,
6468 WINED3DRS_FOGTABLEMODE ,
6469 WINED3DRS_FOGVERTEXMODE ,
6470 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
6471 WINED3DRS_LIGHTING ,
6472 WINED3DRS_LOCALVIEWER ,
6473 WINED3DRS_MULTISAMPLEANTIALIAS ,
6474 WINED3DRS_MULTISAMPLEMASK ,
6475 WINED3DRS_NORMALIZENORMALS ,
6476 WINED3DRS_PATCHEDGESTYLE ,
6477 WINED3DRS_POINTSCALE_A ,
6478 WINED3DRS_POINTSCALE_B ,
6479 WINED3DRS_POINTSCALE_C ,
6480 WINED3DRS_POINTSCALEENABLE ,
6481 WINED3DRS_POINTSIZE ,
6482 WINED3DRS_POINTSIZE_MAX ,
6483 WINED3DRS_POINTSIZE_MIN ,
6484 WINED3DRS_POINTSPRITEENABLE ,
6485 WINED3DRS_RANGEFOGENABLE ,
6486 WINED3DRS_SPECULARMATERIALSOURCE ,
6487 WINED3DRS_TWEENFACTOR ,
6488 WINED3DRS_VERTEXBLEND
6491 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
6492 WINED3DTSS_TEXCOORDINDEX ,
6493 WINED3DTSS_TEXTURETRANSFORMFLAGS
6496 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
6497 WINED3DSAMP_DMAPOFFSET