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 D3DINITIALIZEBASETEXTURE(_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 (WINED3DFMT_UNKNOWN == Format) {
715 } else if (Format == WINED3DFMT_DXT1) {
716 /* DXT1 is half byte per pixel */
717 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4)) >> 1;
719 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
720 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
721 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4));
723 Size = (pow2Width * D3DFmtGetBpp(This, Format)) * pow2Height;
726 /** Create and initialise the surface resource **/
727 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,D3DRTYPE_SURFACE, Size)
728 object->container = (IUnknown*) This;
730 object->currentDesc.Width = Width;
731 object->currentDesc.Height = Height;
732 object->currentDesc.MultiSampleType = MultiSample;
733 object->currentDesc.MultiSampleQuality = MultisampleQuality;
735 /* Setup some glformat defaults */
736 if (WINED3DFMT_UNKNOWN != Format) {
737 object->glDescription.glFormat = D3DFmt2GLFmt(This, object->resource.format);
738 object->glDescription.glFormatInternal = D3DFmt2GLIntFmt(This, object->resource.format);
739 object->glDescription.glType = D3DFmt2GLType(This, object->resource.format);
741 object->glDescription.glFormat = 0;
742 object->glDescription.glFormatInternal = 0;
743 object->glDescription.glType = 0;
746 object->glDescription.textureName = 0;
747 object->glDescription.level = Level;
748 object->glDescription.target = GL_TEXTURE_2D;
751 object->pow2Width = pow2Width;
752 object->pow2Height = pow2Height;
753 object->nonpow2 = (pow2Width != Width || pow2Height != Height) ? TRUE : FALSE;
754 object->discard = Discard;
755 object->activeLock = FALSE;
757 if (WINED3DFMT_UNKNOWN != Format) {
758 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
759 object->pow2Size = (pow2Width * object->bytesPerPixel) * pow2Height;
761 object->bytesPerPixel = 0;
762 object->pow2Size = 0;
765 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
767 TRACE("Pool %d %d %d %d",Pool, D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM);
769 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
770 * this function is too deap to need to care about things like this.
771 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
772 * ****************************************/
774 case D3DPOOL_SCRATCH:
775 if(Lockable == FALSE)
776 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
777 which are mutually exclusive, setting lockable to true\n");
780 case D3DPOOL_SYSTEMMEM:
781 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
782 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
783 case D3DPOOL_MANAGED:
784 if(Usage == D3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
785 Usage of DYNAMIC which are mutually exclusive, not doing \
786 anything just telling you.\n");
788 case D3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
789 if(!(Usage & D3DUSAGE_DYNAMIC) && !(Usage & D3DUSAGE_RENDERTARGET)
790 && !(Usage && D3DUSAGE_DEPTHSTENCIL ) && Lockable == TRUE)
791 FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
794 FIXME("(%p) Unknown pool %d\n", This, Pool);
798 if (Usage & D3DUSAGE_RENDERTARGET && Pool != D3DPOOL_DEFAULT) {
799 FIXME("Trying to create a render target that isn't in the default pool\n");
803 object->locked = FALSE;
804 object->lockable = (WINED3DFMT_D16_LOCKABLE == Format) ? TRUE : Lockable;
806 /* mark the texture as dirty so that it get's loaded first time around*/
807 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
808 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
809 This, Width, Height, Format, debug_d3dformat(Format),
810 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
815 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
816 DWORD Usage, WINED3DFORMAT Format, D3DPOOL Pool,
817 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
818 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
820 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
821 IWineD3DTextureImpl *object;
826 unsigned int pow2Width = Width;
827 unsigned int pow2Height = Height;
830 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) ....\n", This, Width, Height, Levels, Usage);
832 /* TODO: It should only be possible to create textures for formats
833 that are reported as supported */
834 if (WINED3DFMT_UNKNOWN >= Format) {
835 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
836 return D3DERR_INVALIDCALL;
839 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, D3DRTYPE_TEXTURE, 0);
840 D3DINITIALIZEBASETEXTURE(object->baseTexture);
841 object->width = Width;
842 object->height = Height;
844 /** Non-power2 support **/
845 /* Find the nearest pow2 match */
846 pow2Width = pow2Height = 1;
847 while (pow2Width < Width) pow2Width <<= 1;
848 while (pow2Height < Height) pow2Height <<= 1;
850 /** FIXME: add support for real non-power-two if it's provided by the video card **/
851 /* Precalculated scaling for 'faked' non power of two texture coords */
852 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
853 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
854 TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
856 /* Calculate levels for mip mapping */
858 TRACE("calculating levels %d\n", object->baseTexture.levels);
859 object->baseTexture.levels++;
862 while (tmpW > 1 && tmpH > 1) {
863 tmpW = max(1, tmpW >> 1);
864 tmpH = max(1, tmpH >> 1);
865 object->baseTexture.levels++;
867 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
870 /* Generate all the surfaces */
873 for (i = 0; i < object->baseTexture.levels; i++)
875 /* use the callback to create the texture surface */
876 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
879 FIXME("Failed to create surface %p\n", object);
881 for (j = 0 ; j < i ; j++) {
882 IWineD3DSurface_Release(object->surfaces[j]);
884 /* heap free object */
885 HeapFree(GetProcessHeap(), 0, object);
891 IWineD3DSurface_SetContainer(object->surfaces[i], (IUnknown *)object);
892 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
893 /* calculate the next mipmap level */
894 tmpW = max(1, tmpW >> 1);
895 tmpH = max(1, tmpH >> 1);
898 TRACE("(%p) : Created texture %p\n", This, object);
902 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
903 UINT Width, UINT Height, UINT Depth,
904 UINT Levels, DWORD Usage,
905 WINED3DFORMAT Format, D3DPOOL Pool,
906 IWineD3DVolumeTexture **ppVolumeTexture,
907 HANDLE *pSharedHandle, IUnknown *parent,
908 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
910 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
911 IWineD3DVolumeTextureImpl *object;
917 /* TODO: It should only be possible to create textures for formats
918 that are reported as supported */
919 if (WINED3DFMT_UNKNOWN >= Format) {
920 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
921 return D3DERR_INVALIDCALL;
924 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, D3DRTYPE_VOLUMETEXTURE, 0);
925 D3DINITIALIZEBASETEXTURE(object->baseTexture);
927 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
928 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
930 object->width = Width;
931 object->height = Height;
932 object->depth = Depth;
934 /* Calculate levels for mip mapping */
936 object->baseTexture.levels++;
940 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
941 tmpW = max(1, tmpW >> 1);
942 tmpH = max(1, tmpH >> 1);
943 tmpD = max(1, tmpD >> 1);
944 object->baseTexture.levels++;
946 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
949 /* Generate all the surfaces */
954 for (i = 0; i < object->baseTexture.levels; i++)
956 /* Create the volume */
957 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
958 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
960 /* Set it's container to this object */
961 IWineD3DVolume_SetContainer(object->volumes[i], (IUnknown *)object);
963 /* calcualte the next mipmap level */
964 tmpW = max(1, tmpW >> 1);
965 tmpH = max(1, tmpH >> 1);
966 tmpD = max(1, tmpD >> 1);
969 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
970 TRACE("(%p) : Created volume texture %p\n", This, object);
974 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
975 UINT Width, UINT Height, UINT Depth,
977 WINED3DFORMAT Format, D3DPOOL Pool,
978 IWineD3DVolume** ppVolume,
979 HANDLE* pSharedHandle, IUnknown *parent) {
981 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
982 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
984 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, D3DRTYPE_VOLUME, ((Width * D3DFmtGetBpp(This, Format)) * Height * Depth))
986 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
987 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
989 object->currentDesc.Width = Width;
990 object->currentDesc.Height = Height;
991 object->currentDesc.Depth = Depth;
992 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
994 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
995 object->lockable = TRUE;
996 object->locked = FALSE;
997 memset(&object->lockedBox, 0, sizeof(D3DBOX));
998 object->dirty = TRUE;
1000 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
1003 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
1004 UINT Levels, DWORD Usage,
1005 WINED3DFORMAT Format, D3DPOOL Pool,
1006 IWineD3DCubeTexture **ppCubeTexture,
1007 HANDLE *pSharedHandle, IUnknown *parent,
1008 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1010 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1011 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1015 unsigned int pow2EdgeLength = EdgeLength;
1017 /* TODO: It should only be possible to create textures for formats
1018 that are reported as supported */
1019 if (WINED3DFMT_UNKNOWN >= Format) {
1020 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
1021 return D3DERR_INVALIDCALL;
1024 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, D3DRTYPE_CUBETEXTURE, 0);
1025 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1027 TRACE("(%p) Create Cube Texture\n", This);
1029 /** Non-power2 support **/
1031 /* Find the nearest pow2 match */
1033 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
1035 object->edgeLength = EdgeLength;
1036 /* TODO: support for native non-power 2 */
1037 /* Precalculated scaling for 'faked' non power of two texture coords */
1038 object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
1040 /* Calculate levels for mip mapping */
1042 object->baseTexture.levels++;
1045 tmpW = max(1, tmpW >> 1);
1046 object->baseTexture.levels++;
1048 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1051 /* Generate all the surfaces */
1053 for (i = 0; i < object->baseTexture.levels; i++) {
1055 /* Create the 6 faces */
1056 for (j = 0; j < 6; j++) {
1058 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
1059 i /* Level */, &object->surfaces[j][i],pSharedHandle);
1065 for (l = 0; l < j; l++) {
1066 IWineD3DSurface_Release(object->surfaces[j][i]);
1068 for (k = 0; k < i; k++) {
1069 for (l = 0; l < 6; l++) {
1070 IWineD3DSurface_Release(object->surfaces[l][j]);
1074 FIXME("(%p) Failed to create surface\n",object);
1075 HeapFree(GetProcessHeap(),0,object);
1076 *ppCubeTexture = NULL;
1079 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IUnknown *)object);
1080 TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1082 tmpW = max(1, tmpW >> 1);
1085 TRACE("(%p) : Created Cube Texture %p\n", This, object);
1086 *ppCubeTexture = (IWineD3DCubeTexture *) object;
1090 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1091 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1092 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1094 if (NULL == ppQuery) {
1095 /* Just a check to see if we support this type of query */
1096 HRESULT hr = D3DERR_NOTAVAILABLE;
1097 /* Lie and say everything is good (we can return ok fake data from a stub) */
1099 case WINED3DQUERYTYPE_VCACHE:
1100 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1101 case WINED3DQUERYTYPE_VERTEXSTATS:
1102 case WINED3DQUERYTYPE_EVENT:
1103 case WINED3DQUERYTYPE_TIMESTAMP:
1104 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1105 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1106 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1107 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1108 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1109 case WINED3DQUERYTYPE_PIXELTIMINGS:
1110 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1111 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1113 case WINED3DQUERYTYPE_OCCLUSION:
1114 TRACE("(%p) occlusion query\n", This);
1115 if (GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY))
1119 FIXME("(%p) Unhandled query type %d\n",This , Type);
1121 FIXME("(%p) : Stub request for query type %d returned %ld\n", This, Type, hr);
1125 D3DCREATEOBJECTINSTANCE(object, Query)
1126 object->type = Type;
1127 /* allocated the 'extended' data based on the type of query requested */
1129 case D3DQUERYTYPE_OCCLUSION:
1130 if(GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY)) {
1131 TRACE("(%p) Allocating data for an occlusion query\n", This);
1132 object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1135 case D3DQUERYTYPE_VCACHE:
1136 case D3DQUERYTYPE_RESOURCEMANAGER:
1137 case D3DQUERYTYPE_VERTEXSTATS:
1138 case D3DQUERYTYPE_EVENT:
1139 case D3DQUERYTYPE_TIMESTAMP:
1140 case D3DQUERYTYPE_TIMESTAMPDISJOINT:
1141 case D3DQUERYTYPE_TIMESTAMPFREQ:
1142 case D3DQUERYTYPE_PIPELINETIMINGS:
1143 case D3DQUERYTYPE_INTERFACETIMINGS:
1144 case D3DQUERYTYPE_VERTEXTIMINGS:
1145 case D3DQUERYTYPE_PIXELTIMINGS:
1146 case D3DQUERYTYPE_BANDWIDTHTIMINGS:
1147 case D3DQUERYTYPE_CACHEUTILIZATION:
1149 object->extendedData = 0;
1150 FIXME("(%p) Unhandled query type %d\n",This , Type);
1152 TRACE("(%p) : Created Query %p\n", This, object);
1156 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1157 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1159 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1160 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1161 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1164 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1166 XVisualInfo template;
1167 GLXContext oldContext;
1168 Drawable oldDrawable;
1169 HRESULT hr = D3D_OK;
1171 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1173 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1174 * does a device hold a reference to a swap chain giving them a lifetime of the device
1175 * or does the swap chain notify the device of its destruction.
1176 *******************************/
1178 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1180 /* Initialize other useful values */
1181 object->presentParms.BackBufferCount = 1; /* TODO:? support for gl_aux buffers */
1183 /*********************
1184 * Lookup the window Handle and the relating X window handle
1185 ********************/
1187 /* Setup hwnd we are using, plus which display this equates to */
1188 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1189 if (!object->win_handle) {
1190 object->win_handle = This->createParms.hFocusWindow;
1193 object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window" );
1194 hDc = GetDC(object->win_handle);
1195 object->display = get_display(hDc);
1196 ReleaseDC(object->win_handle, hDc);
1197 TRACE("Using a display of %p %p\n", object->display, hDc);
1199 if (NULL == object->display || NULL == hDc) {
1200 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1201 return D3DERR_NOTAVAILABLE;
1204 if (object->win == 0) {
1205 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1206 return D3DERR_NOTAVAILABLE;
1209 * Create an opengl context for the display visual
1210 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1211 * use different properties after that point in time. FIXME: How to handle when requested format
1212 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1213 * it chooses is identical to the one already being used!
1214 **********************************/
1216 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1219 /* Create a new context for this swapchain */
1220 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1221 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1222 (or the best possible if none is requested) */
1223 TRACE("Found x visual ID : %ld\n", template.visualid);
1225 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1226 if (NULL == object->visInfo) {
1227 ERR("cannot really get XVisual\n");
1229 return D3DERR_NOTAVAILABLE;
1232 /* Write out some debug info about the visual/s */
1233 TRACE("Using x visual ID : %ld\n", template.visualid);
1234 TRACE(" visual info: %p\n", object->visInfo);
1235 TRACE(" num items : %d\n", num);
1236 for (n = 0;n < num; n++) {
1237 TRACE("=====item=====: %d\n", n + 1);
1238 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1239 TRACE(" screen : %d\n", object->visInfo[n].screen);
1240 TRACE(" depth : %u\n", object->visInfo[n].depth);
1241 TRACE(" class : %d\n", object->visInfo[n].class);
1242 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1243 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1244 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1245 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1246 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1247 /* log some extra glx info */
1248 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1249 TRACE(" gl_aux_buffers : %d\n", value);
1250 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1251 TRACE(" gl_buffer_size : %d\n", value);
1252 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1253 TRACE(" gl_red_size : %d\n", value);
1254 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1255 TRACE(" gl_green_size : %d\n", value);
1256 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1257 TRACE(" gl_blue_size : %d\n", value);
1258 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1259 TRACE(" gl_alpha_size : %d\n", value);
1260 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1261 TRACE(" gl_depth_size : %d\n", value);
1262 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1263 TRACE(" gl_stencil_size : %d\n", value);
1265 /* Now choose a simila visual ID*/
1267 #ifdef USE_CONTEXT_MANAGER
1269 /** TODO: use a context mamager **/
1273 IWineD3DSwapChain *implSwapChain;
1274 if (D3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1275 /* The first time around we create the context that is shared with all other swapchains and render targets */
1276 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1277 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1280 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1281 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1282 /* and create a new context with the implicit swapchains context as the shared context */
1283 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1284 IWineD3DSwapChain_Release(implSwapChain);
1289 XFree(object->visInfo);
1290 object->visInfo = NULL;
1292 if (NULL == object->glCtx) {
1293 ERR("cannot create glxContext\n");
1295 return D3DERR_NOTAVAILABLE;
1299 if (object->glCtx == NULL) {
1300 ERR("Error in context creation !\n");
1301 return D3DERR_INVALIDCALL;
1303 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1304 object->win_handle, object->glCtx, object->win, object->visInfo);
1307 /*********************
1308 * Windowed / Fullscreen
1309 *******************/
1312 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1313 * so we should really check to see if there is a fullscreen swapchain already
1314 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1315 **************************************/
1317 if (!*(pPresentationParameters->Windowed)) {
1323 /* Get info on the current display setup */
1324 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1325 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1328 /* Change the display settings */
1329 memset(&devmode, 0, sizeof(DEVMODEW));
1330 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1331 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1332 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1333 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1334 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1335 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1337 /* Make popup window */
1338 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1339 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1340 *(pPresentationParameters->BackBufferWidth),
1341 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1347 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1348 * then the corresponding dimension of the client area of the hDeviceWindow
1349 * (or the focus window, if hDeviceWindow is NULL) is taken.
1350 **********************/
1352 if (*(pPresentationParameters->Windowed) &&
1353 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1354 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1357 GetClientRect(object->win_handle, &Rect);
1359 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1360 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1361 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1363 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1364 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1365 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1369 /*********************
1370 * finish off parameter initialization
1371 *******************/
1373 /* Put the correct figures in the presentation parameters */
1374 TRACE("Coppying accross presentaion paraneters\n");
1375 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1376 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1377 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1378 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1379 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1380 object->presentParms.MultiSampleQuality = *(pPresentationParameters->MultiSampleQuality);
1381 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1382 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1383 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1384 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1385 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1386 object->presentParms.Flags = *(pPresentationParameters->Flags);
1387 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1388 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1391 /*********************
1392 * Create the back, front and stencil buffers
1393 *******************/
1394 TRACE("calling rendertarget CB\n");
1395 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1396 object->presentParms.BackBufferWidth,
1397 object->presentParms.BackBufferHeight,
1398 object->presentParms.BackBufferFormat,
1399 object->presentParms.MultiSampleType,
1400 object->presentParms.MultiSampleQuality,
1401 TRUE /* Lockable */,
1402 &object->frontBuffer,
1403 NULL /* pShared (always null)*/);
1404 if (object->frontBuffer != NULL)
1405 IWineD3DSurface_SetContainer(object->frontBuffer, (IUnknown *)object);
1406 TRACE("calling rendertarget CB\n");
1407 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1408 object->presentParms.BackBufferWidth,
1409 object->presentParms.BackBufferHeight,
1410 object->presentParms.BackBufferFormat,
1411 object->presentParms.MultiSampleType,
1412 object->presentParms.MultiSampleQuality,
1413 TRUE /* Lockable */,
1414 &object->backBuffer,
1415 NULL /* pShared (always null)*/);
1416 if (object->backBuffer != NULL)
1417 IWineD3DSurface_SetContainer(object->backBuffer, (IUnknown *)object);
1419 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1420 if (pPresentationParameters->EnableAutoDepthStencil) {
1421 TRACE("Creating depth stencil buffer\n");
1422 if (This->depthStencilBuffer == NULL ) {
1423 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1424 object->presentParms.BackBufferWidth,
1425 object->presentParms.BackBufferHeight,
1426 object->presentParms.AutoDepthStencilFormat,
1427 object->presentParms.MultiSampleType,
1428 object->presentParms.MultiSampleQuality,
1429 FALSE /* FIXME: Discard */,
1430 &This->depthStencilBuffer,
1431 NULL /* pShared (always null)*/ );
1432 if (This->depthStencilBuffer != NULL)
1433 IWineD3DSurface_SetContainer(This->depthStencilBuffer, (IUnknown *)iface);
1436 /** TODO: A check on width, height and multisample types
1437 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1438 ****************************/
1439 object->wantsDepthStencilBuffer = TRUE;
1441 object->wantsDepthStencilBuffer = FALSE;
1444 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1447 /*********************
1448 * init the default renderTarget management
1449 *******************/
1450 object->drawable = object->win;
1451 object->render_ctx = object->glCtx;
1454 /*********************
1455 * Setup some defaults and clear down the buffers
1456 *******************/
1458 /** save current context and drawable **/
1459 oldContext = glXGetCurrentContext();
1460 oldDrawable = glXGetCurrentDrawable();
1462 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1463 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1464 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1466 checkGLcall("glXMakeCurrent");
1468 TRACE("Setting up the screen\n");
1469 /* Clear the screen */
1470 glClearColor(1.0, 0.0, 0.0, 0.0);
1471 checkGLcall("glClearColor");
1474 glClearStencil(0xffff);
1476 checkGLcall("glClear");
1478 glColor3f(1.0, 1.0, 1.0);
1479 checkGLcall("glColor3f");
1481 glEnable(GL_LIGHTING);
1482 checkGLcall("glEnable");
1484 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1485 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1487 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1488 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1490 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1491 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1493 /* switch back to the original context (if there was one)*/
1494 if (This->swapchains != NULL) {
1495 /** TODO: restore the context and drawable **/
1496 glXMakeCurrent(object->display, oldDrawable, oldContext);
1501 { /* Finally add the swapchain to the end of the devices' swapchain list */
1502 SwapChainList **nextSwapchain;
1503 nextSwapchain = &This->swapchains;
1504 while (*nextSwapchain != NULL) {
1505 nextSwapchain = &((*nextSwapchain)->next);
1507 (*nextSwapchain) = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->swapchains));
1508 (*nextSwapchain)->swapchain = (IWineD3DSwapChain *)object;
1510 TRACE("Set swapchain to %p\n", object);
1511 } else { /* something went wrong so clean up */
1512 IUnknown* bufferParent;
1513 if (object->frontBuffer) {
1514 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1515 IUnknown_Release(bufferParent); /* once for the get parent */
1516 if (IUnknown_Release(bufferParent) > 0) {
1517 FIXME("(%p) Something's still holding the front buffer\n",This);
1520 if (object->backBuffer) {
1521 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1522 IUnknown_Release(bufferParent); /* once for the get parent */
1523 if (IUnknown_Release(bufferParent) > 0) {
1524 FIXME("(%p) Something's still holding the back buffer\n",This);
1527 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1528 /* Clean up the context */
1529 /* check that we are the current context first (we shouldn't be though!) */
1530 if (object->glCtx != 0) {
1531 if(glXGetCurrentContext() == object->glCtx) {
1532 glXMakeCurrent(object->display, None, NULL);
1534 glXDestroyContext(object->display, object->glCtx);
1536 HeapFree(GetProcessHeap(), 0, object);
1543 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1544 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1545 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1546 unsigned int numberOfSwapChains = 0;
1547 SwapChainList *swapchain;
1549 swapchain = This->swapchains;
1550 /* itterate through the list to get a count */
1551 while (swapchain != NULL) {
1552 swapchain = swapchain->next;
1553 numberOfSwapChains++;
1556 TRACE("(%p) returning %d\n", This, numberOfSwapChains);
1557 return numberOfSwapChains;
1560 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1561 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1562 SwapChainList *swapchain;
1564 HRESULT hr = D3DERR_INVALIDCALL;
1565 swapchain = This->swapchains;
1566 TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1569 TRACE("(%p) Finding swapchain %d\n", This, iSwapChain);
1570 while (i > 0 && swapchain != NULL) {
1571 swapchain = swapchain->next;
1576 FIXME("(%p) Unable to find swapchain %d\n", This, iSwapChain);
1578 } else if (swapchain != NULL) {
1579 /** TODO: move off to a linkesList implementation **/
1580 *pSwapChain = swapchain->swapchain;
1581 IWineD3DSwapChain_AddRef(*pSwapChain);
1585 TRACE("(%p) returning %p\n", This, *pSwapChain);
1589 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
1590 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1592 FIXME("(%p) : Stub\n",This);
1598 * Vertex Declaration
1600 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1601 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1602 IWineD3DVertexDeclarationImpl *object = NULL;
1603 HRESULT hr = D3D_OK;
1604 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1605 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1608 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1613 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1614 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DVertexShader** ppVertexShader, IUnknown *parent) {
1615 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1616 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1617 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1619 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1620 IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1625 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
1626 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1627 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1628 HRESULT hr = D3D_OK;
1630 D3DCREATEOBJECTINSTANCE(object, PixelShader)
1631 hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
1633 TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
1635 WARN("(%p) : Failed to create pixel shader\n", This);
1641 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
1642 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1643 *ppD3D= This->wineD3D;
1644 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1645 IWineD3D_AddRef(*ppD3D);
1649 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1650 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1651 * Into the video ram as possible and seeing how many fit
1652 * you can also get the correct initial value from via X and ATI's driver
1653 *******************/
1654 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1655 static BOOL showfixmes = TRUE;
1657 FIXME("(%p) : stub, emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1658 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1661 TRACE("(%p) : emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1662 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1663 /* videomemory is simulated videomemory + AGP memory left */
1664 return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1672 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1673 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1674 HRESULT hr = D3D_OK;
1676 /* Update the current state block */
1677 This->updateStateBlock->fvf = fvf;
1678 This->updateStateBlock->changed.fvf = TRUE;
1679 This->updateStateBlock->set.fvf = TRUE;
1681 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1684 /* clear down the vertex declaration
1685 NOTE: Axis and Allies doesn't work properly otherwise
1686 (may be a stateblock problem though!)
1688 hr = IWineD3DDevice_SetVertexDeclaration(iface, NULL);
1695 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1696 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1697 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1698 *pfvf = This->stateBlock->fvf;
1703 * Get / Set Stream Source
1705 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1706 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1707 IWineD3DVertexBuffer *oldSrc;
1709 /**TODO: instance and index data, see
1710 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1712 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
1715 /* D3d9 only, but shouldn't hurt d3d8 */
1718 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1720 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1721 FIXME("stream index data not supported\n");
1723 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1724 FIXME("stream instance data not supported\n");
1728 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1730 if (StreamNumber >= MAX_STREAMS) {
1731 WARN("Stream out of range %d\n", StreamNumber);
1732 return D3DERR_INVALIDCALL;
1735 oldSrc = This->stateBlock->streamSource[StreamNumber];
1736 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1738 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
1739 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
1740 This->updateStateBlock->streamStride[StreamNumber] = Stride;
1741 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
1742 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
1743 This->updateStateBlock->streamFlags[StreamNumber] = streamFlags;
1745 /* Handle recording of state blocks */
1746 if (This->isRecordingState) {
1747 TRACE("Recording... not performing anything\n");
1751 /* Not recording... */
1752 /* Need to do a getParent and pass the reffs up */
1753 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
1754 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
1755 so for now, just count internally */
1756 if (pStreamData != NULL) {
1757 IUnknown *newVertexBufferParent;
1758 /* GetParent will add a ref, so leave it hanging until the vertex buffer is cleared */
1759 IWineD3DVertexBuffer_GetParent(pStreamData, &newVertexBufferParent);
1761 if (oldSrc != NULL) {
1762 IUnknown *oldVertexBufferParent;
1763 IWineD3DVertexBuffer_GetParent(oldSrc, &oldVertexBufferParent);
1764 IUnknown_Release(oldVertexBufferParent);
1765 IUnknown_Release(oldVertexBufferParent);
1771 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
1772 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1775 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
1776 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
1779 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1781 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1782 FIXME("stream index data not supported\n");
1784 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1785 FIXME("stream instance data not supported\n");
1789 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1791 if (StreamNumber >= MAX_STREAMS) {
1792 WARN("Stream out of range %d\n", StreamNumber);
1793 return D3DERR_INVALIDCALL;
1795 *pStream = This->stateBlock->streamSource[StreamNumber];
1796 *pStride = This->stateBlock->streamStride[StreamNumber];
1797 *pOffset = This->stateBlock->streamOffset[StreamNumber];
1799 if (*pStream == NULL) {
1800 FIXME("Attempting to get an empty stream %d, returning D3DERR_INVALIDCALL\n", StreamNumber);
1801 return D3DERR_INVALIDCALL;
1804 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
1808 /*Should be quite easy, just an extension of vertexdata
1810 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1812 The divider is a bit odd though
1814 VertexOffset = StartVertex / Divider * StreamStride +
1815 VertexIndex / Divider * StreamStride + StreamOffset
1818 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
1819 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1821 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
1822 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (D3DSTREAMSOURCE_INSTANCEDATA | D3DSTREAMSOURCE_INDEXEDDATA );
1824 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
1825 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
1826 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
1828 if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
1829 FIXME("Stream indexing not fully supported\n");
1835 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
1836 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1838 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
1839 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
1841 TRACE("(%p) : returning %d\n", This, *Divider);
1847 * Get / Set & Multiply Transform
1849 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1850 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1852 /* Most of this routine, comments included copied from ddraw tree initially: */
1853 TRACE("(%p) : Transform State=%d\n", This, d3dts);
1855 /* Handle recording of state blocks */
1856 if (This->isRecordingState) {
1857 TRACE("Recording... not performing anything\n");
1858 This->updateStateBlock->changed.transform[d3dts] = TRUE;
1859 This->updateStateBlock->set.transform[d3dts] = TRUE;
1860 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1865 * If the new matrix is the same as the current one,
1866 * we cut off any further processing. this seems to be a reasonable
1867 * optimization because as was noticed, some apps (warcraft3 for example)
1868 * tend towards setting the same matrix repeatedly for some reason.
1870 * From here on we assume that the new matrix is different, wherever it matters.
1872 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1873 TRACE("The app is setting the same matrix over again\n");
1876 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1880 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1881 where ViewMat = Camera space, WorldMat = world space.
1883 In OpenGL, camera and world space is combined into GL_MODELVIEW
1884 matrix. The Projection matrix stay projection matrix.
1887 /* Capture the times we can just ignore the change for now */
1888 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1889 This->modelview_valid = FALSE;
1892 } else if (d3dts == D3DTS_PROJECTION) {
1893 This->proj_valid = FALSE;
1896 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1897 /* Indexed Vertex Blending Matrices 256 -> 511 */
1898 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1899 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1903 /* Now we really are going to have to change a matrix */
1906 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1907 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
1908 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1911 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1912 * NOTE: We have to reset the positions even if the light/plane is not currently
1913 * enabled, since the call to enable it will not reset the position.
1914 * NOTE2: Apparently texture transforms do NOT need reapplying
1917 PLIGHTINFOEL *lightChain = NULL;
1918 This->modelview_valid = FALSE;
1919 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
1921 glMatrixMode(GL_MODELVIEW);
1922 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1924 glLoadMatrixf((float *)lpmatrix);
1925 checkGLcall("glLoadMatrixf(...)");
1928 lightChain = This->stateBlock->lights;
1929 while (lightChain && lightChain->glIndex != -1) {
1930 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1931 checkGLcall("glLightfv posn");
1932 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1933 checkGLcall("glLightfv dirn");
1934 lightChain = lightChain->next;
1937 /* Reset Clipping Planes if clipping is enabled */
1938 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1939 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1940 checkGLcall("glClipPlane");
1944 } else { /* What was requested!?? */
1945 WARN("invalid matrix specified: %i\n", d3dts);
1948 /* Release lock, all done */
1953 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1954 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1955 TRACE("(%p) : for Transform State %d\n", This, State);
1956 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1960 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1961 D3DMATRIX *mat = NULL;
1964 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1965 * below means it will be recorded in a state block change, but it
1966 * works regardless where it is recorded.
1967 * If this is found to be wrong, change to StateBlock.
1969 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1970 TRACE("(%p) : For state %u\n", This, State);
1972 if (State < HIGHEST_TRANSFORMSTATE)
1974 mat = &This->updateStateBlock->transforms[State];
1976 FIXME("Unhandled transform state!!\n");
1979 /* Copied from ddraw code: */
1980 temp.u.s._11 = (mat->u.s._11 * pMatrix->u.s._11) + (mat->u.s._21 * pMatrix->u.s._12) +
1981 (mat->u.s._31 * pMatrix->u.s._13) + (mat->u.s._41 * pMatrix->u.s._14);
1982 temp.u.s._21 = (mat->u.s._11 * pMatrix->u.s._21) + (mat->u.s._21 * pMatrix->u.s._22) +
1983 (mat->u.s._31 * pMatrix->u.s._23) + (mat->u.s._41 * pMatrix->u.s._24);
1984 temp.u.s._31 = (mat->u.s._11 * pMatrix->u.s._31) + (mat->u.s._21 * pMatrix->u.s._32) +
1985 (mat->u.s._31 * pMatrix->u.s._33) + (mat->u.s._41 * pMatrix->u.s._34);
1986 temp.u.s._41 = (mat->u.s._11 * pMatrix->u.s._41) + (mat->u.s._21 * pMatrix->u.s._42) +
1987 (mat->u.s._31 * pMatrix->u.s._43) + (mat->u.s._41 * pMatrix->u.s._44);
1989 temp.u.s._12 = (mat->u.s._12 * pMatrix->u.s._11) + (mat->u.s._22 * pMatrix->u.s._12) +
1990 (mat->u.s._32 * pMatrix->u.s._13) + (mat->u.s._42 * pMatrix->u.s._14);
1991 temp.u.s._22 = (mat->u.s._12 * pMatrix->u.s._21) + (mat->u.s._22 * pMatrix->u.s._22) +
1992 (mat->u.s._32 * pMatrix->u.s._23) + (mat->u.s._42 * pMatrix->u.s._24);
1993 temp.u.s._32 = (mat->u.s._12 * pMatrix->u.s._31) + (mat->u.s._22 * pMatrix->u.s._32) +
1994 (mat->u.s._32 * pMatrix->u.s._33) + (mat->u.s._42 * pMatrix->u.s._34);
1995 temp.u.s._42 = (mat->u.s._12 * pMatrix->u.s._41) + (mat->u.s._22 * pMatrix->u.s._42) +
1996 (mat->u.s._32 * pMatrix->u.s._43) + (mat->u.s._42 * pMatrix->u.s._44);
1998 temp.u.s._13 = (mat->u.s._13 * pMatrix->u.s._11) + (mat->u.s._23 * pMatrix->u.s._12) +
1999 (mat->u.s._33 * pMatrix->u.s._13) + (mat->u.s._43 * pMatrix->u.s._14);
2000 temp.u.s._23 = (mat->u.s._13 * pMatrix->u.s._21) + (mat->u.s._23 * pMatrix->u.s._22) +
2001 (mat->u.s._33 * pMatrix->u.s._23) + (mat->u.s._43 * pMatrix->u.s._24);
2002 temp.u.s._33 = (mat->u.s._13 * pMatrix->u.s._31) + (mat->u.s._23 * pMatrix->u.s._32) +
2003 (mat->u.s._33 * pMatrix->u.s._33) + (mat->u.s._43 * pMatrix->u.s._34);
2004 temp.u.s._43 = (mat->u.s._13 * pMatrix->u.s._41) + (mat->u.s._23 * pMatrix->u.s._42) +
2005 (mat->u.s._33 * pMatrix->u.s._43) + (mat->u.s._43 * pMatrix->u.s._44);
2007 temp.u.s._14 = (mat->u.s._14 * pMatrix->u.s._11) + (mat->u.s._24 * pMatrix->u.s._12) +
2008 (mat->u.s._34 * pMatrix->u.s._13) + (mat->u.s._44 * pMatrix->u.s._14);
2009 temp.u.s._24 = (mat->u.s._14 * pMatrix->u.s._21) + (mat->u.s._24 * pMatrix->u.s._22) +
2010 (mat->u.s._34 * pMatrix->u.s._23) + (mat->u.s._44 * pMatrix->u.s._24);
2011 temp.u.s._34 = (mat->u.s._14 * pMatrix->u.s._31) + (mat->u.s._24 * pMatrix->u.s._32) +
2012 (mat->u.s._34 * pMatrix->u.s._33) + (mat->u.s._44 * pMatrix->u.s._34);
2013 temp.u.s._44 = (mat->u.s._14 * pMatrix->u.s._41) + (mat->u.s._24 * pMatrix->u.s._42) +
2014 (mat->u.s._34 * pMatrix->u.s._43) + (mat->u.s._44 * pMatrix->u.s._44);
2016 /* Apply change via set transform - will reapply to eg. lights this way */
2017 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2022 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
2024 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2025 you can reference any indexes you want as long as that number max are enabled at any
2026 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2027 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2028 but when recording, just build a chain pretty much of commands to be replayed. */
2030 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2032 PLIGHTINFOEL *object, *temp;
2034 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2035 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2037 /* If recording state block, just add to end of lights chain */
2038 if (This->isRecordingState) {
2039 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2040 if (NULL == object) {
2041 return D3DERR_OUTOFVIDEOMEMORY;
2043 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2044 object->OriginalIndex = Index;
2045 object->glIndex = -1;
2046 object->changed = TRUE;
2048 /* Add to the END of the chain of lights changes to be replayed */
2049 if (This->updateStateBlock->lights == NULL) {
2050 This->updateStateBlock->lights = object;
2052 temp = This->updateStateBlock->lights;
2053 while (temp->next != NULL) temp=temp->next;
2054 temp->next = object;
2056 TRACE("Recording... not performing anything more\n");
2060 /* Ok, not recording any longer so do real work */
2061 object = This->stateBlock->lights;
2062 while (object != NULL && object->OriginalIndex != Index) object = object->next;
2064 /* If we didn't find it in the list of lights, time to add it */
2065 if (object == NULL) {
2066 PLIGHTINFOEL *insertAt,*prevPos;
2068 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2069 if (NULL == object) {
2070 return D3DERR_OUTOFVIDEOMEMORY;
2072 object->OriginalIndex = Index;
2073 object->glIndex = -1;
2075 /* Add it to the front of list with the idea that lights will be changed as needed
2076 BUT after any lights currently assigned GL indexes */
2077 insertAt = This->stateBlock->lights;
2079 while (insertAt != NULL && insertAt->glIndex != -1) {
2081 insertAt = insertAt->next;
2084 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2085 This->stateBlock->lights = object;
2086 } else if (insertAt == NULL) { /* End of list */
2087 prevPos->next = object;
2088 object->prev = prevPos;
2089 } else { /* Middle of chain */
2090 if (prevPos == NULL) {
2091 This->stateBlock->lights = object;
2093 prevPos->next = object;
2095 object->prev = prevPos;
2096 object->next = insertAt;
2097 insertAt->prev = object;
2101 /* Initialize the object */
2102 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,
2103 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2104 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2105 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2106 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2107 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2108 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2110 /* Save away the information */
2111 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2113 switch (pLight->Type) {
2114 case D3DLIGHT_POINT:
2116 object->lightPosn[0] = pLight->Position.x;
2117 object->lightPosn[1] = pLight->Position.y;
2118 object->lightPosn[2] = pLight->Position.z;
2119 object->lightPosn[3] = 1.0f;
2120 object->cutoff = 180.0f;
2124 case D3DLIGHT_DIRECTIONAL:
2126 object->lightPosn[0] = -pLight->Direction.x;
2127 object->lightPosn[1] = -pLight->Direction.y;
2128 object->lightPosn[2] = -pLight->Direction.z;
2129 object->lightPosn[3] = 0.0;
2130 object->exponent = 0.0f;
2131 object->cutoff = 180.0f;
2136 object->lightPosn[0] = pLight->Position.x;
2137 object->lightPosn[1] = pLight->Position.y;
2138 object->lightPosn[2] = pLight->Position.z;
2139 object->lightPosn[3] = 1.0;
2142 object->lightDirn[0] = pLight->Direction.x;
2143 object->lightDirn[1] = pLight->Direction.y;
2144 object->lightDirn[2] = pLight->Direction.z;
2145 object->lightDirn[3] = 1.0;
2148 * opengl-ish and d3d-ish spot lights use too different models for the
2149 * light "intensity" as a function of the angle towards the main light direction,
2150 * so we only can approximate very roughly.
2151 * however spot lights are rather rarely used in games (if ever used at all).
2152 * furthermore if still used, probably nobody pays attention to such details.
2154 if (pLight->Falloff == 0) {
2157 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2159 if (rho < 0.0001) rho = 0.0001f;
2160 object->exponent = -0.3/log(cos(rho/2));
2161 object->cutoff = pLight->Phi*90/M_PI;
2167 FIXME("Unrecognized light type %d\n", pLight->Type);
2170 /* Update the live definitions if the light is currently assigned a glIndex */
2171 if (object->glIndex != -1) {
2172 setup_light(iface, object->glIndex, object);
2177 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2178 PLIGHTINFOEL *lightInfo = NULL;
2179 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2180 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2182 /* Locate the light in the live lights */
2183 lightInfo = This->stateBlock->lights;
2184 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2186 if (lightInfo == NULL) {
2187 TRACE("Light information requested but light not defined\n");
2188 return D3DERR_INVALIDCALL;
2191 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
2196 * Get / Set Light Enable
2197 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2199 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2200 PLIGHTINFOEL *lightInfo = NULL;
2201 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2202 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2204 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2205 if (This->isRecordingState) {
2206 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2207 if (NULL == lightInfo) {
2208 return D3DERR_OUTOFVIDEOMEMORY;
2210 lightInfo->OriginalIndex = Index;
2211 lightInfo->glIndex = -1;
2212 lightInfo->enabledChanged = TRUE;
2214 /* Add to the END of the chain of lights changes to be replayed */
2215 if (This->updateStateBlock->lights == NULL) {
2216 This->updateStateBlock->lights = lightInfo;
2218 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2219 while (temp->next != NULL) temp=temp->next;
2220 temp->next = lightInfo;
2222 TRACE("Recording... not performing anything more\n");
2226 /* Not recording... So, locate the light in the live lights */
2227 lightInfo = This->stateBlock->lights;
2228 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2230 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2231 if (lightInfo == NULL) {
2232 D3DLIGHT9 lightParms;
2233 /* Warning - untested code :-) Prob safe to change fixme to a trace but
2234 wait until someone confirms it seems to work! */
2235 TRACE("Light enabled requested but light not defined, so defining one!\n");
2236 lightParms.Type = D3DLIGHT_DIRECTIONAL;
2237 lightParms.Diffuse.r = 1.0;
2238 lightParms.Diffuse.g = 1.0;
2239 lightParms.Diffuse.b = 1.0;
2240 lightParms.Diffuse.a = 0.0;
2241 lightParms.Specular.r = 0.0;
2242 lightParms.Specular.g = 0.0;
2243 lightParms.Specular.b = 0.0;
2244 lightParms.Specular.a = 0.0;
2245 lightParms.Ambient.r = 0.0;
2246 lightParms.Ambient.g = 0.0;
2247 lightParms.Ambient.b = 0.0;
2248 lightParms.Ambient.a = 0.0;
2249 lightParms.Position.x = 0.0;
2250 lightParms.Position.y = 0.0;
2251 lightParms.Position.z = 0.0;
2252 lightParms.Direction.x = 0.0;
2253 lightParms.Direction.y = 0.0;
2254 lightParms.Direction.z = 1.0;
2255 lightParms.Range = 0.0;
2256 lightParms.Falloff = 0.0;
2257 lightParms.Attenuation0 = 0.0;
2258 lightParms.Attenuation1 = 0.0;
2259 lightParms.Attenuation2 = 0.0;
2260 lightParms.Theta = 0.0;
2261 lightParms.Phi = 0.0;
2262 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
2264 /* Search for it again! Should be fairly quick as near head of list */
2265 lightInfo = This->stateBlock->lights;
2266 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2267 if (lightInfo == NULL) {
2268 FIXME("Adding default lights has failed dismally\n");
2269 return D3DERR_INVALIDCALL;
2273 /* OK, we now have a light... */
2274 if (Enable == FALSE) {
2276 /* If we are disabling it, check it was enabled, and
2277 still only do something if it has assigned a glIndex (which it should have!) */
2278 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2279 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2281 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2282 checkGLcall("glDisable GL_LIGHT0+Index");
2285 TRACE("Nothing to do as light was not enabled\n");
2287 lightInfo->lightEnabled = FALSE;
2290 /* We are enabling it. If it is enabled, it's really simple */
2291 if (lightInfo->lightEnabled) {
2293 TRACE("Nothing to do as light was enabled\n");
2295 /* If it already has a glIndex, it's still simple */
2296 } else if (lightInfo->glIndex != -1) {
2297 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2298 lightInfo->lightEnabled = TRUE;
2300 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2301 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2304 /* Otherwise got to find space - lights are ordered gl indexes first */
2306 PLIGHTINFOEL *bsf = NULL;
2307 PLIGHTINFOEL *pos = This->stateBlock->lights;
2308 PLIGHTINFOEL *prev = NULL;
2312 /* Try to minimize changes as much as possible */
2313 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2315 /* Try to remember which index can be replaced if necessary */
2316 if (bsf==NULL && pos->lightEnabled == FALSE) {
2317 /* Found a light we can replace, save as best replacement */
2321 /* Step to next space */
2327 /* If we have too many active lights, fail the call */
2328 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2329 FIXME("Program requests too many concurrent lights\n");
2330 return D3DERR_INVALIDCALL;
2332 /* If we have allocated all lights, but not all are enabled,
2333 reuse one which is not enabled */
2334 } else if (Index == This->maxConcurrentLights) {
2335 /* use bsf - Simply swap the new light and the BSF one */
2336 PLIGHTINFOEL *bsfNext = bsf->next;
2337 PLIGHTINFOEL *bsfPrev = bsf->prev;
2340 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2341 if (bsf->prev != NULL) {
2342 bsf->prev->next = lightInfo;
2344 This->stateBlock->lights = lightInfo;
2347 /* If not side by side, lots of chains to update */
2348 if (bsf->next != lightInfo) {
2349 lightInfo->prev->next = bsf;
2350 bsf->next->prev = lightInfo;
2351 bsf->next = lightInfo->next;
2352 bsf->prev = lightInfo->prev;
2353 lightInfo->next = bsfNext;
2354 lightInfo->prev = bsfPrev;
2358 bsf->prev = lightInfo;
2359 bsf->next = lightInfo->next;
2360 lightInfo->next = bsf;
2361 lightInfo->prev = bsfPrev;
2366 glIndex = bsf->glIndex;
2368 lightInfo->glIndex = glIndex;
2369 lightInfo->lightEnabled = TRUE;
2371 /* Finally set up the light in gl itself */
2372 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2374 setup_light(iface, glIndex, lightInfo);
2375 glEnable(GL_LIGHT0 + glIndex);
2376 checkGLcall("glEnable GL_LIGHT0 new setup");
2379 /* If we reached the end of the allocated lights, with space in the
2380 gl lights, setup a new light */
2381 } else if (pos->glIndex == -1) {
2383 /* We reached the end of the allocated gl lights, so already
2384 know the index of the next one! */
2386 lightInfo->glIndex = glIndex;
2387 lightInfo->lightEnabled = TRUE;
2389 /* In an ideal world, it's already in the right place */
2390 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2391 /* No need to move it */
2393 /* Remove this light from the list */
2394 lightInfo->prev->next = lightInfo->next;
2395 if (lightInfo->next != NULL) {
2396 lightInfo->next->prev = lightInfo->prev;
2399 /* Add in at appropriate place (inbetween prev and pos) */
2400 lightInfo->prev = prev;
2401 lightInfo->next = pos;
2403 This->stateBlock->lights = lightInfo;
2405 prev->next = lightInfo;
2408 pos->prev = lightInfo;
2412 /* Finally set up the light in gl itself */
2413 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2415 setup_light(iface, glIndex, lightInfo);
2416 glEnable(GL_LIGHT0 + glIndex);
2417 checkGLcall("glEnable GL_LIGHT0 new setup");
2426 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2428 PLIGHTINFOEL *lightInfo = NULL;
2429 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2430 TRACE("(%p) : for idx(%ld)\n", This, Index);
2432 /* Locate the light in the live lights */
2433 lightInfo = This->stateBlock->lights;
2434 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2436 if (lightInfo == NULL) {
2437 TRACE("Light enabled state requested but light not defined\n");
2438 return D3DERR_INVALIDCALL;
2440 *pEnable = lightInfo->lightEnabled;
2445 * Get / Set Clip Planes
2447 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2448 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2449 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2451 /* Validate Index */
2452 if (Index >= GL_LIMITS(clipplanes)) {
2453 TRACE("Application has requested clipplane this device doesn't support\n");
2454 return D3DERR_INVALIDCALL;
2457 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2458 This->updateStateBlock->set.clipplane[Index] = TRUE;
2459 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2460 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2461 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2462 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2464 /* Handle recording of state blocks */
2465 if (This->isRecordingState) {
2466 TRACE("Recording... not performing anything\n");
2474 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2475 glMatrixMode(GL_MODELVIEW);
2477 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2479 TRACE("Clipplane [%f,%f,%f,%f]\n",
2480 This->updateStateBlock->clipplane[Index][0],
2481 This->updateStateBlock->clipplane[Index][1],
2482 This->updateStateBlock->clipplane[Index][2],
2483 This->updateStateBlock->clipplane[Index][3]);
2484 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2485 checkGLcall("glClipPlane");
2493 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2494 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2495 TRACE("(%p) : for idx %ld\n", This, Index);
2497 /* Validate Index */
2498 if (Index >= GL_LIMITS(clipplanes)) {
2499 TRACE("Application has requested clipplane this device doesn't support\n");
2500 return D3DERR_INVALIDCALL;
2503 pPlane[0] = This->stateBlock->clipplane[Index][0];
2504 pPlane[1] = This->stateBlock->clipplane[Index][1];
2505 pPlane[2] = This->stateBlock->clipplane[Index][2];
2506 pPlane[3] = This->stateBlock->clipplane[Index][3];
2511 * Get / Set Clip Plane Status
2512 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2514 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2515 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2516 FIXME("(%p) : stub\n", This);
2517 if (NULL == pClipStatus) {
2518 return D3DERR_INVALIDCALL;
2520 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2521 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2525 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2526 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2527 FIXME("(%p) : stub\n", This);
2528 if (NULL == pClipStatus) {
2529 return D3DERR_INVALIDCALL;
2531 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2532 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2537 * Get / Set Material
2538 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2540 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2541 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2543 This->updateStateBlock->changed.material = TRUE;
2544 This->updateStateBlock->set.material = TRUE;
2545 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2547 /* Handle recording of state blocks */
2548 if (This->isRecordingState) {
2549 TRACE("Recording... not performing anything\n");
2554 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2555 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2556 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2557 pMaterial->Ambient.b, pMaterial->Ambient.a);
2558 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2559 pMaterial->Specular.b, pMaterial->Specular.a);
2560 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2561 pMaterial->Emissive.b, pMaterial->Emissive.a);
2562 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2564 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2565 checkGLcall("glMaterialfv(GL_AMBIENT)");
2566 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2567 checkGLcall("glMaterialfv(GL_DIFFUSE)");
2569 /* Only change material color if specular is enabled, otherwise it is set to black */
2570 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2571 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2572 checkGLcall("glMaterialfv(GL_SPECULAR");
2574 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2575 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2576 checkGLcall("glMaterialfv(GL_SPECULAR");
2578 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2579 checkGLcall("glMaterialfv(GL_EMISSION)");
2580 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2581 checkGLcall("glMaterialf(GL_SHININESS");
2587 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2588 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2589 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2590 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2591 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2592 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2593 pMaterial->Ambient.b, pMaterial->Ambient.a);
2594 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2595 pMaterial->Specular.b, pMaterial->Specular.a);
2596 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2597 pMaterial->Emissive.b, pMaterial->Emissive.a);
2598 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2606 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2607 UINT BaseVertexIndex) {
2608 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2609 IWineD3DIndexBuffer *oldIdxs;
2611 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2612 oldIdxs = This->updateStateBlock->pIndexData;
2614 This->updateStateBlock->changed.indices = TRUE;
2615 This->updateStateBlock->set.indices = TRUE;
2616 This->updateStateBlock->pIndexData = pIndexData;
2617 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2619 /* Handle recording of state blocks */
2620 if (This->isRecordingState) {
2621 TRACE("Recording... not performing anything\n");
2626 IUnknown *indexBufferParent;
2627 /* Getting the parent causes a addRef... it gets released when the indicies are clear */
2628 IWineD3DIndexBuffer_GetParent(pIndexData, &indexBufferParent);
2631 IUnknown *indexBufferParent;
2632 IWineD3DIndexBuffer_GetParent(oldIdxs, &indexBufferParent);
2633 IUnknown_Release(indexBufferParent);
2634 IUnknown_Release(indexBufferParent);
2639 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2640 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2642 *ppIndexData = This->stateBlock->pIndexData;
2644 /* up ref count on ppindexdata */
2646 IWineD3DIndexBuffer_AddRef(*ppIndexData);
2647 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2648 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
2650 TRACE("(%p) No index data set\n", This);
2652 TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
2658 * Get / Set Viewports
2660 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2661 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2663 TRACE("(%p)\n", This);
2664 This->updateStateBlock->changed.viewport = TRUE;
2665 This->updateStateBlock->set.viewport = TRUE;
2666 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2668 /* Handle recording of state blocks */
2669 if (This->isRecordingState) {
2670 TRACE("Recording... not performing anything\n");
2676 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2677 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2679 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2680 checkGLcall("glDepthRange");
2681 /* Note: GL requires lower left, DirectX supplies upper left */
2682 /* TODO: replace usage of renderTarget with context management */
2683 glViewport(pViewport->X,
2684 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2685 pViewport->Width, pViewport->Height);
2687 checkGLcall("glViewport");
2695 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2696 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2697 TRACE("(%p)\n", This);
2698 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2703 * Get / Set Render States
2704 * TODO: Verify against dx9 definitions
2706 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2708 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2709 DWORD OldValue = This->stateBlock->renderState[State];
2711 /* Simple way of referring to either a DWORD or a 4 byte float */
2717 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2718 This->updateStateBlock->changed.renderState[State] = TRUE;
2719 This->updateStateBlock->set.renderState[State] = TRUE;
2720 This->updateStateBlock->renderState[State] = Value;
2722 /* Handle recording of state blocks */
2723 if (This->isRecordingState) {
2724 TRACE("Recording... not performing anything\n");
2731 case WINED3DRS_FILLMODE :
2732 switch ((D3DFILLMODE) Value) {
2733 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2734 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2735 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2737 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
2739 checkGLcall("glPolygonMode (fillmode)");
2742 case WINED3DRS_LIGHTING :
2744 glEnable(GL_LIGHTING);
2745 checkGLcall("glEnable GL_LIGHTING");
2747 glDisable(GL_LIGHTING);
2748 checkGLcall("glDisable GL_LIGHTING");
2752 case WINED3DRS_ZENABLE :
2753 switch ((D3DZBUFFERTYPE) Value) {
2755 glDisable(GL_DEPTH_TEST);
2756 checkGLcall("glDisable GL_DEPTH_TEST");
2759 glEnable(GL_DEPTH_TEST);
2760 checkGLcall("glEnable GL_DEPTH_TEST");
2763 glEnable(GL_DEPTH_TEST);
2764 checkGLcall("glEnable GL_DEPTH_TEST");
2765 FIXME("W buffer is not well handled\n");
2768 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2772 case WINED3DRS_CULLMODE :
2774 /* If we are culling "back faces with clockwise vertices" then
2775 set front faces to be counter clockwise and enable culling
2777 switch ((D3DCULL) Value) {
2779 glDisable(GL_CULL_FACE);
2780 checkGLcall("glDisable GL_CULL_FACE");
2783 glEnable(GL_CULL_FACE);
2784 checkGLcall("glEnable GL_CULL_FACE");
2785 if (This->renderUpsideDown) {
2787 checkGLcall("glFrontFace GL_CW");
2789 glFrontFace(GL_CCW);
2790 checkGLcall("glFrontFace GL_CCW");
2792 glCullFace(GL_BACK);
2795 glEnable(GL_CULL_FACE);
2796 checkGLcall("glEnable GL_CULL_FACE");
2797 if (This->renderUpsideDown) {
2798 glFrontFace(GL_CCW);
2799 checkGLcall("glFrontFace GL_CCW");
2802 checkGLcall("glFrontFace GL_CW");
2804 glCullFace(GL_BACK);
2807 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2811 case WINED3DRS_SHADEMODE :
2812 switch ((D3DSHADEMODE) Value) {
2814 glShadeModel(GL_FLAT);
2815 checkGLcall("glShadeModel");
2817 case D3DSHADE_GOURAUD:
2818 glShadeModel(GL_SMOOTH);
2819 checkGLcall("glShadeModel");
2821 case D3DSHADE_PHONG:
2822 FIXME("D3DSHADE_PHONG isn't supported?\n");
2825 return D3DERR_INVALIDCALL;
2827 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2831 case WINED3DRS_DITHERENABLE :
2833 glEnable(GL_DITHER);
2834 checkGLcall("glEnable GL_DITHER");
2836 glDisable(GL_DITHER);
2837 checkGLcall("glDisable GL_DITHER");
2841 case WINED3DRS_ZWRITEENABLE :
2844 checkGLcall("glDepthMask");
2847 checkGLcall("glDepthMask");
2851 case WINED3DRS_ZFUNC :
2853 int glParm = GL_LESS;
2855 switch ((D3DCMPFUNC) Value) {
2856 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2857 case D3DCMP_LESS: glParm=GL_LESS; break;
2858 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2859 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2860 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2861 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2862 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2863 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2865 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2867 glDepthFunc(glParm);
2868 checkGLcall("glDepthFunc");
2872 case WINED3DRS_AMBIENT :
2875 D3DCOLORTOGLFLOAT4(Value, col);
2876 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2877 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2878 checkGLcall("glLightModel for MODEL_AMBIENT");
2883 case WINED3DRS_ALPHABLENDENABLE :
2886 checkGLcall("glEnable GL_BLEND");
2888 glDisable(GL_BLEND);
2889 checkGLcall("glDisable GL_BLEND");
2893 case WINED3DRS_SRCBLEND :
2894 case WINED3DRS_DESTBLEND :
2896 int newVal = GL_ZERO;
2898 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2899 case D3DBLEND_ONE : newVal = GL_ONE; break;
2900 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2901 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2902 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2903 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2904 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2905 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2906 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2907 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2908 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2910 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2911 This->srcBlend = newVal;
2912 This->dstBlend = newVal;
2915 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2916 This->srcBlend = newVal;
2917 This->dstBlend = newVal;
2920 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2923 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2924 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2925 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2926 glBlendFunc(This->srcBlend, This->dstBlend);
2928 checkGLcall("glBlendFunc");
2932 case WINED3DRS_ALPHATESTENABLE :
2934 glEnable(GL_ALPHA_TEST);
2935 checkGLcall("glEnable GL_ALPHA_TEST");
2937 glDisable(GL_ALPHA_TEST);
2938 checkGLcall("glDisable GL_ALPHA_TEST");
2942 case WINED3DRS_ALPHAFUNC :
2944 int glParm = GL_LESS;
2945 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2947 switch ((D3DCMPFUNC) Value) {
2948 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2949 case D3DCMP_LESS: glParm = GL_LESS; break;
2950 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2951 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2952 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2953 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2954 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2955 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2957 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2959 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2960 glAlphaFunc(glParm, ref);
2961 This->alphafunc = glParm;
2962 checkGLcall("glAlphaFunc");
2966 case WINED3DRS_ALPHAREF :
2968 int glParm = This->alphafunc;
2971 ref = ((float) Value) / 255.0f;
2972 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2973 glAlphaFunc(glParm, ref);
2974 checkGLcall("glAlphaFunc");
2978 case WINED3DRS_CLIPPLANEENABLE :
2979 case WINED3DRS_CLIPPING :
2981 /* Ensure we only do the changed clip planes */
2982 DWORD enable = 0xFFFFFFFF;
2983 DWORD disable = 0x00000000;
2985 /* If enabling / disabling all */
2986 if (State == WINED3DRS_CLIPPING) {
2988 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2991 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2995 enable = Value & ~OldValue;
2996 disable = ~Value & OldValue;
2999 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
3000 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
3001 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
3002 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
3003 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
3004 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
3006 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
3007 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
3008 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
3009 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
3010 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
3011 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
3013 /** update clipping status */
3015 This->stateBlock->clip_status.ClipUnion = 0;
3016 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
3018 This->stateBlock->clip_status.ClipUnion = 0;
3019 This->stateBlock->clip_status.ClipIntersection = 0;
3024 case WINED3DRS_BLENDOP :
3026 int glParm = GL_FUNC_ADD;
3028 switch ((D3DBLENDOP) Value) {
3029 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
3030 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
3031 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3032 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
3033 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
3035 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
3037 TRACE("glBlendEquation(%x)\n", glParm);
3038 glBlendEquation(glParm);
3039 checkGLcall("glBlendEquation");
3043 case WINED3DRS_TEXTUREFACTOR :
3047 /* Note the texture color applies to all textures whereas
3048 GL_TEXTURE_ENV_COLOR applies to active only */
3050 D3DCOLORTOGLFLOAT4(Value, col);
3051 /* Set the default alpha blend color */
3052 glBlendColor(col[0], col[1], col[2], col[3]);
3053 checkGLcall("glBlendColor");
3055 /* And now the default texture color as well */
3056 for (i = 0; i < GL_LIMITS(textures); i++) {
3058 /* Note the D3DRS value applies to all textures, but GL has one
3059 per texture, so apply it now ready to be used! */
3060 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3063 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3066 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3067 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3072 case WINED3DRS_SPECULARENABLE :
3074 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3075 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3076 specular color. This is wrong:
3077 Separate specular color means the specular colour is maintained separately, whereas
3078 single color means it is merged in. However in both cases they are being used to
3080 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3081 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3085 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3086 checkGLcall("glMaterialfv");
3087 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3088 glEnable(GL_COLOR_SUM_EXT);
3090 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3092 checkGLcall("glEnable(GL_COLOR_SUM)");
3094 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3096 /* for the case of enabled lighting: */
3097 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3098 checkGLcall("glMaterialfv");
3100 /* for the case of disabled lighting: */
3101 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3102 glDisable(GL_COLOR_SUM_EXT);
3104 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3106 checkGLcall("glDisable(GL_COLOR_SUM)");
3111 case WINED3DRS_STENCILENABLE :
3113 glEnable(GL_STENCIL_TEST);
3114 checkGLcall("glEnable GL_STENCIL_TEST");
3116 glDisable(GL_STENCIL_TEST);
3117 checkGLcall("glDisable GL_STENCIL_TEST");
3121 case WINED3DRS_STENCILFUNC :
3123 int glParm = GL_ALWAYS;
3124 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3125 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3127 switch ((D3DCMPFUNC) Value) {
3128 case D3DCMP_NEVER: glParm=GL_NEVER; break;
3129 case D3DCMP_LESS: glParm=GL_LESS; break;
3130 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
3131 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
3132 case D3DCMP_GREATER: glParm=GL_GREATER; break;
3133 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
3134 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
3135 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
3137 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3139 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3140 This->stencilfunc = glParm;
3141 glStencilFunc(glParm, ref, mask);
3142 checkGLcall("glStencilFunc");
3146 case WINED3DRS_STENCILREF :
3148 int glParm = This->stencilfunc;
3150 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3153 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3154 glStencilFunc(glParm, ref, mask);
3155 checkGLcall("glStencilFunc");
3159 case WINED3DRS_STENCILMASK :
3161 int glParm = This->stencilfunc;
3162 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3163 GLuint mask = Value;
3165 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3166 glStencilFunc(glParm, ref, mask);
3167 checkGLcall("glStencilFunc");
3171 case WINED3DRS_STENCILFAIL :
3177 fail = StencilOp(Value);
3178 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
3179 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
3180 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
3181 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
3183 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3184 glStencilOp(fail, zfail, zpass);
3185 checkGLcall("glStencilOp(fail, zfail, zpass);");
3188 case WINED3DRS_STENCILZFAIL :
3194 glGetIntegerv(GL_STENCIL_FAIL, &fail);
3195 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
3196 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
3197 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
3198 zfail = StencilOp(Value);
3200 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3201 glStencilOp(fail, zfail, zpass);
3202 checkGLcall("glStencilOp(fail, zfail, zpass);");
3205 case WINED3DRS_STENCILPASS :
3211 glGetIntegerv(GL_STENCIL_FAIL, &fail);
3212 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
3213 zpass = StencilOp(Value);
3214 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
3215 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
3217 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3218 glStencilOp(fail, zfail, zpass);
3219 checkGLcall("glStencilOp(fail, zfail, zpass);");
3223 case WINED3DRS_STENCILWRITEMASK :
3225 glStencilMask(Value);
3226 TRACE("glStencilMask(%lu)\n", Value);
3227 checkGLcall("glStencilMask");
3231 case WINED3DRS_FOGENABLE :
3233 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
3235 checkGLcall("glEnable GL_FOG");
3238 checkGLcall("glDisable GL_FOG");
3243 case WINED3DRS_RANGEFOGENABLE :
3246 TRACE("Enabled RANGEFOG");
3248 TRACE("Disabled RANGEFOG");
3253 case WINED3DRS_FOGCOLOR :
3256 D3DCOLORTOGLFLOAT4(Value, col);
3257 /* Set the default alpha blend color */
3258 glFogfv(GL_FOG_COLOR, &col[0]);
3259 checkGLcall("glFog GL_FOG_COLOR");
3263 case WINED3DRS_FOGTABLEMODE :
3265 glHint(GL_FOG_HINT, GL_NICEST);
3267 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3268 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3269 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3270 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3272 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3274 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3275 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3280 case WINED3DRS_FOGVERTEXMODE :
3282 glHint(GL_FOG_HINT, GL_FASTEST);
3284 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3285 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3286 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3287 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3289 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3291 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3292 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
3297 case WINED3DRS_FOGSTART :
3300 glFogfv(GL_FOG_START, &tmpvalue.f);
3301 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3302 TRACE("Fog Start == %f\n", tmpvalue.f);
3306 case WINED3DRS_FOGEND :
3309 glFogfv(GL_FOG_END, &tmpvalue.f);
3310 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3311 TRACE("Fog End == %f\n", tmpvalue.f);
3315 case WINED3DRS_FOGDENSITY :
3318 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3319 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3323 case WINED3DRS_VERTEXBLEND :
3325 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3326 TRACE("Vertex Blending state to %ld\n", Value);
3330 case WINED3DRS_TWEENFACTOR :
3333 This->updateStateBlock->tween_factor = tmpvalue.f;
3334 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3338 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
3340 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3344 case WINED3DRS_COLORVERTEX :
3345 case WINED3DRS_DIFFUSEMATERIALSOURCE :
3346 case WINED3DRS_SPECULARMATERIALSOURCE :
3347 case WINED3DRS_AMBIENTMATERIALSOURCE :
3348 case WINED3DRS_EMISSIVEMATERIALSOURCE :
3350 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3352 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3353 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3354 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3355 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3356 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3357 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3359 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3360 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3361 Parm = GL_AMBIENT_AND_DIFFUSE;
3365 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3367 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3369 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3376 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3378 This->tracking_color = NEEDS_TRACKING;
3379 This->tracking_parm = Parm;
3383 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3388 case WINED3DRS_LINEPATTERN :
3394 tmppattern.d = Value;
3396 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3398 if (tmppattern.lp.wRepeatFactor) {
3399 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3400 checkGLcall("glLineStipple(repeat, linepattern)");
3401 glEnable(GL_LINE_STIPPLE);
3402 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3404 glDisable(GL_LINE_STIPPLE);
3405 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3410 case WINED3DRS_ZBIAS : /* D3D8 only */
3414 TRACE("ZBias value %f\n", tmpvalue.f);
3415 glPolygonOffset(0, -tmpvalue.f);
3416 checkGLcall("glPolygonOffset(0, -Value)");
3417 glEnable(GL_POLYGON_OFFSET_FILL);
3418 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3419 glEnable(GL_POLYGON_OFFSET_LINE);
3420 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3421 glEnable(GL_POLYGON_OFFSET_POINT);
3422 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3424 glDisable(GL_POLYGON_OFFSET_FILL);
3425 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3426 glDisable(GL_POLYGON_OFFSET_LINE);
3427 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3428 glDisable(GL_POLYGON_OFFSET_POINT);
3429 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3434 case WINED3DRS_NORMALIZENORMALS :
3436 glEnable(GL_NORMALIZE);
3437 checkGLcall("glEnable(GL_NORMALIZE);");
3439 glDisable(GL_NORMALIZE);
3440 checkGLcall("glDisable(GL_NORMALIZE);");
3444 case WINED3DRS_POINTSIZE :
3445 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
3447 TRACE("Set point size to %f\n", tmpvalue.f);
3448 glPointSize(tmpvalue.f);
3449 checkGLcall("glPointSize(...);");
3452 case WINED3DRS_POINTSIZE_MIN :
3453 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3455 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3456 checkGLcall("glPointParameterfEXT(...);");
3458 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3462 case WINED3DRS_POINTSIZE_MAX :
3463 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3465 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3466 checkGLcall("glPointParameterfEXT(...);");
3468 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3472 case WINED3DRS_POINTSCALE_A :
3473 case WINED3DRS_POINTSCALE_B :
3474 case WINED3DRS_POINTSCALE_C :
3475 case WINED3DRS_POINTSCALEENABLE :
3477 /* If enabled, supply the parameters, otherwise fall back to defaults */
3478 if (This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3479 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3480 /* TODO: Correct the scaling (this hack seems to be good enough for every demo that uses point sprites!) */
3481 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A])/ This->stateBlock->viewport.Width;
3482 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B])/ This->stateBlock->viewport.Height;
3483 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) *
3484 2.0f /(This->stateBlock->viewport.Width * This->stateBlock->viewport.Height);
3486 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3487 TRACE("glPointParameterfvARB %f %f %f\n", att[0], att[1], att[2]);
3488 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3489 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3491 TRACE("WINED3DRS_POINTSCALEENABLE not supported on this opengl\n");
3494 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3495 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3496 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3497 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3499 TRACE("WINED3DRS_POINTSCALEENABLE not supported, but not on either\n");
3505 case WINED3DRS_COLORWRITEENABLE :
3507 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3508 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3509 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3510 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3511 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3512 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3513 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3514 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3515 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3516 checkGLcall("glColorMask(...)");
3520 case WINED3DRS_LOCALVIEWER :
3522 GLint state = (Value) ? 1 : 0;
3523 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3524 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3528 case WINED3DRS_LASTPIXEL :
3531 TRACE("Last Pixel Drawing Enabled\n");
3533 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3538 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3541 TRACE("Software Processing Enabled\n");
3543 TRACE("Software Processing Disabled\n");
3548 /** not supported */
3549 case WINED3DRS_ZVISIBLE :
3552 return D3DERR_INVALIDCALL;
3554 case WINED3DRS_POINTSPRITEENABLE :
3555 /* TODO: NV_POINT_SPRITE */
3556 if (GL_SUPPORT(ARB_POINT_SPRITE)) {
3557 if (Value != FALSE) {
3558 /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
3559 glDisable(GL_POINT_SMOOTH);
3560 /* Centre the texture on the vertex */
3561 VTRACE("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
3562 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
3564 VTRACE("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
3565 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
3566 checkGLcall("glTexEnvf(...)");
3567 VTRACE("glEnable( GL_POINT_SPRITE_ARB )\n");
3568 glEnable( GL_POINT_SPRITE_ARB );
3569 checkGLcall("glEnable(...)");
3571 VTRACE("glDisable( GL_POINT_SPRITE_ARB )\n");
3572 glDisable( GL_POINT_SPRITE_ARB );
3573 checkGLcall("glEnable(...)");
3577 /* Unhandled yet...! */
3578 case WINED3DRS_EDGEANTIALIAS :
3579 case WINED3DRS_WRAP0 :
3580 case WINED3DRS_WRAP1 :
3581 case WINED3DRS_WRAP2 :
3582 case WINED3DRS_WRAP3 :
3583 case WINED3DRS_WRAP4 :
3584 case WINED3DRS_WRAP5 :
3585 case WINED3DRS_WRAP6 :
3586 case WINED3DRS_WRAP7 :
3588 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
3589 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
3590 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
3591 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
3592 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
3594 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
3596 TRACE("(%p)->(%d,%ld) Texture wraping not yet supported\n",This, State, Value);
3598 case WINED3DRS_MULTISAMPLEANTIALIAS :
3599 case WINED3DRS_MULTISAMPLEMASK :
3600 case WINED3DRS_PATCHEDGESTYLE :
3601 case WINED3DRS_PATCHSEGMENTS :
3602 case WINED3DRS_DEBUGMONITORTOKEN :
3603 case WINED3DRS_POSITIONORDER :
3604 case WINED3DRS_NORMALORDER :
3605 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3606 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3609 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3617 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3618 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3619 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3620 *pValue = This->stateBlock->renderState[State];
3625 * Get / Set Sampler States
3626 * TODO: Verify against dx9 definitions
3629 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3630 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3632 * SetSampler is designed to allow for more than the standard up to 8 textures
3633 * and Geforce has stopped supporting more than 6 standard textures in openGL.
3634 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3636 * http://developer.nvidia.com/object/General_FAQ.html#t6
3638 * There are two new settings for GForce
3640 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3641 * and the texture one:
3642 * GL_MAX_TEXTURE_COORDS_ARB.
3643 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3645 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
3646 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
3648 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
3649 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE, Sampler, Type);
3650 return D3DERR_INVALIDCALL;
3652 TRACE("Setting sampler %ld %d to %ld\n", Sampler, Type, Value);
3653 This->updateStateBlock->samplerState[Sampler][Type] = Value;
3654 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
3655 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
3657 /* Handle recording of state blocks */
3658 if (This->isRecordingState) {
3659 TRACE("Recording... not performing anything\n");
3666 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3667 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3668 /** TODO: check that sampler is in range **/
3669 *Value = This->updateStateBlock->samplerState[Sampler][Type];
3670 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
3675 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3676 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3679 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3680 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3681 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3687 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3688 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3689 GLint scissorBox[4];
3692 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3693 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
3694 pRect->left = scissorBox[1];
3695 pRect->top = scissorBox[2];
3696 pRect->right = scissorBox[1] + scissorBox[3];
3697 pRect->bottom = scissorBox[2] + scissorBox[4];
3698 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3703 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3704 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3706 TRACE("(%p) : pDecl=%p\n", This, pDecl);
3708 /* TODO: what about recording stateblocks? */
3709 if (NULL != pDecl) {
3710 IWineD3DVertexDeclaration_AddRef(pDecl);
3712 if (NULL != This->updateStateBlock->vertexDecl) {
3713 IWineD3DVertexDeclaration_Release(This->updateStateBlock->vertexDecl);
3715 This->updateStateBlock->vertexDecl = pDecl;
3716 This->updateStateBlock->changed.vertexDecl = TRUE;
3717 This->updateStateBlock->set.vertexDecl = TRUE;
3721 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3722 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3724 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3726 *ppDecl = This->updateStateBlock->vertexDecl;
3727 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3731 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
3732 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3733 IWineD3DVertexShader *oldShader = This->updateStateBlock->vertexShader;
3735 This->updateStateBlock->vertexShader = pShader;
3736 This->updateStateBlock->changed.vertexShader = TRUE;
3737 This->updateStateBlock->set.vertexShader = TRUE;
3739 if (This->isRecordingState) {
3740 TRACE("Recording... not performing anything\n");
3744 if (pShader != NULL) {
3745 IUnknown *newVertexShaderParent;
3746 /* GetParent will add a ref, so leave it hanging until the vertex buffer is cleared */
3747 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3748 IWineD3DVertexShader_GetParent(pShader, &newVertexShaderParent);
3750 TRACE("Clear down the shader\n");
3752 if (oldShader != NULL) {
3753 IUnknown *oldVertexShaderParent;
3754 IWineD3DVertexShader_GetParent(oldShader, &oldVertexShaderParent);
3755 IUnknown_Release(oldVertexShaderParent);
3756 IUnknown_Release(oldVertexShaderParent);
3759 * TODO: merge HAL shaders context switching from prototype
3764 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
3765 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3767 if (NULL == ppShader) {
3768 return D3DERR_INVALIDCALL;
3770 *ppShader = This->stateBlock->vertexShader;
3771 if( NULL != *ppShader)
3772 IWineD3DVertexShader_AddRef(*ppShader);
3774 TRACE("(%p) : returning %p\n", This, *ppShader);
3778 #define GET_SHADER_CONSTANT(_vertexshaderconstant, _count, _sizecount) \
3779 count = min(_count, MAX_VSHADER_CONSTANTS - (StartRegister + 1)); \
3780 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3781 return D3DERR_INVALIDCALL; \
3782 memcpy(pConstantData, This->updateStateBlock->_vertexshaderconstant + (StartRegister * _sizecount), count * (sizeof(*pConstantData) * _sizecount));
3784 #define SET_SHADER_CONSTANT(_vertexshaderconstant, _count, _sizecount) \
3785 int count = min(_count, MAX_VSHADER_CONSTANTS - (StartRegister + 1)); \
3786 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3787 return D3DERR_INVALIDCALL; \
3788 memcpy(This->updateStateBlock->_vertexshaderconstant + (StartRegister * _sizecount), pConstantData, count * (sizeof(*pConstantData) * _sizecount)); \
3789 This->updateStateBlock->changed.vertexShader = TRUE; \
3790 This->updateStateBlock->set.vertexShader = TRUE;
3792 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
3793 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3795 SET_SHADER_CONSTANT(vertexShaderConstantB, BoolCount, 1);
3797 /* populate the bitmap that says which constant type we should load */
3798 for (i = StartRegister; i < BoolCount + StartRegister; ++i) {
3799 This->updateStateBlock->changed.vertexShaderConstants[i] = TRUE;
3800 This->updateStateBlock->set.vertexShaderConstants[i] = TRUE;
3801 This->updateStateBlock->vertexShaderConstantT[i] = WINESHADERCNST_BOOL;
3802 TRACE("(%p) : Setting vsb %d to %d\n", This->updateStateBlock, i, pConstantData[i - StartRegister]);
3808 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
3809 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3812 /* verify that the requested shader constant was populated with a boolean */
3813 for (i = StartRegister; i < BoolCount; ++i) {
3814 if (This->updateStateBlock->vertexShaderConstantT[i] != WINESHADERCNST_BOOL) {
3816 /* the constant for this register isn't a boolean */
3817 WARN("(%p) : Caller requested a boolean where stateblock (%p) entry is a %s. Returning D3DERR_INVALIDCALL\n", This,This->updateStateBlock,
3818 This->updateStateBlock->vertexShaderConstantT[i] == WINESHADERCNST_INTEGER ? "integer" : "float");
3819 return D3DERR_INVALIDCALL;
3823 GET_SHADER_CONSTANT(vertexShaderConstantB, BoolCount, 1);
3827 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
3828 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3831 SET_SHADER_CONSTANT(vertexShaderConstantI, Vector4iCount, 4);
3833 /* populate the bitmap that says which constant type we should load */
3834 for (i = StartRegister; i < StartRegister + Vector4iCount; ++i) {
3835 This->updateStateBlock->changed.vertexShaderConstants[i] = TRUE;
3836 This->updateStateBlock->set.vertexShaderConstants[i] = TRUE;
3837 This->updateStateBlock->vertexShaderConstantT[i] = WINESHADERCNST_INTEGER;
3838 TRACE("(%p) : Setting vsi %d to %d\n", This->updateStateBlock, i, pConstantData[i - StartRegister]);
3844 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
3845 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3848 /* verify that the requested shader constant was populated with a integer */
3849 for (i = StartRegister; i < Vector4iCount; ++i) {
3850 if (This->updateStateBlock->vertexShaderConstantT[i] != WINESHADERCNST_INTEGER) {
3852 /* the constant for this register isn't a integer */
3853 WARN("(%p) : Caller requested a integer where stateblock (%p) entry is a %s. Returning D3DERR_INVALIDCALL\n", This, This->updateStateBlock,
3854 This->updateStateBlock->vertexShaderConstantT[i] == WINESHADERCNST_BOOL ? "boolean" : "float");
3855 return D3DERR_INVALIDCALL;
3859 GET_SHADER_CONSTANT(vertexShaderConstantI, Vector4iCount, 4);
3864 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
3865 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3868 SET_SHADER_CONSTANT(vertexShaderConstantF, Vector4fCount, 4);
3870 /* populate the bitmap that says which constant type we should load */
3871 for (i = StartRegister; i < StartRegister + Vector4fCount; ++i) {
3872 This->updateStateBlock->changed.vertexShaderConstants[i] = TRUE;
3873 This->updateStateBlock->set.vertexShaderConstants[i] = TRUE;
3874 This->updateStateBlock->vertexShaderConstantT[i] = WINESHADERCNST_FLOAT;
3875 TRACE("(%p) : Setting vsf %d to %f\n", This->updateStateBlock, i, pConstantData[i - StartRegister]);
3880 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
3881 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3884 /* verify that the requested shader constant was populated with a float */
3885 for (i = StartRegister; i < Vector4fCount; ++i) {
3886 if (This->updateStateBlock->vertexShaderConstantT[i] != WINESHADERCNST_FLOAT) {
3888 /* the constant for this register isn't a float */
3889 WARN("(%p) : Caller requested a float where stateblock (%p) entry is a %s. Returning D3DERR_INVALIDCALL\n", This, This->updateStateBlock,
3890 This->updateStateBlock->vertexShaderConstantT[i] == WINESHADERCNST_BOOL ? "boolean" : "integer");
3891 return D3DERR_INVALIDCALL;
3897 GET_SHADER_CONSTANT(vertexShaderConstantF, Vector4fCount, 4);
3902 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
3903 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3905 /* populate the bitmap that says which constant type we should load */
3906 for (i = StartRegister; i < StartRegister + VectorNCount; ++i) {
3907 This->updateStateBlock->changed.vertexShaderConstants[i] = TRUE;
3908 This->updateStateBlock->set.vertexShaderConstants[i] = TRUE;
3909 This->updateStateBlock->vertexShaderConstantT[i] = WINESHADERCNST_NONE;
3910 TRACE("(%p) : Setting vsf %d\n", This, i);
3915 #undef SET_SHADER_CONSTANT
3916 #undef GET_SHADER_CONSTANT
3918 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
3920 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3921 IWineD3DPixelShader *oldpShader = This->updateStateBlock->pixelShader;
3923 This->updateStateBlock->pixelShader = pShader;
3924 This->updateStateBlock->changed.pixelShader = TRUE;
3925 This->updateStateBlock->set.pixelShader = TRUE;
3927 if (pShader == NULL) {
3928 /* clear down the shader */
3929 TRACE("Clear down the shader\n");
3932 /* Handle recording of state blocks */
3933 if (This->isRecordingState) {
3934 TRACE("Recording... not performing anything\n");
3938 * TODO: merge HAL shaders context switching from prototype
3941 /* manage reference counting. */
3942 if (pShader != NULL) {
3943 IWineD3DPixelShader_GetParent(pShader, &parent); /* get parent adds a ref for us*/
3946 if (oldpShader != NULL) {
3947 IWineD3DPixelShader_GetParent(oldpShader, &parent);
3948 IUnknown_Release(parent); /* once for the getparent */
3949 IUnknown_Release(parent); /* and once for the ref */
3955 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3956 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3958 if (NULL == ppShader) {
3959 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
3960 return D3DERR_INVALIDCALL;
3963 *ppShader = This->updateStateBlock->pixelShader;
3964 if (NULL != ppShader) {
3965 IWineD3DPixelShader_AddRef(*ppShader);
3967 TRACE("(%p) : returning %p\n", This, *ppShader);
3971 #define GET_SHADER_CONSTANT(_pixelshaderconstant, _count, _sizecount) \
3972 count = min(_count, MAX_PSHADER_CONSTANTS - (StartRegister + 1)); \
3973 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3974 return D3DERR_INVALIDCALL; \
3975 memcpy(pConstantData, This->updateStateBlock->_pixelshaderconstant + (StartRegister * _sizecount), count * (sizeof(*pConstantData) * _sizecount)); \
3978 #define SET_SHADER_CONSTANT(_pixelshaderconstant, _count, _sizecount) \
3979 int count = min(_count, MAX_PSHADER_CONSTANTS - (StartRegister + 1)); \
3980 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3981 return D3DERR_INVALIDCALL; \
3982 memcpy(This->updateStateBlock->_pixelshaderconstant + (StartRegister * _sizecount), pConstantData, count * (sizeof(*pConstantData) * _sizecount));
3985 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
3986 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3989 SET_SHADER_CONSTANT(pixelShaderConstantB, BoolCount, 1);
3991 /* populate the bitmap that says which constant type we should load */
3992 for (i = StartRegister; i < BoolCount + StartRegister; ++i) {
3993 This->updateStateBlock->changed.pixelShaderConstants[i] = TRUE;
3994 This->updateStateBlock->set.pixelShaderConstants[i] = TRUE;
3995 This->updateStateBlock->pixelShaderConstantT[i] = WINESHADERCNST_BOOL;
3996 TRACE("(%p) : Setting psb %d to %d\n", This->updateStateBlock, i, pConstantData[i - StartRegister]);
4003 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
4004 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4007 /* verify that the requested shader constant was populated with a integer */
4008 for (i = StartRegister; i < BoolCount; ++i) {
4009 if (WINESHADERCNST_BOOL != This->updateStateBlock->pixelShaderConstantT[i]) {
4011 /* the constant for this register isn't a boolean */
4012 WARN("(%p) : Caller requested a integer where stateblock (%p) entry is a %s. Returning D3DERR_INVALIDCALL\n", This, This->updateStateBlock,
4013 WINESHADERCNST_INTEGER == This->updateStateBlock->vertexShaderConstantT[i] ? "integer" : "float");
4014 return D3DERR_INVALIDCALL;
4019 GET_SHADER_CONSTANT(pixelShaderConstantB, BoolCount, 1);
4024 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
4025 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4028 SET_SHADER_CONSTANT(pixelShaderConstantI, Vector4iCount, 4);
4030 /* populate the bitmap that says which constant type we should load */
4031 for (i = StartRegister; i < Vector4iCount + StartRegister; ++i) {
4032 This->updateStateBlock->changed.pixelShaderConstants[i] = TRUE;
4033 This->updateStateBlock->set.pixelShaderConstants[i] = TRUE;
4034 This->updateStateBlock->pixelShaderConstantT[i] = WINESHADERCNST_INTEGER;
4035 TRACE("(%p) : Setting psb %d to %d\n", This->updateStateBlock, i, pConstantData[i - StartRegister]);
4041 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
4042 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4045 /* verify that the requested shader constant was populated with a integer */
4046 for (i = StartRegister; i < Vector4iCount; ++i) {
4047 if (WINESHADERCNST_INTEGER != This->updateStateBlock->pixelShaderConstantT[i]) {
4049 /* the constant for this register isn't a integer */
4050 WARN("(%p) : Caller requested a integer where stateblock (%p) entry is a %s. Returning D3DERR_INVALIDCALL\n", This, This->updateStateBlock,
4051 WINESHADERCNST_BOOL == This->updateStateBlock->vertexShaderConstantT[i] ? "boolean" : "float");
4052 return D3DERR_INVALIDCALL;
4056 GET_SHADER_CONSTANT(pixelShaderConstantI, Vector4iCount, 4);
4061 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
4062 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4064 SET_SHADER_CONSTANT(pixelShaderConstantF, Vector4fCount, 4);
4066 /* populate the bitmap that says which constant type we should load */
4067 for (i = StartRegister; i < Vector4fCount + StartRegister; ++i) {
4068 This->updateStateBlock->changed.pixelShaderConstants[i] = TRUE;
4069 This->updateStateBlock->set.pixelShaderConstants[i] = TRUE;
4070 This->updateStateBlock->pixelShaderConstantT[i] = WINESHADERCNST_FLOAT;
4071 TRACE("(%p) : Setting psb %d to %f\n", This->updateStateBlock, i, pConstantData[i - StartRegister]);
4077 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
4078 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4081 /* verify that the requested shader constant was populated with a integer */
4082 for (i = StartRegister; i < Vector4fCount; ++i) {
4083 if (WINESHADERCNST_FLOAT != This->updateStateBlock->pixelShaderConstantT[i]) {
4085 /* the constant for this register isn't a float */
4086 WARN("(%p) : Caller requested a integer where stateblock (%p) entry is a %s. Returning D3DERR_INVALIDCALL\n", This, This->updateStateBlock,
4087 WINESHADERCNST_BOOL == This->updateStateBlock->vertexShaderConstantT[i] ? "boolean" : "integer");
4088 return D3DERR_INVALIDCALL;
4092 GET_SHADER_CONSTANT(pixelShaderConstantF, Vector4fCount, 4);
4097 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
4098 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4101 /* populate the bitmap that says which constant type we should load */
4102 for (i = StartRegister; i < StartRegister + VectorNCount; ++i) {
4103 This->updateStateBlock->changed.pixelShaderConstants[i] = TRUE;
4104 This->updateStateBlock->set.pixelShaderConstants[i] = TRUE;
4105 This->updateStateBlock->pixelShaderConstantT[i] = WINESHADERCNST_NONE;
4106 TRACE("(%p) : Setting vsf %d\n", This, i);
4112 #undef SET_SHADER_CONSTANT
4113 #undef GET_SHADER_CONSTANT
4115 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
4116 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4117 FIXME("(%p) : stub\n", This);
4122 * Apply / Get / Set Texture Stage States
4123 * TODO: Verify against dx9 definitions
4126 /* NOTE: It's expected that this function is going to be called lots of times with the same stage active, so make it the callers responsibility to GLACTIVETEXTURE(Stage) for better state management. Set the correct Texture unit active before calling ApplyTextureStageState */
4127 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
4128 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4129 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
4130 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4132 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4134 /* Check that the stage is within limits */
4135 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4136 TRACE("Attempt to access invalid texture rejected\n");
4143 case WINED3DTSS_ALPHAOP :
4144 case WINED3DTSS_COLOROP :
4145 /* nothing to do as moved to drawprim for now */
4147 case WINED3DTSS_ADDRESSW :
4148 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
4149 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
4150 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
4153 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
4154 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
4155 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
4156 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
4159 case WINED3DTSS_TEXCOORDINDEX :
4161 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
4163 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
4164 one flag, you can still specify an index value, which the system uses to
4165 determine the texture wrapping mode.
4166 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
4167 means use the vertex position (camera-space) as the input texture coordinates
4168 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
4169 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
4170 to the TEXCOORDINDEX value */
4173 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
4175 switch (Value & 0xFFFF0000) {
4176 case D3DTSS_TCI_PASSTHRU:
4177 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
4178 glDisable(GL_TEXTURE_GEN_S);
4179 glDisable(GL_TEXTURE_GEN_T);
4180 glDisable(GL_TEXTURE_GEN_R);
4181 glDisable(GL_TEXTURE_GEN_Q);
4182 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
4185 case D3DTSS_TCI_CAMERASPACEPOSITION:
4186 /* CameraSpacePosition means use the vertex position, transformed to camera space,
4187 as the input texture coordinates for this stage's texture transformation. This
4188 equates roughly to EYE_LINEAR */
4190 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4191 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4192 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4193 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4194 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4196 glMatrixMode(GL_MODELVIEW);
4199 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4200 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4201 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4202 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4205 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
4206 glEnable(GL_TEXTURE_GEN_S);
4207 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4208 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4209 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4210 glEnable(GL_TEXTURE_GEN_T);
4211 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4212 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4213 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4214 glEnable(GL_TEXTURE_GEN_R);
4215 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4216 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4217 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4221 case D3DTSS_TCI_CAMERASPACENORMAL:
4223 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4224 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4225 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4226 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4227 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4228 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
4230 glMatrixMode(GL_MODELVIEW);
4233 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4234 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4235 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4236 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4239 glEnable(GL_TEXTURE_GEN_S);
4240 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4241 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4242 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4243 glEnable(GL_TEXTURE_GEN_T);
4244 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4245 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4246 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4247 glEnable(GL_TEXTURE_GEN_R);
4248 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4249 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4250 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4255 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
4257 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4258 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4259 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4260 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4261 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4262 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
4264 glMatrixMode(GL_MODELVIEW);
4267 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4268 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4269 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4270 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4273 glEnable(GL_TEXTURE_GEN_S);
4274 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4275 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4276 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4277 glEnable(GL_TEXTURE_GEN_T);
4278 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4279 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4280 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4281 glEnable(GL_TEXTURE_GEN_R);
4282 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4283 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4284 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4289 /* Unhandled types: */
4292 /* ? disable GL_TEXTURE_GEN_n ? */
4293 glDisable(GL_TEXTURE_GEN_S);
4294 glDisable(GL_TEXTURE_GEN_T);
4295 glDisable(GL_TEXTURE_GEN_R);
4296 glDisable(GL_TEXTURE_GEN_Q);
4297 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
4304 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
4305 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);
4308 case WINED3DTSS_BUMPENVMAT00 :
4309 case WINED3DTSS_BUMPENVMAT01 :
4310 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
4312 case WINED3DTSS_BUMPENVMAT10 :
4313 case WINED3DTSS_BUMPENVMAT11 :
4314 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
4317 case WINED3DTSS_BUMPENVLSCALE :
4318 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4321 case WINED3DTSS_BUMPENVLOFFSET :
4322 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4325 case WINED3DTSS_RESULTARG :
4326 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4330 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
4331 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4340 * Get / Set Texture Stage States
4341 * TODO: Verify against dx9 definitions
4343 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
4344 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4346 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4348 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4350 /* Reject invalid texture units */
4351 if (Stage >= GL_LIMITS(textures)) {
4352 TRACE("Attempt to access invalid texture rejected\n");
4353 return D3DERR_INVALIDCALL;
4356 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
4357 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
4358 This->updateStateBlock->textureState[Stage][Type] = Value;
4363 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4364 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4365 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4366 *pValue = This->updateStateBlock->textureState[Stage][Type];
4373 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4375 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4376 IWineD3DBaseTexture *oldTexture;
4378 oldTexture = This->updateStateBlock->textures[Stage];
4379 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
4381 #if 0 /* TODO: check so vertex textures */
4382 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
4383 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
4388 /* Reject invalid texture units */
4389 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4390 WARN("Attempt to access invalid texture rejected\n");
4391 return D3DERR_INVALIDCALL;
4394 oldTexture = This->updateStateBlock->textures[Stage];
4395 TRACE("GL_LIMITS %d\n",GL_LIMITS(textures));
4396 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
4398 This->updateStateBlock->set.textures[Stage] = TRUE;
4399 This->updateStateBlock->changed.textures[Stage] = TRUE;
4400 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
4401 This->updateStateBlock->textures[Stage] = pTexture;
4403 /* Handle recording of state blocks */
4404 if (This->isRecordingState) {
4405 TRACE("Recording... not performing anything\n");
4409 /** NOTE: MSDN says that setTexture increases the reference count,
4410 * and the the application nust set the texture back to null (or have a leaky application),
4411 * This means we should pass the refcount up to the parent
4412 *******************************/
4413 if (NULL != This->updateStateBlock->textures[Stage]) {
4414 IUnknown *textureParent;
4415 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[Stage], (IUnknown **)&textureParent);
4416 /** NOTE: GetParent will increase the ref count for me, I won't clean up until the texture is set to NULL **/
4419 if (NULL != oldTexture) {
4420 IUnknown *textureParent;
4421 IWineD3DBaseTexture_GetParent(oldTexture, (IUnknown **)&textureParent);
4422 IUnknown_Release(textureParent);
4423 IUnknown_Release(textureParent); /** NOTE: Twice because GetParent adds a ref **/
4430 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4431 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4432 TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
4434 /* Reject invalid texture units */
4435 if (Stage >= GL_LIMITS(textures)) {
4436 TRACE("Attempt to access invalid texture rejected\n");
4437 return D3DERR_INVALIDCALL;
4439 *ppTexture=This->updateStateBlock->textures[Stage];
4441 IWineD3DBaseTexture_AddRef(*ppTexture);
4443 return D3DERR_INVALIDCALL;
4450 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type,
4451 IWineD3DSurface **ppBackBuffer) {
4452 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4453 IWineD3DSwapChain *swapChain;
4456 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4458 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4460 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4461 IWineD3DSwapChain_Release(swapChain);
4463 *ppBackBuffer = NULL;
4468 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4469 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4470 WARN("(%p) : stub, calling idirect3d for now\n", This);
4471 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4474 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
4475 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4476 IWineD3DSwapChain *swapChain;
4479 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4481 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4482 IWineD3DSwapChain_Release(swapChain);
4484 FIXME("(%p) Error getting display mode\n", This);
4489 * Stateblock related functions
4492 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4493 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4494 IWineD3DStateBlockImpl *object;
4495 TRACE("(%p)", This);
4496 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4497 if (NULL == object ) {
4498 FIXME("(%p)Error allocating memory for stateblock\n", This);
4499 return E_OUTOFMEMORY;
4501 TRACE("(%p) creted object %p\n", This, object);
4502 object->wineD3DDevice= This;
4503 /** FIXME: object->parent = parent; **/
4504 object->parent = NULL;
4505 object->blockType = WINED3DSBT_ALL;
4507 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
4509 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4510 This->updateStateBlock = object;
4511 This->isRecordingState = TRUE;
4513 TRACE("(%p) recording stateblock %p\n",This , object);
4517 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4518 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4520 if (!This->isRecordingState) {
4521 FIXME("(%p) not recording! returning error\n", This);
4522 *ppStateBlock = NULL;
4523 return D3DERR_INVALIDCALL;
4526 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4527 This->isRecordingState = FALSE;
4528 This->updateStateBlock = This->stateBlock;
4529 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4530 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4531 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4536 * Scene related functions
4538 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4539 /* At the moment we have no need for any functionality at the beginning
4541 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4542 TRACE("(%p) : stub\n", This);
4546 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4547 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4548 TRACE("(%p)\n", This);
4550 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4552 checkGLcall("glFlush");
4554 TRACE("End Scene\n");
4555 if(This->renderTarget != NULL) {
4557 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4558 IUnknown *targetContainer = NULL;
4559 if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
4560 || D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
4561 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
4562 /** always dirtify for now. we must find a better way to see that surface have been modified
4563 (Modifications should will only occur via draw-primitive, but we do need better locking
4564 switching to render-to-texture should remove the overhead though.
4566 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4567 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
4568 IWineD3DSurface_PreLoad(This->renderTarget);
4569 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4570 IUnknown_Release(targetContainer);
4573 This->sceneEnded = TRUE;
4578 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4579 CONST RECT* pSourceRect, CONST RECT* pDestRect,
4580 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4581 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4582 IWineD3DSwapChain *swapChain = NULL;
4584 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4586 TRACE("(%p) Presenting the frame\n", This);
4588 for(i = 0 ; i < swapchains ; i ++) {
4590 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4591 TRACE("presentinng chain %d, %p\n", i, swapChain);
4592 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4593 IWineD3DSwapChain_Release(swapChain);
4599 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4600 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4601 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4603 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4604 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4605 when the depth-buffer format does not contain stencil buffer information, this method fails. */
4606 GLbitfield glMask = 0;
4607 GLboolean old_ztest;
4608 GLfloat old_z_clear_value;
4609 GLint old_stencil_clear_value;
4610 GLfloat old_color_clear_value[4];
4612 CONST D3DRECT* curRect;
4614 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4615 Count, pRects, Flags, Z, Stencil);
4619 glEnable(GL_SCISSOR_TEST);
4620 checkGLcall("glEnable GL_SCISSOR_TEST");
4622 if (Count > 0 && pRects) {
4628 /* Only set the values up once, as they are not changing */
4629 if (Flags & D3DCLEAR_STENCIL) {
4630 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4631 glClearStencil(Stencil);
4632 checkGLcall("glClearStencil");
4633 glMask = glMask | GL_STENCIL_BUFFER_BIT;
4634 glStencilMask(0xFFFFFFFF);
4637 if (Flags & D3DCLEAR_ZBUFFER) {
4638 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4639 glDepthMask(GL_TRUE);
4640 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4642 checkGLcall("glClearDepth");
4643 glMask = glMask | GL_DEPTH_BUFFER_BIT;
4646 if (Flags & D3DCLEAR_TARGET) {
4647 TRACE("Clearing screen with glClear to color %lx\n", Color);
4648 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4649 glClearColor(D3DCOLOR_R(Color),
4653 checkGLcall("glClearColor");
4655 /* Clear ALL colors! */
4656 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4657 glMask = glMask | GL_COLOR_BUFFER_BIT;
4660 /* Now process each rect in turn */
4661 for (i = 0; i < Count || i == 0; i++) {
4664 /* Note gl uses lower left, width/height */
4665 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4666 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4667 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4668 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4669 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4670 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4671 checkGLcall("glScissor");
4673 glScissor(This->stateBlock->viewport.X,
4674 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
4675 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4676 This->stateBlock->viewport.Width,
4677 This->stateBlock->viewport.Height);
4678 checkGLcall("glScissor");
4681 /* Clear the selected rectangle (or full screen) */
4683 checkGLcall("glClear");
4685 /* Step to the next rectangle */
4686 if (curRect) curRect = curRect + sizeof(D3DRECT);
4689 /* Restore the old values (why..?) */
4690 if (Flags & D3DCLEAR_STENCIL) {
4691 glClearStencil(old_stencil_clear_value);
4692 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4694 if (Flags & D3DCLEAR_ZBUFFER) {
4695 glDepthMask(old_ztest);
4696 glClearDepth(old_z_clear_value);
4698 if (Flags & D3DCLEAR_TARGET) {
4699 glClearColor(old_color_clear_value[0],
4700 old_color_clear_value[1],
4701 old_color_clear_value[2],
4702 old_color_clear_value[3]);
4703 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4704 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4705 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4706 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4709 glDisable(GL_SCISSOR_TEST);
4710 checkGLcall("glDisable");
4719 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4720 UINT PrimitiveCount) {
4722 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4723 This->stateBlock->streamIsUP = FALSE;
4725 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4726 debug_d3dprimitivetype(PrimitiveType),
4727 StartVertex, PrimitiveCount);
4728 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
4729 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
4735 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4736 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4737 D3DPRIMITIVETYPE PrimitiveType,
4738 INT baseVIndex, UINT minIndex,
4739 UINT NumVertices, UINT startIndex, UINT primCount) {
4741 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4743 IWineD3DIndexBuffer *pIB;
4744 D3DINDEXBUFFER_DESC IdxBufDsc;
4746 pIB = This->stateBlock->pIndexData;
4747 This->stateBlock->streamIsUP = FALSE;
4749 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
4750 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4751 minIndex, NumVertices, startIndex, baseVIndex, primCount);
4753 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4754 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4760 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
4761 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
4766 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4767 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4768 UINT VertexStreamZeroStride) {
4769 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4771 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4772 debug_d3dprimitivetype(PrimitiveType),
4773 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4775 if (This->stateBlock->streamSource[0] != NULL) {
4776 IUnknown *vertexBufferParent;
4777 IWineD3DVertexBuffer_GetParent(This->stateBlock->streamSource[0], &vertexBufferParent);
4778 IUnknown_Release(vertexBufferParent);
4779 IUnknown_Release(vertexBufferParent);
4782 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4783 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4784 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4785 This->stateBlock->streamIsUP = TRUE;
4787 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
4788 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
4789 /* stream zero settings set to null at end, as per the msdn
4790 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
4792 This->stateBlock->streamStride[0] = 0;
4793 This->stateBlock->streamSource[0] = NULL;
4795 /*stream zero settings set to null at end, as per the msdn */
4799 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4800 UINT MinVertexIndex, UINT NumVertices,
4801 UINT PrimitiveCount, CONST void* pIndexData,
4802 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4803 UINT VertexStreamZeroStride) {
4805 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4807 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4808 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4809 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
4810 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4812 if (IndexDataFormat == WINED3DFMT_INDEX16) {
4818 if (This->stateBlock->streamSource[0] != NULL) {
4819 IUnknown *vertexBufferParent;
4820 IWineD3DVertexBuffer_GetParent(This->stateBlock->streamSource[0], &vertexBufferParent);
4821 This->stateBlock->streamSource[0] = NULL;
4822 IUnknown_Release(vertexBufferParent);
4823 IUnknown_Release(vertexBufferParent);
4826 if (This->stateBlock->pIndexData) {
4827 IUnknown *indexBufferParent;
4828 IWineD3DIndexBuffer_GetParent(This->stateBlock->pIndexData, &indexBufferParent);
4829 This->stateBlock->pIndexData = NULL;
4830 IUnknown_Release(indexBufferParent);
4831 IUnknown_Release(indexBufferParent);
4834 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4835 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4836 This->stateBlock->streamIsUP = TRUE;
4837 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4839 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
4840 /* stream zero settings set to null at end as per the msdn
4841 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
4844 /* stream zero settings set to null at end as per the msdn */
4845 This->stateBlock->streamSource[0] = NULL;
4846 This->stateBlock->streamStride[0] = 0;
4851 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4852 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
4853 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4854 HRESULT hr = D3D_OK;
4855 D3DRESOURCETYPE sourceType;
4856 D3DRESOURCETYPE destinationType;
4859 /* TODO: think about moving the code into IWineD3DBaseTexture */
4861 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
4863 /* verify that the source and destination textures aren't NULL */
4864 if (NULL == pSourceTexture || NULL == pDestinationTexture) {
4865 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning D3DERR_INVALIDCALL\n",
4866 This, pSourceTexture, pDestinationTexture);
4867 hr = D3DERR_INVALIDCALL;
4870 if (pSourceTexture == pDestinationTexture) {
4871 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning D3DERR_INVALIDCALL\n",
4872 This, pSourceTexture, pDestinationTexture);
4873 hr = D3DERR_INVALIDCALL;
4875 /* Verify that the source and destination textures are the same type */
4876 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
4877 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
4879 if (sourceType != destinationType) {
4880 WARN("(%p) Sorce and destination types must match, returning D3DERR_INVALIDCALL\n",
4882 hr = D3DERR_INVALIDCALL;
4885 /* check that both textures have the identical numbers of levels */
4886 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
4887 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning D3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
4888 hr = D3DERR_INVALIDCALL;
4893 /* Make sure that the destination texture is loaded */
4894 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
4896 /* Update every surface level of the texture */
4897 levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
4899 switch (sourceType) {
4900 case D3DRTYPE_TEXTURE:
4902 IWineD3DSurface *srcSurface;
4903 IWineD3DSurface *destSurface;
4905 for (i = 0 ; i < levels ; ++i) {
4906 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture, i, &srcSurface);
4907 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
4908 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4909 IWineD3DSurface_Release(srcSurface);
4910 IWineD3DSurface_Release(destSurface);
4912 WARN("(%p) : Call to update surface failed\n", This);
4918 case D3DRTYPE_CUBETEXTURE:
4920 IWineD3DSurface *srcSurface;
4921 IWineD3DSurface *destSurface;
4922 D3DCUBEMAP_FACES faceType;
4924 for (i = 0 ; i < levels ; ++i) {
4925 /* Update each cube face */
4926 for (faceType = D3DCUBEMAP_FACE_POSITIVE_X; faceType <= D3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
4927 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture, faceType, i, &srcSurface);
4929 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4931 TRACE("Got srcSurface %p\n", srcSurface);
4933 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
4935 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4937 TRACE("Got desrSurface %p\n", destSurface);
4939 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4940 IWineD3DSurface_Release(srcSurface);
4941 IWineD3DSurface_Release(destSurface);
4943 WARN("(%p) : Call to update surface failed\n", This);
4950 #if 0 /* TODO: Add support for volume textures */
4951 case D3DRTYPE_VOLUMETEXTURE:
4953 IWineD3DVolume srcVolume = NULL;
4954 IWineD3DSurface destVolume = NULL;
4956 for (i = 0 ; i < levels ; ++i) {
4957 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture, i, &srcVolume);
4958 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
4959 hr = IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
4960 IWineD3DVolume_Release(srcSurface);
4961 IWineD3DVolume_Release(destSurface);
4963 WARN("(%p) : Call to update volume failed\n", This);
4971 FIXME("(%p) : Unsupported source and destination type\n", This);
4972 hr = D3DERR_INVALIDCALL;
4979 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
4980 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
4981 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
4982 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4984 TRACE("(%p) : stub\n", This);
4987 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
4988 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4989 /** TODO: remove remove casts to IWineD3DSurfaceImpl *
4990 * NOTE It may be best to move the code into surface to occomplish this
4991 ****************************************/
4993 WINED3DSURFACE_DESC surfaceDesc;
4994 unsigned int surfaceWidth, surfaceHeight;
4995 glDescriptor *targetGlDescription = NULL;
4996 glDescriptor *surfaceGlDescription = NULL;
4997 IWineD3DSwapChainImpl *container = NULL;
4999 IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
5000 IWineD3DSurface_GetGlDesc(pSurface, &surfaceGlDescription);
5001 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5003 surfaceDesc.Width = &surfaceWidth;
5004 surfaceDesc.Height = &surfaceHeight;
5005 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5006 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
5008 /* Ok, I may need to setup some kind of active swapchain reference on the device */
5009 IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
5011 /* TODO: opengl Context switching for swapchains etc... */
5012 if (NULL != container || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
5013 if (NULL != container && (pRenderTarget == container->backBuffer)) {
5014 glReadBuffer(GL_BACK);
5015 vcheckGLcall("glReadBuffer(GL_BACK)");
5016 } else if ((NULL != container && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
5017 glReadBuffer(GL_FRONT);
5018 vcheckGLcall("glReadBuffer(GL_FRONT)");
5019 } else if (pRenderTarget == This->depthStencilBuffer) {
5020 FIXME("Reading of depthstencil not yet supported\n");
5023 glReadPixels(surfaceGlDescription->target,
5024 surfaceGlDescription->level,
5027 surfaceGlDescription->glFormat,
5028 surfaceGlDescription->glType,
5029 (void *)IWineD3DSurface_GetData(pSurface));
5030 vcheckGLcall("glReadPixels(...)");
5031 if(NULL != container ){
5032 IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
5035 IWineD3DBaseTexture *container;
5036 GLenum textureDimensions = GL_TEXTURE_2D;
5038 if (D3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
5039 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
5040 IWineD3DBaseTexture_Release(container);
5042 /* TODO: 2D -> Cube surface coppies etc.. */
5043 if (surfaceGlDescription->target != textureDimensions) {
5044 FIXME("(%p) : Texture dimension mismatch\n", This);
5046 glEnable(textureDimensions);
5047 vcheckGLcall("glEnable(GL_TEXTURE_...)");
5048 /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
5049 glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
5050 vcheckGLcall("glBindTexture");
5051 glGetTexImage(surfaceGlDescription->target,
5052 surfaceGlDescription->level,
5053 surfaceGlDescription->glFormat,
5054 surfaceGlDescription->glType,
5055 (void *)IWineD3DSurface_GetData(pSurface));
5056 glDisable(textureDimensions);
5057 vcheckGLcall("glDisable(GL_TEXTURE_...)");
5064 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
5065 IWineD3DSwapChain *swapChain;
5067 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5069 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
5070 IWineD3DSwapChain_Release(swapChain);
5075 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5076 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5077 /* return a sensible default */
5079 /* TODO: If the window is minimized then validate device should return something other than d3d_ok */
5080 FIXME("(%p) : stub\n", This);
5084 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5085 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5087 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5088 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5089 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5090 return D3DERR_INVALIDCALL;
5092 for (j = 0; j < 256; ++j) {
5093 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
5094 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5095 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
5096 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5098 TRACE("(%p) : returning\n", This);
5102 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5103 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5105 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5106 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5107 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5108 return D3DERR_INVALIDCALL;
5110 for (j = 0; j < 256; ++j) {
5111 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
5112 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5113 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
5114 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5116 TRACE("(%p) : returning\n", This);
5120 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5121 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5122 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5123 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5124 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5125 return D3DERR_INVALIDCALL;
5127 /*TODO: stateblocks */
5128 This->currentPalette = PaletteNumber;
5129 TRACE("(%p) : returning\n", This);
5133 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
5134 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5135 if (PaletteNumber == NULL) {
5136 WARN("(%p) : returning Invalid Call\n", This);
5137 return D3DERR_INVALIDCALL;
5139 /*TODO: stateblocks */
5140 *PaletteNumber = This->currentPalette;
5141 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
5145 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
5146 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5147 static BOOL showFixmes = TRUE;
5149 FIXME("(%p) : stub\n", This);
5153 This->softwareVertexProcessing = bSoftware;
5158 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
5159 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5160 static BOOL showFixmes = TRUE;
5162 FIXME("(%p) : stub\n", This);
5165 return This->softwareVertexProcessing;
5169 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
5170 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5171 IWineD3DSwapChain *swapChain;
5174 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
5176 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5178 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
5179 IWineD3DSwapChain_Release(swapChain);
5181 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
5187 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
5188 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5189 static BOOL showfixmes = TRUE;
5190 if(nSegments != 0.0f) {
5192 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
5199 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
5200 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5201 static BOOL showfixmes = TRUE;
5203 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
5209 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
5210 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5211 /** TODO: remove casts to IWineD3DSurfaceImpl
5212 * NOTE: move code to surface to accomplish this
5213 ****************************************/
5214 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
5215 int srcWidth, srcHeight;
5216 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
5217 WINED3DFORMAT destFormat, srcFormat;
5219 int destLeft, destTop;
5220 D3DPOOL srcPool, destPool;
5222 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
5223 glDescriptor *glDescription = NULL;
5224 GLenum textureDimensions = GL_TEXTURE_2D;
5225 IWineD3DBaseTexture *baseTexture;
5227 WINED3DSURFACE_DESC winedesc;
5229 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
5230 memset(&winedesc, 0, sizeof(winedesc));
5231 winedesc.Width = &srcSurfaceWidth;
5232 winedesc.Height = &srcSurfaceHeight;
5233 winedesc.Pool = &srcPool;
5234 winedesc.Format = &srcFormat;
5236 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5238 winedesc.Width = &destSurfaceWidth;
5239 winedesc.Height = &destSurfaceHeight;
5240 winedesc.Pool = &destPool;
5241 winedesc.Format = &destFormat;
5242 winedesc.Size = &destSize;
5244 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5246 if(srcPool != D3DPOOL_SYSTEMMEM || destPool != D3DPOOL_DEFAULT){
5247 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning D3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
5248 return D3DERR_INVALIDCALL;
5251 if (destFormat == WINED3DFMT_UNKNOWN) {
5252 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5253 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5255 /* Get the update surface description */
5256 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5259 /* Make sure the surface is loaded and up to date */
5260 IWineD3DSurface_PreLoad(pDestinationSurface);
5262 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
5266 /* this needs to be done in lines if the sourceRect != the sourceWidth */
5267 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
5268 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
5269 destLeft = pDestPoint ? pDestPoint->x : 0;
5270 destTop = pDestPoint ? pDestPoint->y : 0;
5273 /* This function doesn't support compressed textures
5274 the pitch is just bytesPerPixel * width */
5275 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
5276 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
5277 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
5278 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
5280 /* TODO DXT formats */
5282 if(pSourceRect != NULL && pSourceRect->top != 0){
5283 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
5285 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
5287 ,glDescription->level
5292 ,glDescription->glFormat
5293 ,glDescription->glType
5294 ,IWineD3DSurface_GetData(pSourceSurface)
5298 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
5300 /* need to lock the surface to get the data */
5301 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5304 /* TODO: Cube and volume support */
5306 /* not a whole row so we have to do it a line at a time */
5309 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
5310 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5312 for(j = destTop ; j < (srcHeight + destTop) ; j++){
5314 glTexSubImage2D(glDescription->target
5315 ,glDescription->level
5320 ,glDescription->glFormat
5321 ,glDescription->glType
5322 ,data /* could be quicker using */
5327 } else { /* Full width, so just write out the whole texture */
5329 if (WINED3DFMT_DXT1 == destFormat ||
5330 WINED3DFMT_DXT2 == destFormat ||
5331 WINED3DFMT_DXT3 == destFormat ||
5332 WINED3DFMT_DXT4 == destFormat ||
5333 WINED3DFMT_DXT5 == destFormat) {
5334 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
5335 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
5336 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
5337 FIXME("Updating part of a compressed texture is not supported at the moment\n");
5338 } if (destFormat != srcFormat) {
5339 FIXME("Updating mixed format compressed texture is not curretly support\n");
5341 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
5342 glDescription->level,
5343 glDescription->glFormatInternal,
5348 IWineD3DSurface_GetData(pSourceSurface));
5351 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
5356 if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
5358 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
5359 to repack the data from pow2Width/Height to expected Width,Height, this makes the
5360 data returned by GetData non-power2 width/height with hardware non-power2
5361 pow2Width/height are set to surface width height, repacking isn't needed so it
5362 doesn't matter which function gets called. */
5363 glTexSubImage2D(glDescription->target
5364 ,glDescription->level
5369 ,glDescription->glFormat
5370 ,glDescription->glType
5371 ,IWineD3DSurface_GetData(pSourceSurface)
5375 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
5376 glTexSubImage2D(glDescription->target
5377 ,glDescription->level
5380 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
5381 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
5382 ,glDescription->glFormat
5383 ,glDescription->glType
5384 ,IWineD3DSurface_GetData(pSourceSurface)
5390 checkGLcall("glTexSubImage2D");
5392 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
5393 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
5394 * surface bigger than it needs to be hmm.. */
5395 if (D3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
5396 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
5397 IWineD3DBaseTexture_Release(baseTexture);
5400 glDisable(textureDimensions); /* This needs to be managed better.... */
5406 /* Implementation details at http://developer.nvidia.com/attach/6494
5408 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
5409 hmm.. no longer supported use
5410 OpenGL evaluators or tessellate surfaces within your application.
5413 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
5414 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
5415 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5416 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
5417 FIXME("(%p) : Stub\n", This);
5422 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
5423 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
5424 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5425 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
5426 FIXME("(%p) : Stub\n", This);
5430 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5431 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5432 TRACE("(%p) Handle(%d)\n", This, Handle);
5433 FIXME("(%p) : Stub\n", This);
5437 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
5438 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
5439 fill a surface with a block of color! */
5440 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5441 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
5442 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
5443 IWineD3DSwapChainImpl *container = NULL;
5444 BOOL isRenderTarget = FALSE;
5445 unsigned int width, height;
5446 unsigned int top, left;
5449 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
5451 if (surface->resource.pool != D3DPOOL_DEFAULT) {
5452 FIXME("call to colorfill with non D3DPOOL_DEFAULT surface\n");
5453 return D3DERR_INVALIDCALL;
5456 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
5457 if (D3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
5458 if (D3DUSAGE_RENDERTARGET & surface->resource.usage) {
5459 /* TODO: make sure we set everything back to the way it was, and context management!
5460 glGetIntegerv(GL_READ_BUFFER, &prev_read);
5461 vcheckGLcall("glIntegerv");
5462 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
5463 vcheckGLcall("glIntegerv");
5465 TRACE("Color fill to render targets may cause some graphics issues\n");
5466 if (pSurface == container->frontBuffer) {
5467 glDrawBuffer(GL_FRONT);
5469 glDrawBuffer(GL_BACK);
5472 if (D3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
5473 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld\n", surface, surface->resource.usage);
5475 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
5477 if (container != NULL) {
5478 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5480 /* we can use GL_STENCIL_INDEX etc...*/
5483 if (container != NULL) {
5484 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5486 isRenderTarget = TRUE;
5488 /* TODO: drawing to GL_FRONT and GL_BACK */
5489 /* TODO: see if things can be speeded up by using the correct
5490 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
5491 if (pRect == NULL) {
5494 width = surface->currentDesc.Width;
5495 height = surface->currentDesc.Height;
5499 width = pRect->x2 - left;
5500 height = pRect->y2 - top;
5503 data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
5504 /* Create a 'line' of color color, in the correct format for the surface */
5505 for (u = 0 ; u < width ; u ++) {
5510 if (isRenderTarget == FALSE) {
5511 glDescriptor *glDesc;
5512 IWineD3DSurface_PreLoad(pSurface);
5514 /* draw a block of the coloured line on the sufrace */
5515 IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
5516 for (v = 0 ; v< height;v++) {
5517 glTexSubImage2D(glDesc->target
5518 ,glDesc->level /* level */
5528 checkGLcall("glTexSubImage2D");
5530 glDisable(glDesc->target);
5532 /** FIXME: Using GLClear may be faster **/
5533 glRasterPos2i(left, top);
5534 glPixelZoom((float)width ,(float)height);
5535 glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
5536 checkGLcall("glDrawPixels");
5538 HeapFree(GetProcessHeap(), 0, data);
5544 /* rendertarget and deptth stencil functions */
5545 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
5546 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5548 /* FIXME: Implelent RenderTargetIndex >0 */
5549 if(RenderTargetIndex > 0)
5550 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
5552 *ppRenderTarget = This->renderTarget;
5553 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
5554 /* Note inc ref on returned surface */
5555 if(*ppRenderTarget != NULL)
5556 IWineD3DSurface_AddRef(*ppRenderTarget);
5560 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5561 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5562 *ppZStencilSurface = This->depthStencilBuffer;
5563 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
5565 if(*ppZStencilSurface != NULL) {
5566 /* Note inc ref on returned surface */
5567 IWineD3DSurface_AddRef(*ppZStencilSurface);
5572 /* internal static helper functions */
5573 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5574 IWineD3DSurface *RenderSurface);
5576 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5577 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5578 HRESULT hr = D3D_OK;
5579 WINED3DVIEWPORT viewport;
5581 TRACE("(%p) Swapping rendertarget\n",This);
5582 if (RenderTargetIndex > 0) {
5583 FIXME("(%p) Render targets other than the first are not supported\n",This);
5584 RenderTargetIndex = 0;
5587 /* MSDN says that null disables the render target
5588 but a device must always be associated with a render target
5589 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5591 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5594 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5595 FIXME("Trying to set render target 0 to NULL\n");
5596 return D3DERR_INVALIDCALL;
5598 /* TODO: replace Impl* usage with interface usage */
5599 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & D3DUSAGE_RENDERTARGET) {
5600 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);
5601 return D3DERR_INVALIDCALL;
5603 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
5604 * builds, but I think wine counts as a 'debug' build for now.
5605 ******************************/
5606 /* If we are trying to set what we already have, don't bother */
5607 if (pRenderTarget == This->renderTarget) {
5608 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5610 /* Otherwise, set the render target up */
5612 if (FALSE == This->sceneEnded) {
5613 IWineD3DDevice_EndScene(iface);
5615 TRACE("clearing renderer\n");
5616 /* IWineD3DDeviceImpl_CleanRender(iface); */
5617 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5618 depending on the renter target implementation being used.
5619 A shared context implementation will share all buffers between all rendertargets (including swapchains),
5620 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5621 stencil buffer and incure an extra memory overhead */
5622 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
5625 if (SUCCEEDED(hr)) {
5626 /* Finally, reset the viewport as the MSDN states. */
5627 /* TODO: Replace impl usage */
5628 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
5629 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
5632 viewport.MaxZ = 1.0f;
5633 viewport.MinZ = 0.0f;
5634 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
5636 FIXME("Unknown error setting the render target\n");
5638 This->sceneEnded = FALSE;
5642 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
5643 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5644 HRESULT hr = D3D_OK;
5645 IWineD3DSurface *tmp;
5647 TRACE("(%p) Swapping z-buffer\n",This);
5649 if (pNewZStencil == This->stencilBufferTarget) {
5650 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5652 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5653 * depending on the renter target implementation being used.
5654 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5655 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5656 * stencil buffer and incure an extra memory overhead
5657 ******************************************************/
5660 tmp = This->stencilBufferTarget;
5661 This->stencilBufferTarget = pNewZStencil;
5662 /* should we be calling the parent or the wined3d surface? */
5663 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
5664 if (NULL != tmp) IWineD3DSurface_Release(tmp);
5666 /** TODO: glEnable/glDisable on depth/stencil depending on
5667 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
5668 **********************************************************/
5675 #ifdef GL_VERSION_1_3
5676 /* Internal functions not in DirectX */
5677 /** TODO: move this off to the opengl context manager
5678 *(the swapchain doesn't need to know anything about offscreen rendering!)
5679 ****************************************************/
5681 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
5683 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5685 TRACE("(%p), %p\n", This, swapchain);
5687 if (swapchain->win != swapchain->drawable) {
5688 /* Set everything back the way it ws */
5689 swapchain->render_ctx = swapchain->glCtx;
5690 swapchain->drawable = swapchain->win;
5695 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
5696 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
5697 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5700 unsigned int height;
5701 WINED3DFORMAT format;
5702 WINED3DSURFACE_DESC surfaceDesc;
5703 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5704 surfaceDesc.Width = &width;
5705 surfaceDesc.Height = &height;
5706 surfaceDesc.Format = &format;
5707 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5709 /* I need a get width/height function (and should do something with the format) */
5710 for (i = 0; i < CONTEXT_CACHE; ++i) {
5711 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
5712 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
5713 the pSurface can be set to 0 allowing it to be reused from cache **/
5714 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
5715 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
5716 *context = &This->contextCache[i];
5719 if (This->contextCache[i].Width == 0) {
5720 This->contextCache[i].pSurface = pSurface;
5721 This->contextCache[i].Width = width;
5722 This->contextCache[i].Height = height;
5723 *context = &This->contextCache[i];
5727 if (i == CONTEXT_CACHE) {
5728 int minUsage = 0x7FFFFFFF; /* MAX_INT */
5729 glContext *dropContext = 0;
5730 for (i = 0; i < CONTEXT_CACHE; i++) {
5731 if (This->contextCache[i].usedcount < minUsage) {
5732 dropContext = &This->contextCache[i];
5733 minUsage = This->contextCache[i].usedcount;
5736 /* clean up the context (this doesn't work for ATI at the moment */
5738 glXDestroyContext(swapchain->display, dropContext->context);
5739 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
5742 dropContext->Width = 0;
5743 dropContext->pSurface = pSurface;
5744 *context = dropContext;
5746 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
5747 for (i = 0; i < CONTEXT_CACHE; i++) {
5748 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
5752 if (*context != NULL)
5755 return E_OUTOFMEMORY;
5759 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
5760 * the functionality needs splitting up so that we don't do more than we should do.
5761 * this only seems to impact performance a little.
5762 ******************************/
5763 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5764 IWineD3DSurface *RenderSurface) {
5765 HRESULT ret = D3DERR_INVALIDCALL;
5768 * Currently only active for GLX >= 1.3
5769 * for others versions we'll have to use GLXPixmaps
5771 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
5772 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
5773 * so only check OpenGL version
5774 * ..........................
5775 * I don't believe that it is a problem with NVidia headers,
5776 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
5777 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
5779 * Your application will report GLX version 1.2 on glXQueryVersion.
5780 * However, it is safe to call the GLX 1.3 functions as described below.
5782 #if defined(GL_VERSION_1_3)
5784 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5785 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
5786 IWineD3DSurface *tmp;
5787 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
5788 GLXFBConfig* cfgs = NULL;
5792 IWineD3DSwapChain *currentSwapchain;
5793 IWineD3DSwapChainImpl *swapchain;
5794 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
5795 * but switch them off if the StencilSurface is set to NULL
5796 ** *********************************************************/
5797 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
5798 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
5801 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
5802 it StencilSurface != NULL && zBufferTarget == NULL switch it on
5805 #define PUSH1(att) attribs[nAttribs++] = (att);
5806 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
5808 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
5810 /** TODO: remove the reff to Impl (context manager should fix this!) **/
5811 IWineD3DSwapChainImpl *impSwapChain;
5812 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
5813 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
5814 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
5819 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
5820 PUSH2(GLX_X_RENDERABLE, TRUE);
5821 PUSH2(GLX_DOUBLEBUFFER, TRUE);
5822 TRACE("calling makeglcfg\n");
5823 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
5826 TRACE("calling chooseFGConfig\n");
5827 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5830 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
5831 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
5832 why we failed and only show this message once! */
5833 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"); /**/
5835 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
5836 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
5837 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
5838 PUSH2(GLX_DOUBLEBUFFER, FALSE);
5839 TRACE("calling makeglcfg\n");
5840 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
5842 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5849 for (i = 0; i < nCfgs; ++i) {
5850 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
5851 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
5852 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
5855 if (NULL != This->renderTarget) {
5857 vcheckGLcall("glFlush");
5858 /** This is only useful if the old render target was a swapchain,
5859 * we need to supercede this with a function that displays
5860 * the current buffer on the screen. This is easy to do in glx1.3 but
5861 * we need to do copy-write pixels in glx 1.2.
5862 ************************************************/
5863 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
5865 printf("Hit Enter to get next frame ...\n");
5871 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain) != D3D_OK) {
5872 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
5873 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
5877 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
5878 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
5879 **********************************************************************/
5880 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == D3D_OK) {
5881 /* We also need to make sure that the lights &co are also in the context of the swapchains */
5882 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
5883 TRACE("making swapchain active\n");
5884 if (RenderSurface != This->renderTarget) {
5885 if (RenderSurface == swapchain->backBuffer) {
5887 /* This could be flagged so that some operations work directly with the front buffer */
5888 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
5890 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
5892 TRACE("Error in setting current context: context %p drawable %ld !\n",
5893 impSwapChain->glCtx, impSwapChain->win);
5896 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5898 checkGLcall("glXMakeContextCurrent");
5900 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5902 else if (pbuffer_support == TRUE && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
5904 /** ********************************************************************
5905 * This is a quickly hacked out implementation of offscreen textures.
5906 * It will work in most cases but there may be problems if the client
5907 * modifies the texture directly, or expects the contents of the rendertarget
5910 * There are some real speed vs compatibility issues here:
5911 * we should really use a new context for every texture, but that eats ram.
5912 * we should also be restoring the texture to the pbuffer but that eats CPU
5913 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
5914 * but if this means reusing the display backbuffer then we need to make sure that
5915 * states are correctly preserved.
5916 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
5917 * and gain a good performance increase at the cost of compatibility.
5918 * I would suggest that, when this is the case, a user configurable flag be made
5919 * available, allowing the user to choose the best emulated experience for them.
5920 *********************************************************************/
5922 XVisualInfo *visinfo;
5923 glContext *newContext;
5925 /* Here were using a shared context model */
5926 if (D3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
5927 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5930 /* If the context doesn't exist then create a new one */
5931 /* TODO: This should really be part of findGlContext */
5932 if (NULL == newContext->context) {
5934 TRACE("making new buffer\n");
5936 PUSH2(GLX_PBUFFER_WIDTH, newContext->Width);
5937 PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
5940 newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
5942 /** ****************************************
5943 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
5945 * In future releases, we may provide the calls glXCreateNewContext,
5946 * glXQueryDrawable and glXMakeContextCurrent.
5947 * so until then we have to use glXGetVisualFromFBConfig &co..
5948 ********************************************/
5951 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
5953 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
5955 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
5959 if (NULL == newContext || NULL == newContext->context) {
5960 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5962 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
5963 if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
5964 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
5967 /* Clean up the old context */
5968 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5969 /* Set the current context of the swapchain to the new context */
5970 impSwapChain->drawable = newContext->drawable;
5971 impSwapChain->render_ctx = newContext->context;
5975 #if 1 /* Apply the stateblock to the new context
5976 FIXME: This is a bit of a hack, each context should know it's own state,
5977 the directX current directX state should then be applied to the context */
5980 IWineD3DStateBlockImpl *oldUpdateStateBlock;
5981 oldUpdateStateBlock = This->updateStateBlock;
5982 oldRecording= This->isRecordingState;
5983 This->isRecordingState = FALSE;
5984 This->updateStateBlock = This->stateBlock;
5985 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
5987 This->isRecordingState = oldRecording;
5988 This->updateStateBlock = oldUpdateStateBlock;
5993 /* clean up the current rendertargets swapchain (if it belonged to one) */
5994 if (currentSwapchain != NULL) {
5995 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
5998 /* Were done with the opengl context management, setup the rendertargets */
6000 tmp = This->renderTarget;
6001 This->renderTarget = RenderSurface;
6002 IWineD3DSurface_AddRef(This->renderTarget);
6003 IWineD3DSurface_Release(tmp);
6009 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
6010 /* Check that the container is not a swapchain member */
6012 IWineD3DSwapChain *tmpSwapChain;
6013 if (D3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
6014 This->renderUpsideDown = TRUE;
6016 This->renderUpsideDown = FALSE;
6017 IWineD3DSwapChain_Release(tmpSwapChain);
6019 /* Force updating the cull mode */
6020 TRACE("setting render state\n");
6021 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
6022 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
6024 /* Force updating projection matrix */
6025 This->last_was_rhw = FALSE;
6026 This->proj_valid = FALSE;
6034 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
6035 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
6040 if ( NULL != impSwapChain) {
6041 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
6049 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
6050 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
6051 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6052 /* TODO: the use of Impl is deprecated. */
6053 /* some basic validation checks */
6054 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
6056 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
6058 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
6059 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
6060 return D3DERR_INVALIDCALL;
6062 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
6063 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
6064 return D3DERR_INVALIDCALL;
6066 /* TODO: make the cursor 'real' */
6068 This->xHotSpot = XHotSpot;
6069 This->yHotSpot = YHotSpot;
6074 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
6075 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6076 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
6078 This->xScreenSpace = XScreenSpace;
6079 This->yScreenSpace = YScreenSpace;
6085 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
6086 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6087 TRACE("(%p) : visible(%d)\n", This, bShow);
6089 This->bCursorVisible = bShow;
6094 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
6095 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6096 TRACE("(%p) : state (%lu)\n", This, This->state);
6097 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
6098 switch (This->state) {
6101 case D3DERR_DEVICELOST:
6103 ResourceList *resourceList = This->resources;
6104 while (NULL != resourceList) {
6105 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == D3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
6106 return D3DERR_DEVICENOTRESET;
6107 resourceList = resourceList->next;
6109 return D3DERR_DEVICELOST;
6111 case D3DERR_DRIVERINTERNALERROR:
6112 return D3DERR_DRIVERINTERNALERROR;
6116 return D3DERR_DRIVERINTERNALERROR;
6120 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
6121 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6122 /** FIXME: Resource tracking needs to be done,
6123 * The closes we can do to this is set the priorities of all managed textures low
6124 * and then reset them.
6125 ***********************************************************/
6126 FIXME("(%p) : stub\n", This);
6130 HRESULT WINAPI IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
6131 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6132 /** FIXME: Resource trascking needs to be done.
6133 * in effect this pulls all non only default
6134 * textures out of video memory and deletes all glTextures (glDeleteTextures)
6135 * and should clear down the context and set it up according to pPresentationParameters
6136 ***********************************************************/
6137 FIXME("(%p) : stub\n", This);
6141 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
6142 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6143 /** FIXME: always true at the moment **/
6144 if(bEnableDialogs == FALSE) {
6145 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
6151 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
6152 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6154 FIXME("(%p) : stub\n", This);
6155 /* Setup some reasonable defaults */
6156 pParameters->AdapterOrdinal = 0; /* always for now */
6157 pParameters->DeviceType = D3DDEVTYPE_HAL; /* always for now */
6158 pParameters->hFocusWindow = 0;
6159 pParameters->BehaviorFlags =0;
6163 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
6164 IWineD3DSwapChain *swapchain;
6165 HRESULT hrc = D3D_OK;
6167 TRACE("Relaying to swapchain\n");
6169 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
6170 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (D3DGAMMARAMP *)pRamp);
6171 IWineD3DSwapChain_Release(swapchain);
6176 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
6177 IWineD3DSwapChain *swapchain;
6178 HRESULT hrc = D3D_OK;
6180 TRACE("Relaying to swapchain\n");
6182 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
6183 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
6184 IWineD3DSwapChain_Release(swapchain);
6190 /** ********************************************************
6191 * Notification functions
6192 ** ********************************************************/
6193 /** This function must be called in the release of a resource when ref == 0,
6194 * the contents of resource must still be correct,
6195 * any handels to other resource held by the caller must be closed
6196 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
6197 *****************************************************/
6198 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6199 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6200 ResourceList* resourceList;
6202 TRACE("(%p) : resource %p\n", This, resource);
6204 EnterCriticalSection(&resourceStoreCriticalSection);
6206 /* add a new texture to the frot of the linked list */
6207 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
6208 resourceList->resource = resource;
6210 /* Get the old head */
6211 resourceList->next = This->resources;
6213 This->resources = resourceList;
6214 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
6217 LeaveCriticalSection(&resourceStoreCriticalSection);
6222 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6223 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6224 ResourceList* resourceList = NULL;
6225 ResourceList* previousResourceList = NULL;
6227 TRACE("(%p) : resource %p\n", This, resource);
6230 EnterCriticalSection(&resourceStoreCriticalSection);
6232 resourceList = This->resources;
6234 while (resourceList != NULL) {
6235 if(resourceList->resource == resource) break;
6236 previousResourceList = resourceList;
6237 resourceList = resourceList->next;
6240 if (resourceList == NULL) {
6241 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
6243 LeaveCriticalSection(&resourceStoreCriticalSection);
6247 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
6249 /* make sure we don't leave a hole in the list */
6250 if (previousResourceList != NULL) {
6251 previousResourceList->next = resourceList->next;
6253 This->resources = resourceList->next;
6257 LeaveCriticalSection(&resourceStoreCriticalSection);
6263 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
6264 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6267 TRACE("(%p) : resource %p\n", This, resource);
6268 switch(IWineD3DResource_GetType(resource)){
6269 case D3DRTYPE_SURFACE:
6270 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
6272 case D3DRTYPE_TEXTURE:
6273 case D3DRTYPE_CUBETEXTURE:
6274 case D3DRTYPE_VOLUMETEXTURE:
6275 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
6276 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6277 IUnknown *textureParent;
6278 IWineD3DBaseTexture_GetParent(This->stateBlock->textures[counter], &textureParent);
6279 /* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
6280 FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter, resource, textureParent);
6281 IUnknown_Release(textureParent);
6282 This->stateBlock->textures[counter] = NULL;
6284 if (This->updateStateBlock != This->stateBlock ){
6285 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6286 IUnknown *textureParent;
6287 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[counter], &textureParent);
6288 /* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
6289 FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter, resource, textureParent);
6290 IUnknown_Release(textureParent);
6291 This->updateStateBlock->textures[counter] = NULL;
6296 case D3DRTYPE_VOLUME:
6297 /* TODO: nothing really? */
6299 case D3DRTYPE_VERTEXBUFFER:
6300 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
6303 TRACE("Cleaning up stream pointers\n");
6305 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
6306 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
6307 FINDOUT: should changes.streamSource[StreamNumber] be set ?
6309 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6310 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
6311 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
6312 This->updateStateBlock->streamSource[streamNumber] = 0;
6313 /* Set changed flag? */
6316 if (This->stateBlock != NULL ) { /* only happens if there is an error in the application, or on reset/release (because we don't manage internal tracking properly) */
6317 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
6318 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
6319 This->stateBlock->streamSource[streamNumber] = 0;
6322 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
6323 else { /* This shouldn't happen */
6324 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
6331 case D3DRTYPE_INDEXBUFFER:
6332 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
6333 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6334 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6335 This->updateStateBlock->pIndexData = NULL;
6338 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
6339 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6340 This->stateBlock->pIndexData = NULL;
6346 FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
6351 /* Remove the resoruce from the resourceStore */
6352 IWineD3DDeviceImpl_RemoveResource(iface, resource);
6354 TRACE("Resource released\n");
6359 /** This function is to be called by the swapchain when it is released and it's ref = 0
6360 *****************************************************/
6361 void WINAPI IWineD3DDeviceImpl_SwapChainReleased(IWineD3DDevice *iface, IWineD3DSwapChain *swapChain){
6362 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6363 SwapChainList **nextSwapchain;
6364 nextSwapchain = &This->swapchains;
6366 /* Check to see if the swapchian is being used as the render target */
6367 if (This->renderTarget != NULL) {
6368 IWineD3DSurface *swapchainBackBuffer;
6370 IWineD3DSwapChain_GetBackBuffer(swapChain, 0 ,( D3DBACKBUFFER_TYPE) 0, &swapchainBackBuffer);
6371 if (This->renderTarget == swapchainBackBuffer) {
6372 /* Don't know what to do, so warn and carry on as usual (which in this case leaves the renderterget in limbo) */
6373 FIXME("Atempting to release a swapchain that is currently beuing used as a render target, behaviour is undefined\n");
6377 /* Go through the swapchain list and try to find the swapchain being released */
6378 while(*nextSwapchain != NULL && (*nextSwapchain)->swapchain != swapChain) {
6379 nextSwapchain = &(*nextSwapchain)->next;
6382 /* Check to see if we found the swapchain */
6383 if (NULL != *nextSwapchain) {
6384 /* We found the swapchain so remove it from the list */
6385 TRACE("(%p) releasing swapchain(%p)\n", iface, swapChain);
6386 HeapFree(GetProcessHeap(), 0 , *nextSwapchain);
6387 *nextSwapchain = (*nextSwapchain)->next;
6389 /* We didn't find the swapchain on the list, this can only heppen because of a programming error in wined3d */
6390 FIXME("(%p) Attempting to release a swapchain (%p) that hasn't been stored\n", iface, swapChain);
6393 TRACE("swapchain (%p) released\n", swapChain);
6397 /**********************************************************
6398 * IWineD3DDevice VTbl follows
6399 **********************************************************/
6401 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
6403 /*** IUnknown methods ***/
6404 IWineD3DDeviceImpl_QueryInterface,
6405 IWineD3DDeviceImpl_AddRef,
6406 IWineD3DDeviceImpl_Release,
6407 /*** IWineD3DDevice methods ***/
6408 IWineD3DDeviceImpl_GetParent,
6409 /*** Creation methods**/
6410 IWineD3DDeviceImpl_CreateVertexBuffer,
6411 IWineD3DDeviceImpl_CreateIndexBuffer,
6412 IWineD3DDeviceImpl_CreateStateBlock,
6413 IWineD3DDeviceImpl_CreateSurface,
6414 IWineD3DDeviceImpl_CreateTexture,
6415 IWineD3DDeviceImpl_CreateVolumeTexture,
6416 IWineD3DDeviceImpl_CreateVolume,
6417 IWineD3DDeviceImpl_CreateCubeTexture,
6418 IWineD3DDeviceImpl_CreateQuery,
6419 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
6420 IWineD3DDeviceImpl_CreateVertexDeclaration,
6421 IWineD3DDeviceImpl_CreateVertexShader,
6422 IWineD3DDeviceImpl_CreatePixelShader,
6423 /*** Odd functions **/
6424 IWineD3DDeviceImpl_EvictManagedResources,
6425 IWineD3DDeviceImpl_GetAvailableTextureMem,
6426 IWineD3DDeviceImpl_GetBackBuffer,
6427 IWineD3DDeviceImpl_GetCreationParameters,
6428 IWineD3DDeviceImpl_GetDeviceCaps,
6429 IWineD3DDeviceImpl_GetDirect3D,
6430 IWineD3DDeviceImpl_GetDisplayMode,
6431 IWineD3DDeviceImpl_GetNumberOfSwapChains,
6432 IWineD3DDeviceImpl_GetRasterStatus,
6433 IWineD3DDeviceImpl_GetSwapChain,
6434 IWineD3DDeviceImpl_Reset,
6435 IWineD3DDeviceImpl_SetDialogBoxMode,
6436 IWineD3DDeviceImpl_SetCursorProperties,
6437 IWineD3DDeviceImpl_SetCursorPosition,
6438 IWineD3DDeviceImpl_ShowCursor,
6439 IWineD3DDeviceImpl_TestCooperativeLevel,
6440 /*** Getters and setters **/
6441 IWineD3DDeviceImpl_SetClipPlane,
6442 IWineD3DDeviceImpl_GetClipPlane,
6443 IWineD3DDeviceImpl_SetClipStatus,
6444 IWineD3DDeviceImpl_GetClipStatus,
6445 IWineD3DDeviceImpl_SetCurrentTexturePalette,
6446 IWineD3DDeviceImpl_GetCurrentTexturePalette,
6447 IWineD3DDeviceImpl_SetDepthStencilSurface,
6448 IWineD3DDeviceImpl_GetDepthStencilSurface,
6449 IWineD3DDeviceImpl_SetFVF,
6450 IWineD3DDeviceImpl_GetFVF,
6451 IWineD3DDeviceImpl_SetGammaRamp,
6452 IWineD3DDeviceImpl_GetGammaRamp,
6453 IWineD3DDeviceImpl_SetIndices,
6454 IWineD3DDeviceImpl_GetIndices,
6455 IWineD3DDeviceImpl_SetLight,
6456 IWineD3DDeviceImpl_GetLight,
6457 IWineD3DDeviceImpl_SetLightEnable,
6458 IWineD3DDeviceImpl_GetLightEnable,
6459 IWineD3DDeviceImpl_SetMaterial,
6460 IWineD3DDeviceImpl_GetMaterial,
6461 IWineD3DDeviceImpl_SetNPatchMode,
6462 IWineD3DDeviceImpl_GetNPatchMode,
6463 IWineD3DDeviceImpl_SetPaletteEntries,
6464 IWineD3DDeviceImpl_GetPaletteEntries,
6465 IWineD3DDeviceImpl_SetPixelShader,
6466 IWineD3DDeviceImpl_GetPixelShader,
6467 IWineD3DDeviceImpl_SetPixelShaderConstantB,
6468 IWineD3DDeviceImpl_GetPixelShaderConstantB,
6469 IWineD3DDeviceImpl_SetPixelShaderConstantI,
6470 IWineD3DDeviceImpl_GetPixelShaderConstantI,
6471 IWineD3DDeviceImpl_SetPixelShaderConstantF,
6472 IWineD3DDeviceImpl_GetPixelShaderConstantF,
6473 IWineD3DDeviceImpl_SetPixelShaderConstantN,
6474 IWineD3DDeviceImpl_SetRenderState,
6475 IWineD3DDeviceImpl_GetRenderState,
6476 IWineD3DDeviceImpl_SetRenderTarget,
6477 IWineD3DDeviceImpl_GetRenderTarget,
6478 IWineD3DDeviceImpl_SetSamplerState,
6479 IWineD3DDeviceImpl_GetSamplerState,
6480 IWineD3DDeviceImpl_SetScissorRect,
6481 IWineD3DDeviceImpl_GetScissorRect,
6482 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
6483 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
6484 IWineD3DDeviceImpl_SetStreamSource,
6485 IWineD3DDeviceImpl_GetStreamSource,
6486 IWineD3DDeviceImpl_SetStreamSourceFreq,
6487 IWineD3DDeviceImpl_GetStreamSourceFreq,
6488 IWineD3DDeviceImpl_SetTexture,
6489 IWineD3DDeviceImpl_GetTexture,
6490 IWineD3DDeviceImpl_SetTextureStageState,
6491 IWineD3DDeviceImpl_GetTextureStageState,
6492 IWineD3DDeviceImpl_SetTransform,
6493 IWineD3DDeviceImpl_GetTransform,
6494 IWineD3DDeviceImpl_SetVertexDeclaration,
6495 IWineD3DDeviceImpl_GetVertexDeclaration,
6496 IWineD3DDeviceImpl_SetVertexShader,
6497 IWineD3DDeviceImpl_GetVertexShader,
6498 IWineD3DDeviceImpl_SetVertexShaderConstantB,
6499 IWineD3DDeviceImpl_GetVertexShaderConstantB,
6500 IWineD3DDeviceImpl_SetVertexShaderConstantI,
6501 IWineD3DDeviceImpl_GetVertexShaderConstantI,
6502 IWineD3DDeviceImpl_SetVertexShaderConstantF,
6503 IWineD3DDeviceImpl_GetVertexShaderConstantF,
6504 IWineD3DDeviceImpl_SetVertexShaderConstantN,
6505 IWineD3DDeviceImpl_SetViewport,
6506 IWineD3DDeviceImpl_GetViewport,
6507 IWineD3DDeviceImpl_MultiplyTransform,
6508 IWineD3DDeviceImpl_ValidateDevice,
6509 IWineD3DDeviceImpl_ProcessVertices,
6510 /*** State block ***/
6511 IWineD3DDeviceImpl_BeginStateBlock,
6512 IWineD3DDeviceImpl_EndStateBlock,
6513 /*** Scene management ***/
6514 IWineD3DDeviceImpl_BeginScene,
6515 IWineD3DDeviceImpl_EndScene,
6516 IWineD3DDeviceImpl_Present,
6517 IWineD3DDeviceImpl_Clear,
6519 IWineD3DDeviceImpl_DrawPrimitive,
6520 IWineD3DDeviceImpl_DrawIndexedPrimitive,
6521 IWineD3DDeviceImpl_DrawPrimitiveUP,
6522 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
6523 IWineD3DDeviceImpl_DrawRectPatch,
6524 IWineD3DDeviceImpl_DrawTriPatch,
6525 IWineD3DDeviceImpl_DeletePatch,
6526 IWineD3DDeviceImpl_ColorFill,
6527 IWineD3DDeviceImpl_UpdateTexture,
6528 IWineD3DDeviceImpl_UpdateSurface,
6529 IWineD3DDeviceImpl_StretchRect,
6530 IWineD3DDeviceImpl_GetRenderTargetData,
6531 IWineD3DDeviceImpl_GetFrontBufferData,
6532 /*** Internal use IWineD3DDevice methods ***/
6533 IWineD3DDeviceImpl_SetupTextureStates,
6534 /*** object tracking ***/
6535 IWineD3DDeviceImpl_SwapChainReleased,
6536 IWineD3DDeviceImpl_ResourceReleased
6540 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
6541 WINED3DRS_ALPHABLENDENABLE ,
6542 WINED3DRS_ALPHAFUNC ,
6543 WINED3DRS_ALPHAREF ,
6544 WINED3DRS_ALPHATESTENABLE ,
6546 WINED3DRS_COLORWRITEENABLE ,
6547 WINED3DRS_DESTBLEND ,
6548 WINED3DRS_DITHERENABLE ,
6549 WINED3DRS_FILLMODE ,
6550 WINED3DRS_FOGDENSITY ,
6552 WINED3DRS_FOGSTART ,
6553 WINED3DRS_LASTPIXEL ,
6554 WINED3DRS_SHADEMODE ,
6555 WINED3DRS_SRCBLEND ,
6556 WINED3DRS_STENCILENABLE ,
6557 WINED3DRS_STENCILFAIL ,
6558 WINED3DRS_STENCILFUNC ,
6559 WINED3DRS_STENCILMASK ,
6560 WINED3DRS_STENCILPASS ,
6561 WINED3DRS_STENCILREF ,
6562 WINED3DRS_STENCILWRITEMASK ,
6563 WINED3DRS_STENCILZFAIL ,
6564 WINED3DRS_TEXTUREFACTOR ,
6575 WINED3DRS_ZWRITEENABLE
6578 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
6579 WINED3DTSS_ADDRESSW ,
6580 WINED3DTSS_ALPHAARG0 ,
6581 WINED3DTSS_ALPHAARG1 ,
6582 WINED3DTSS_ALPHAARG2 ,
6583 WINED3DTSS_ALPHAOP ,
6584 WINED3DTSS_BUMPENVLOFFSET ,
6585 WINED3DTSS_BUMPENVLSCALE ,
6586 WINED3DTSS_BUMPENVMAT00 ,
6587 WINED3DTSS_BUMPENVMAT01 ,
6588 WINED3DTSS_BUMPENVMAT10 ,
6589 WINED3DTSS_BUMPENVMAT11 ,
6590 WINED3DTSS_COLORARG0 ,
6591 WINED3DTSS_COLORARG1 ,
6592 WINED3DTSS_COLORARG2 ,
6593 WINED3DTSS_COLOROP ,
6594 WINED3DTSS_RESULTARG ,
6595 WINED3DTSS_TEXCOORDINDEX ,
6596 WINED3DTSS_TEXTURETRANSFORMFLAGS
6599 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
6600 WINED3DSAMP_ADDRESSU ,
6601 WINED3DSAMP_ADDRESSV ,
6602 WINED3DSAMP_ADDRESSW ,
6603 WINED3DSAMP_BORDERCOLOR ,
6604 WINED3DSAMP_MAGFILTER ,
6605 WINED3DSAMP_MINFILTER ,
6606 WINED3DSAMP_MIPFILTER ,
6607 WINED3DSAMP_MIPMAPLODBIAS ,
6608 WINED3DSAMP_MAXMIPLEVEL ,
6609 WINED3DSAMP_MAXANISOTROPY ,
6610 WINED3DSAMP_SRGBTEXTURE ,
6611 WINED3DSAMP_ELEMENTINDEX
6614 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
6616 WINED3DRS_AMBIENTMATERIALSOURCE ,
6617 WINED3DRS_CLIPPING ,
6618 WINED3DRS_CLIPPLANEENABLE ,
6619 WINED3DRS_COLORVERTEX ,
6620 WINED3DRS_DIFFUSEMATERIALSOURCE ,
6621 WINED3DRS_EMISSIVEMATERIALSOURCE ,
6622 WINED3DRS_FOGDENSITY ,
6624 WINED3DRS_FOGSTART ,
6625 WINED3DRS_FOGTABLEMODE ,
6626 WINED3DRS_FOGVERTEXMODE ,
6627 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
6628 WINED3DRS_LIGHTING ,
6629 WINED3DRS_LOCALVIEWER ,
6630 WINED3DRS_MULTISAMPLEANTIALIAS ,
6631 WINED3DRS_MULTISAMPLEMASK ,
6632 WINED3DRS_NORMALIZENORMALS ,
6633 WINED3DRS_PATCHEDGESTYLE ,
6634 WINED3DRS_POINTSCALE_A ,
6635 WINED3DRS_POINTSCALE_B ,
6636 WINED3DRS_POINTSCALE_C ,
6637 WINED3DRS_POINTSCALEENABLE ,
6638 WINED3DRS_POINTSIZE ,
6639 WINED3DRS_POINTSIZE_MAX ,
6640 WINED3DRS_POINTSIZE_MIN ,
6641 WINED3DRS_POINTSPRITEENABLE ,
6642 WINED3DRS_RANGEFOGENABLE ,
6643 WINED3DRS_SPECULARMATERIALSOURCE ,
6644 WINED3DRS_TWEENFACTOR ,
6645 WINED3DRS_VERTEXBLEND
6648 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
6649 WINED3DTSS_TEXCOORDINDEX ,
6650 WINED3DTSS_TEXTURETRANSFORMFLAGS
6653 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
6654 WINED3DSAMP_DMAPOFFSET