2 * IWineD3DDevice implementation
4 * Copyright 2002-2005 Jason Edmeades
5 * Copyright 2003-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "wined3d_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
28 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
30 /* x11drv GDI escapes */
31 #define X11DRV_ESCAPE 6789
32 enum x11drv_escape_codes
34 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
35 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
36 X11DRV_GET_FONT, /* get current X font for a DC */
39 /* retrieve the X display to use on a given DC */
40 inline static Display *get_display( HDC hdc )
43 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
45 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
46 sizeof(display), (LPSTR)&display )) display = NULL;
50 /* Memory tracking and object counting */
51 static unsigned int emulated_textureram = 64*1024*1024;
53 /* TODO: setup some flags in the regestry to enable, disable pbuffer support */
54 /* enable pbuffer support for offscreen textures */
55 BOOL pbuffer_support = FALSE;
56 /* allocate one pbuffer per surface */
57 BOOL pbuffer_per_surface = FALSE;
59 /* static function declarations */
60 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
62 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type);
65 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return D3DERR_OUTOFVIDEOMEMORY;}
67 #define D3DCREATEOBJECTINSTANCE(object, type) { \
68 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
69 D3DMEMCHECK(object, pp##type); \
70 object->lpVtbl = &IWineD3D##type##_Vtbl; \
71 object->wineD3DDevice = This; \
72 object->parent = parent; \
74 *pp##type = (IWineD3D##type *) object; \
77 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
78 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
79 D3DMEMCHECK(object, pp##type); \
80 object->lpVtbl = &IWineD3D##type##_Vtbl; \
81 object->resource.wineD3DDevice = This; \
82 object->resource.parent = parent; \
83 object->resource.resourceType = d3dtype; \
84 object->resource.ref = 1; \
85 object->resource.pool = Pool; \
86 object->resource.format = Format; \
87 object->resource.usage = Usage; \
88 object->resource.size = _size; \
89 /* Check that we have enough video ram left */ \
90 if (Pool == D3DPOOL_DEFAULT) { \
91 if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
92 WARN("Out of 'bogus' video memory\n"); \
93 HeapFree(GetProcessHeap(), 0, object); \
95 return D3DERR_OUTOFVIDEOMEMORY; \
97 globalChangeGlRam(_size); \
99 object->resource.allocatedMemory = (0 == _size ? NULL : Pool == D3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
100 if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != D3DPOOL_DEFAULT) { \
101 FIXME("Out of memory!\n"); \
102 HeapFree(GetProcessHeap(), 0, object); \
104 return D3DERR_OUTOFVIDEOMEMORY; \
106 *pp##type = (IWineD3D##type *) object; \
107 IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
108 TRACE("(%p) : Created resource %p\n", This, object); \
111 #define D3DINITILIZEBASETEXTURE(_basetexture) { \
112 _basetexture.levels = Levels; \
113 _basetexture.filterType = (Usage & D3DUSAGE_AUTOGENMIPMAP) ? D3DTEXF_LINEAR : D3DTEXF_NONE; \
114 _basetexture.LOD = 0; \
115 _basetexture.dirty = TRUE; \
118 /**********************************************************
119 * Global variable / Constants follow
120 **********************************************************/
121 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
123 /**********************************************************
124 * Utility functions follow
125 **********************************************************/
126 /* Convert the D3DLIGHT properties into equivalent gl lights */
127 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
130 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
131 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
133 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
134 glMatrixMode(GL_MODELVIEW);
136 glLoadMatrixf((float *)&This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
139 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
140 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
141 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
142 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
143 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
144 checkGLcall("glLightfv");
147 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
148 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
149 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
150 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
151 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
152 checkGLcall("glLightfv");
155 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
156 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
157 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
158 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
159 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
160 checkGLcall("glLightfv");
162 /* Attenuation - Are these right? guessing... */
163 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
164 checkGLcall("glLightf");
165 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
166 checkGLcall("glLightf");
168 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) != 0) {
169 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
171 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
174 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
175 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
176 checkGLcall("glLightf");
178 switch (lightInfo->OriginalParms.Type) {
181 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
182 checkGLcall("glLightfv");
183 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
184 checkGLcall("glLightf");
190 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
191 checkGLcall("glLightfv");
193 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
194 checkGLcall("glLightfv");
195 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
196 checkGLcall("glLightf");
197 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
198 checkGLcall("glLightf");
202 case D3DLIGHT_DIRECTIONAL:
204 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
205 checkGLcall("glLightfv");
206 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
207 checkGLcall("glLightf");
208 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
209 checkGLcall("glLightf");
213 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
216 /* Restore the modelview matrix */
220 /* Apply the current values to the specified texture stage */
221 void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Sampler, DWORD Flags) {
222 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
230 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
231 clamping, MIPLOD, etc. This will work for up to 16 samplers.
234 if (Sampler >= GL_LIMITS(samplers)) {
235 FIXME("Trying to set the state of more samplers %ld than are supported %d by this openGL implementation\n", Sampler, GL_LIMITS(samplers));
238 VTRACE(("Activating appropriate texture state %ld\n", Sampler));
239 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
241 GLACTIVETEXTURE(Sampler);
243 /* Could we use bindTexture and then apply the states instead of GLACTIVETEXTURE */
244 } else if (Sampler > 0) {
245 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
249 /* TODO: change this to a lookup table
250 LOOKUP_TEXTURE_STATES lists all texture states that should be applied.
251 LOOKUP_CONTEXT_SATES list all context applicable states that can be applied
252 etc.... it's a lot cleaner, quicker and possibly easier to maintain than running a switch and setting a skip flag...
253 especially when there are a number of groups of states. */
255 TRACE("-----------------------> Updating the texture at Sampler %ld to have new texture state information\n", Sampler);
257 /* The list of states not to apply is a big as the list of states to apply, so it makes sense to produce an inclusive list */
258 #define APPLY_STATE(_state) IWineD3DDeviceImpl_ApplyTextureUnitState(iface, Sampler, _state)
259 /* these are the only two supported states that need to be applied */
260 APPLY_STATE(WINED3DTSS_TEXCOORDINDEX);
261 APPLY_STATE(WINED3DTSS_TEXTURETRANSFORMFLAGS);
262 #if 0 /* not supported at the moment */
263 APPLY_STATE(WINED3DTSS_BUMPENVMAT00);
264 APPLY_STATE(WINED3DTSS_BUMPENVMAT01);
265 APPLY_STATE(WINED3DTSS_BUMPENVMAT10);
266 APPLY_STATE(WINED3DTSS_BUMPENVMAT11);
267 APPLY_STATE(WINED3DTSS_BUMPENVLSCALE);
268 APPLY_STATE(WINED3DTSS_BUMPENVLOFFSET);
269 APPLY_STATE(WINED3DTSS_RESULTARG);
270 APPLY_STATE(WINED3DTSS_CONSTANT);
272 /* a quick sanity check in case someone forgot to update this function */
273 if (WINED3D_HIGHEST_TEXTURE_STATE > WINED3DTSS_CONSTANT) {
274 FIXME("(%p) : There are more texture states than expected, update device.c to match\n", This);
278 /* apply any sampler states that always need applying */
279 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
280 tmpvalue.d = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPMAPLODBIAS];
281 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
282 GL_TEXTURE_LOD_BIAS_EXT,
284 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
287 /* Note the D3DRS value applies to all textures, but GL has one
288 * per texture, so apply it now ready to be used!
290 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
291 /* Set the default alpha blend color */
292 glBlendColor(col[0], col[1], col[2], col[3]);
293 checkGLcall("glBlendColor");
295 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
296 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
297 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
299 /* TODO: NV_POINT_SPRITE */
300 if (GL_SUPPORT(ARB_POINT_SPRITE)) {
301 if (This->stateBlock->renderState[WINED3DRS_POINTSPRITEENABLE] != FALSE) {
302 /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
303 glDisable(GL_POINT_SMOOTH);
305 /* Centre the texture on the vertex */
306 VTRACE("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
307 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
309 VTRACE("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
310 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
311 checkGLcall("glTexEnvf(...)");
312 VTRACE("glEnable( GL_POINT_SPRITE_ARB )\n");
313 glEnable( GL_POINT_SPRITE_ARB );
314 checkGLcall("glEnable(...)");
316 VTRACE("glDisable( GL_POINT_SPRITE_ARB )\n");
317 glDisable( GL_POINT_SPRITE_ARB );
318 checkGLcall("glEnable(...)");
322 TRACE("-----------------------> Updated the texture at Sampler %ld to have new texture state information\n", Sampler);
325 /**********************************************************
326 * IUnknown parts follows
327 **********************************************************/
329 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
331 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
332 /* FIXME: This needs to extend an IWineD3DBaseObject */
334 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
335 if (IsEqualGUID(riid, &IID_IUnknown)
336 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
337 IUnknown_AddRef(iface);
342 return E_NOINTERFACE;
345 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
346 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
347 ULONG refCount = InterlockedIncrement(&This->ref);
349 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
353 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
354 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
355 ULONG refCount = InterlockedDecrement(&This->ref);
357 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
360 /* TODO: Clean up all the surfaces and textures! */
361 /* FIXME: Create targets and state blocks in d3d8 */
362 if (((IWineD3DImpl *)This->wineD3D)->dxVersion > 8) { /*We don't create a state block in d3d8 yet*/
363 /* NOTE: You must release the parent if the object was created via a callback
364 ** ***************************/
365 /* TODO: this is exactly the same as required by _Reset.., so at some point we need to move the code so that is can be called by reset add release... */
366 /* Release all of the swapchains, except the implicit swapchain */
367 IUnknown* stencilBufferParent;
368 IUnknown* swapChainParent;
370 /* NOTE: Don't release swapchain 0 here, it's 'special' */
371 SwapChainList *nextSwapchain = This->swapchains;
372 if (nextSwapchain != NULL) {
373 nextSwapchain = nextSwapchain->next;
375 WARN("Expected to find the implicit swapchain\n");
378 /* release all the other swapchains */
379 while (nextSwapchain != NULL) {
380 SwapChainList *prevSwapchain = nextSwapchain;
381 nextSwapchain = nextSwapchain->next;
382 IWineD3DSwapChain_Release(prevSwapchain->swapchain);
383 /* NOTE: no need to free the list element, it will be done by the release callback
384 HeapFree(GetProcessHeap(), 0, prevSwapchain); */
386 /* Release the buffers (with sanity checks)*/
387 if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
388 if(This->depthStencilBuffer != This->stencilBufferTarget)
389 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
391 This->stencilBufferTarget = NULL;
393 if(IWineD3DSurface_Release(This->renderTarget) >0){
394 /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
396 This->renderTarget = NULL;
398 IWineD3DSurface_GetParent(This->depthStencilBuffer, &stencilBufferParent);
399 IUnknown_Release(stencilBufferParent); /* once for the get parent */
400 if(IUnknown_Release(stencilBufferParent) >0){ /* the second time for when it was created */
401 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
403 This->depthStencilBuffer = NULL;
405 /* Release the update stateblock */
406 if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){
407 if(This->updateStateBlock != This->stateBlock)
408 FIXME("(%p) Something's still holding the Update stateblock\n",This);
410 This->updateStateBlock = NULL;
411 { /* because were not doing proper internal refcounts releasing the primary state block
412 causes recursion with the extra checks in ResourceReleased, to avoid this we have
413 to set this->stateBlock = NULL; first */
414 IWineD3DStateBlock *stateBlock = (IWineD3DStateBlock *)This->stateBlock;
415 This->stateBlock = NULL;
417 /* Release the stateblock */
418 if(IWineD3DStateBlock_Release(stateBlock) > 0){
419 FIXME("(%p) Something's still holding the Update stateblock\n",This);
423 if (This->swapchains != NULL) {
424 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
425 IWineD3DSwapChain_GetParent(This->swapchains->swapchain, &swapChainParent);
426 IUnknown_Release(swapChainParent); /* once for the get parent */
427 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
428 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
432 if (This->resources != NULL ) {
433 FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This);
435 #if 0 /* TODO: Dump a list of all the resources still bound */
436 dumpResources(This->resources);
438 /* TODO: set the resources to a lost state */
442 IWineD3D_Release(This->wineD3D);
443 This->wineD3D = NULL;
444 HeapFree(GetProcessHeap(), 0, This);
445 TRACE("Freed device %p\n", This);
451 /**********************************************************
452 * IWineD3DDevice implementation follows
453 **********************************************************/
454 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
455 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
456 *pParent = This->parent;
457 IUnknown_AddRef(This->parent);
461 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
462 DWORD FVF, D3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
464 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
465 IWineD3DVertexBufferImpl *object;
466 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
467 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, D3DRTYPE_VERTEXBUFFER, Size)
470 if (Pool == D3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
471 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
475 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
476 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
481 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
482 WINED3DFORMAT Format, D3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
483 HANDLE *sharedHandle, IUnknown *parent) {
484 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
485 IWineD3DIndexBufferImpl *object;
486 TRACE("(%p) Creating index buffer\n", This);
488 /* Allocate the storage for the device */
489 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,D3DRTYPE_INDEXBUFFER, Length)
492 if (Pool == D3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
493 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
496 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
497 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
498 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
503 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
505 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
506 IWineD3DStateBlockImpl *object;
509 D3DCREATEOBJECTINSTANCE(object, StateBlock)
510 object->blockType = Type;
512 /* Special case - Used during initialization to produce a placeholder stateblock
513 so other functions called can update a state block */
514 if (Type == WINED3DSBT_INIT) {
515 /* Don't bother increasing the reference count otherwise a device will never
516 be freed due to circular dependencies */
520 /* Otherwise, might as well set the whole state block to the appropriate values */
521 if ( This->stateBlock != NULL) {
522 memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
524 memset(object->streamFreq, 1, sizeof(object->streamFreq));
527 /* Reset the ref and type after kludging it */
528 object->wineD3DDevice = This;
530 object->blockType = Type;
532 TRACE("Updating changed flags appropriate for type %d\n", Type);
534 if (Type == WINED3DSBT_ALL) {
536 TRACE("ALL => Pretend everything has changed\n");
537 memset(&object->changed, TRUE, sizeof(This->stateBlock->changed));
538 } else if (Type == WINED3DSBT_PIXELSTATE) {
540 TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
541 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
543 object->changed.pixelShader = TRUE;
545 /* Pixel Shader Constants */
546 for (i = 0; i < MAX_PSHADER_CONSTANTS; ++i) {
547 object->changed.pixelShaderConstants[i] = TRUE;
549 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
550 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
552 for (j = 0; j < GL_LIMITS(textures); j++) {
553 for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
554 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
557 for (j = 0 ; j < 16; j++) {
558 for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
560 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
564 } else if (Type == WINED3DSBT_VERTEXSTATE) {
566 TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
567 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
569 object->changed.vertexShader = TRUE;
571 /* Vertex Shader Constants */
572 for (i = 0; i < MAX_VSHADER_CONSTANTS; ++i) {
573 object->changed.vertexShaderConstants[i] = TRUE;
575 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
576 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
578 for (j = 0; j < GL_LIMITS(textures); j++) {
579 for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
580 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
583 for (j = 0 ; j < 16; j++){
584 for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
585 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
589 /* Duplicate light chain */
591 PLIGHTINFOEL *src = NULL;
592 PLIGHTINFOEL *dst = NULL;
593 PLIGHTINFOEL *newEl = NULL;
594 src = This->stateBlock->lights;
595 object->lights = NULL;
599 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
600 if (newEl == NULL) return D3DERR_OUTOFVIDEOMEMORY;
601 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
603 newEl->changed = TRUE;
604 newEl->enabledChanged = TRUE;
606 object->lights = newEl;
617 FIXME("Unrecognized state block type %d\n", Type);
620 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
625 /* ************************************
627 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
630 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
632 If this flag is set, the contents of the depth stencil buffer will be invalid after calling either IDirect3DDevice9::Present or IDirect3DDevice9::SetDepthStencilSurface with a different depth surface.
634 ******************************** */
636 HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height, WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **ppSurface,D3DRESOURCETYPE Type, DWORD Usage, D3DPOOL Pool, D3DMULTISAMPLE_TYPE MultiSample ,DWORD MultisampleQuality, HANDLE* pSharedHandle, IUnknown *parent) {
637 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
638 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
639 unsigned int pow2Width, pow2Height;
640 unsigned int Size = 1;
641 TRACE("(%p) Create surface\n",This);
643 /** FIXME: Check ranges on the inputs are valid
646 * [in] Quality level. The valid range is between zero and one less than the level
647 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
648 * Passing a larger value returns the error D3DERR_INVALIDCALL. The MultisampleQuality
649 * values of paired render targets, depth stencil surfaces, and the MultiSample type
651 *******************************/
656 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
658 * If this flag is set, the contents of the depth stencil buffer will be
659 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
660 * with a different depth surface.
662 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
663 ***************************/
665 if(MultisampleQuality < 0) {
666 FIXME("Invalid multisample level %ld\n", MultisampleQuality);
667 return D3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
670 if(MultisampleQuality > 0) {
671 FIXME("MultisampleQuality set to %ld, substituting 0\n", MultisampleQuality);
672 MultisampleQuality=0;
675 /** FIXME: Check that the format is supported
677 *******************************/
679 /* Non-power2 support */
681 /* Find the nearest pow2 match */
682 pow2Width = pow2Height = 1;
683 while (pow2Width < Width) pow2Width <<= 1;
684 while (pow2Height < Height) pow2Height <<= 1;
686 if (pow2Width > Width || pow2Height > Height) {
687 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
688 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
689 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
690 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
691 This, Width, Height);
692 return D3DERR_NOTAVAILABLE;
696 /** Check against the maximum texture sizes supported by the video card **/
697 if (pow2Width > GL_LIMITS(texture_size) || pow2Height > GL_LIMITS(texture_size)) {
698 /* one of three options
699 1: Do the same as we do with nonpow 2 and scale the texture, (any texture ops would require the texture to be scaled which is potentially slow)
700 2: Set the texture to the maxium size (bad idea)
701 3: WARN and return D3DERR_NOTAVAILABLE;
703 WARN("(%p) Application requested a surface w %d, h %d, but the graphics card only supports %d\n", This, Width, Height, GL_LIMITS(texture_size));
704 return D3DERR_NOTAVAILABLE;
709 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
710 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
712 *********************************/
713 if (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 the and initilise 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 D3DINITILIZEBASETEXTURE(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 D3DINITILIZEBASETEXTURE(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 D3DINITILIZEBASETEXTURE(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 it'd 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 their 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;
1563 HRESULT hr = D3DERR_INVALIDCALL;
1564 swapchain = This->swapchains;
1565 TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1568 TRACE("(%p) Finding swapchain %d\n", This, iSwapChain);
1569 while (iSwapChain > 0 && swapchain != NULL) {
1570 swapchain = swapchain->next;
1574 if (iSwapChain > 0 || swapchain == NULL) {
1575 FIXME("(%p) Unable to find swapchain %d\n", This, iSwapChain);
1578 /** TODO: move off to a linkesList implementation **/
1579 *pSwapChain = swapchain->swapchain;
1580 IWineD3DSwapChain_AddRef(*pSwapChain);
1584 TRACE("(%p) returning %p\n", This, *pSwapChain);
1588 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
1589 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1591 FIXME("(%p) : Stub\n",This);
1597 * Vertex Declaration
1599 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1600 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1601 IWineD3DVertexDeclarationImpl *object = NULL;
1602 HRESULT hr = D3D_OK;
1603 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1604 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1607 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1612 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1613 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DVertexShader** ppVertexShader, IUnknown *parent) {
1614 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1615 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1616 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1618 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1619 IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1624 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DPixelShader** ppPixelShader, IUnknown *parent) {
1625 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1626 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1628 D3DCREATEOBJECTINSTANCE(object, PixelShader)
1630 object->function = pFunction;
1631 #else /* TODO: pixel shader set function */
1632 IWineD3DPixelShaderImpl_SetFuction(*ppPixelShader, pFunction);
1634 FIXME("(%p) : STUB: Created Pixel shader %p\n", This, ppPixelShader);
1640 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice* iface, IWineD3D** ppD3D) {
1641 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1642 *ppD3D= This->wineD3D;
1643 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1644 IWineD3D_AddRef(*ppD3D);
1648 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1649 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1650 * Into the video ram as possible and seeing how many fit
1651 * you can also get the correct initial value from via X and ATI's driver
1652 *******************/
1653 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1654 static BOOL showfixmes = TRUE;
1656 FIXME("(%p) : stub, emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1657 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1660 TRACE("(%p) : emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1661 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1662 /* videomemory is simulated videomemory + AGP memory left */
1663 return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1671 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1672 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1673 HRESULT hr = D3D_OK;
1675 /* Update the current state block */
1676 This->updateStateBlock->fvf = fvf;
1677 This->updateStateBlock->changed.fvf = TRUE;
1678 This->updateStateBlock->set.fvf = TRUE;
1680 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1683 /* clear down the vertex declaration
1684 NOTE: Axis and Allies doesn't work properly otherwise
1685 (may be a stateblock problem though!)
1687 hr = IWineD3DDevice_SetVertexDeclaration(iface, NULL);
1694 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1695 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1696 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1697 *pfvf = This->stateBlock->fvf;
1702 * Get / Set Stream Source
1704 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1705 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1706 IWineD3DVertexBuffer *oldSrc;
1708 /**TODO: instance and index data, see
1709 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1711 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
1714 /* D3d9 only, but shouldn't hurt d3d8 */
1717 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1719 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1720 FIXME("stream index data not supported\n");
1722 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1723 FIXME("stream instance data not supported\n");
1727 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1729 if (StreamNumber >= MAX_STREAMS) {
1730 WARN("Stream out of range %d\n", StreamNumber);
1731 return D3DERR_INVALIDCALL;
1734 oldSrc = This->stateBlock->streamSource[StreamNumber];
1735 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1737 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
1738 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
1739 This->updateStateBlock->streamStride[StreamNumber] = Stride;
1740 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
1741 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
1742 This->updateStateBlock->streamFlags[StreamNumber] = streamFlags;
1744 /* Handle recording of state blocks */
1745 if (This->isRecordingState) {
1746 TRACE("Recording... not performing anything\n");
1750 /* Not recording... */
1751 /* Need to do a getParent and pass the reffs up */
1752 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
1753 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
1754 so for now, just count internally */
1755 if (pStreamData != NULL) {
1756 IUnknown *newVertexBufferParent;
1757 /* GetParent will add a ref, so leave it hanging until the vertex buffer is cleared */
1758 IWineD3DVertexBuffer_GetParent(pStreamData, &newVertexBufferParent);
1760 if (oldSrc != NULL) {
1761 IUnknown *oldVertexBufferParent;
1762 IWineD3DVertexBuffer_GetParent(oldSrc, &oldVertexBufferParent);
1763 IUnknown_Release(oldVertexBufferParent);
1764 IUnknown_Release(oldVertexBufferParent);
1770 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
1771 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1774 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
1775 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
1778 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1780 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1781 FIXME("stream index data not supported\n");
1783 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1784 FIXME("stream instance data not supported\n");
1788 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1790 if (StreamNumber >= MAX_STREAMS) {
1791 WARN("Stream out of range %d\n", StreamNumber);
1792 return D3DERR_INVALIDCALL;
1794 *pStream = This->stateBlock->streamSource[StreamNumber];
1795 *pStride = This->stateBlock->streamStride[StreamNumber];
1796 *pOffset = This->stateBlock->streamOffset[StreamNumber];
1798 if (*pStream == NULL) {
1799 FIXME("Attempting to get an empty stream %d, returning D3DERR_INVALIDCALL\n", StreamNumber);
1800 return D3DERR_INVALIDCALL;
1803 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
1807 /*Should be quite easy, just an extension of vertexdata
1809 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1811 The divider is a bit odd though
1813 VertexOffset = StartVertex / Divider * StreamStride +
1814 VertexIndex / Divider * StreamStride + StreamOffset
1817 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
1818 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1820 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
1821 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (D3DSTREAMSOURCE_INSTANCEDATA | D3DSTREAMSOURCE_INDEXEDDATA );
1823 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
1824 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
1825 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
1827 if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
1828 FIXME("Stream indexing not fully supported\n");
1834 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
1835 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1837 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
1838 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
1840 TRACE("(%p) : returning %d\n", This, *Divider);
1846 * Get / Set & Multiply Transform
1848 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1849 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1851 /* Most of this routine, comments included copied from ddraw tree initially: */
1852 TRACE("(%p) : Transform State=%d\n", This, d3dts);
1854 /* Handle recording of state blocks */
1855 if (This->isRecordingState) {
1856 TRACE("Recording... not performing anything\n");
1857 This->updateStateBlock->changed.transform[d3dts] = TRUE;
1858 This->updateStateBlock->set.transform[d3dts] = TRUE;
1859 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1864 * If the new matrix is the same as the current one,
1865 * we cut off any further processing. this seems to be a reasonable
1866 * optimization because as was noticed, some apps (warcraft3 for example)
1867 * tend towards setting the same matrix repeatedly for some reason.
1869 * From here on we assume that the new matrix is different, wherever it matters.
1871 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1872 TRACE("The app is setting the same matrix over again\n");
1875 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1879 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1880 where ViewMat = Camera space, WorldMat = world space.
1882 In OpenGL, camera and world space is combined into GL_MODELVIEW
1883 matrix. The Projection matrix stay projection matrix.
1886 /* Capture the times we can just ignore the change for now */
1887 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1888 This->modelview_valid = FALSE;
1891 } else if (d3dts == D3DTS_PROJECTION) {
1892 This->proj_valid = FALSE;
1895 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1896 /* Indexed Vertex Blending Matrices 256 -> 511 */
1897 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1898 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1902 /* Now we really are going to have to change a matrix */
1905 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1906 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
1907 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1910 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1911 * NOTE: We have to reset the positions even if the light/plane is not currently
1912 * enabled, since the call to enable it will not reset the position.
1913 * NOTE2: Apparently texture transforms do NOT need reapplying
1916 PLIGHTINFOEL *lightChain = NULL;
1917 This->modelview_valid = FALSE;
1918 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
1920 glMatrixMode(GL_MODELVIEW);
1921 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1923 glLoadMatrixf((float *)lpmatrix);
1924 checkGLcall("glLoadMatrixf(...)");
1927 lightChain = This->stateBlock->lights;
1928 while (lightChain && lightChain->glIndex != -1) {
1929 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1930 checkGLcall("glLightfv posn");
1931 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1932 checkGLcall("glLightfv dirn");
1933 lightChain = lightChain->next;
1936 /* Reset Clipping Planes if clipping is enabled */
1937 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1938 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1939 checkGLcall("glClipPlane");
1943 } else { /* What was requested!?? */
1944 WARN("invalid matrix specified: %i\n", d3dts);
1947 /* Release lock, all done */
1952 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1953 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1954 TRACE("(%p) : for Transform State %d\n", This, State);
1955 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1959 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1960 D3DMATRIX *mat = NULL;
1963 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1964 * below means it will be recorded in a state block change, but it
1965 * works regardless where it is recorded.
1966 * If this is found to be wrong, change to StateBlock.
1968 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1969 TRACE("(%p) : For state %u\n", This, State);
1971 if (State < HIGHEST_TRANSFORMSTATE)
1973 mat = &This->updateStateBlock->transforms[State];
1975 FIXME("Unhandled transform state!!\n");
1978 /* Copied from ddraw code: */
1979 temp.u.s._11 = (mat->u.s._11 * pMatrix->u.s._11) + (mat->u.s._21 * pMatrix->u.s._12) +
1980 (mat->u.s._31 * pMatrix->u.s._13) + (mat->u.s._41 * pMatrix->u.s._14);
1981 temp.u.s._21 = (mat->u.s._11 * pMatrix->u.s._21) + (mat->u.s._21 * pMatrix->u.s._22) +
1982 (mat->u.s._31 * pMatrix->u.s._23) + (mat->u.s._41 * pMatrix->u.s._24);
1983 temp.u.s._31 = (mat->u.s._11 * pMatrix->u.s._31) + (mat->u.s._21 * pMatrix->u.s._32) +
1984 (mat->u.s._31 * pMatrix->u.s._33) + (mat->u.s._41 * pMatrix->u.s._34);
1985 temp.u.s._41 = (mat->u.s._11 * pMatrix->u.s._41) + (mat->u.s._21 * pMatrix->u.s._42) +
1986 (mat->u.s._31 * pMatrix->u.s._43) + (mat->u.s._41 * pMatrix->u.s._44);
1988 temp.u.s._12 = (mat->u.s._12 * pMatrix->u.s._11) + (mat->u.s._22 * pMatrix->u.s._12) +
1989 (mat->u.s._32 * pMatrix->u.s._13) + (mat->u.s._42 * pMatrix->u.s._14);
1990 temp.u.s._22 = (mat->u.s._12 * pMatrix->u.s._21) + (mat->u.s._22 * pMatrix->u.s._22) +
1991 (mat->u.s._32 * pMatrix->u.s._23) + (mat->u.s._42 * pMatrix->u.s._24);
1992 temp.u.s._32 = (mat->u.s._12 * pMatrix->u.s._31) + (mat->u.s._22 * pMatrix->u.s._32) +
1993 (mat->u.s._32 * pMatrix->u.s._33) + (mat->u.s._42 * pMatrix->u.s._34);
1994 temp.u.s._42 = (mat->u.s._12 * pMatrix->u.s._41) + (mat->u.s._22 * pMatrix->u.s._42) +
1995 (mat->u.s._32 * pMatrix->u.s._43) + (mat->u.s._42 * pMatrix->u.s._44);
1997 temp.u.s._13 = (mat->u.s._13 * pMatrix->u.s._11) + (mat->u.s._23 * pMatrix->u.s._12) +
1998 (mat->u.s._33 * pMatrix->u.s._13) + (mat->u.s._43 * pMatrix->u.s._14);
1999 temp.u.s._23 = (mat->u.s._13 * pMatrix->u.s._21) + (mat->u.s._23 * pMatrix->u.s._22) +
2000 (mat->u.s._33 * pMatrix->u.s._23) + (mat->u.s._43 * pMatrix->u.s._24);
2001 temp.u.s._33 = (mat->u.s._13 * pMatrix->u.s._31) + (mat->u.s._23 * pMatrix->u.s._32) +
2002 (mat->u.s._33 * pMatrix->u.s._33) + (mat->u.s._43 * pMatrix->u.s._34);
2003 temp.u.s._43 = (mat->u.s._13 * pMatrix->u.s._41) + (mat->u.s._23 * pMatrix->u.s._42) +
2004 (mat->u.s._33 * pMatrix->u.s._43) + (mat->u.s._43 * pMatrix->u.s._44);
2006 temp.u.s._14 = (mat->u.s._14 * pMatrix->u.s._11) + (mat->u.s._24 * pMatrix->u.s._12) +
2007 (mat->u.s._34 * pMatrix->u.s._13) + (mat->u.s._44 * pMatrix->u.s._14);
2008 temp.u.s._24 = (mat->u.s._14 * pMatrix->u.s._21) + (mat->u.s._24 * pMatrix->u.s._22) +
2009 (mat->u.s._34 * pMatrix->u.s._23) + (mat->u.s._44 * pMatrix->u.s._24);
2010 temp.u.s._34 = (mat->u.s._14 * pMatrix->u.s._31) + (mat->u.s._24 * pMatrix->u.s._32) +
2011 (mat->u.s._34 * pMatrix->u.s._33) + (mat->u.s._44 * pMatrix->u.s._34);
2012 temp.u.s._44 = (mat->u.s._14 * pMatrix->u.s._41) + (mat->u.s._24 * pMatrix->u.s._42) +
2013 (mat->u.s._34 * pMatrix->u.s._43) + (mat->u.s._44 * pMatrix->u.s._44);
2015 /* Apply change via set transform - will reapply to eg. lights this way */
2016 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2021 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
2023 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2024 you can reference any indexes you want as long as that number max are enabled at any
2025 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2026 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2027 but when recording, just build a chain pretty much of commands to be replayed. */
2029 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2031 PLIGHTINFOEL *object, *temp;
2033 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2034 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2036 /* If recording state block, just add to end of lights chain */
2037 if (This->isRecordingState) {
2038 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2039 if (NULL == object) {
2040 return D3DERR_OUTOFVIDEOMEMORY;
2042 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2043 object->OriginalIndex = Index;
2044 object->glIndex = -1;
2045 object->changed = TRUE;
2047 /* Add to the END of the chain of lights changes to be replayed */
2048 if (This->updateStateBlock->lights == NULL) {
2049 This->updateStateBlock->lights = object;
2051 temp = This->updateStateBlock->lights;
2052 while (temp->next != NULL) temp=temp->next;
2053 temp->next = object;
2055 TRACE("Recording... not performing anything more\n");
2059 /* Ok, not recording any longer so do real work */
2060 object = This->stateBlock->lights;
2061 while (object != NULL && object->OriginalIndex != Index) object = object->next;
2063 /* If we didn't find it in the list of lights, time to add it */
2064 if (object == NULL) {
2065 PLIGHTINFOEL *insertAt,*prevPos;
2067 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2068 if (NULL == object) {
2069 return D3DERR_OUTOFVIDEOMEMORY;
2071 object->OriginalIndex = Index;
2072 object->glIndex = -1;
2074 /* Add it to the front of list with the idea that lights will be changed as needed
2075 BUT after any lights currently assigned GL indexes */
2076 insertAt = This->stateBlock->lights;
2078 while (insertAt != NULL && insertAt->glIndex != -1) {
2080 insertAt = insertAt->next;
2083 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2084 This->stateBlock->lights = object;
2085 } else if (insertAt == NULL) { /* End of list */
2086 prevPos->next = object;
2087 object->prev = prevPos;
2088 } else { /* Middle of chain */
2089 if (prevPos == NULL) {
2090 This->stateBlock->lights = object;
2092 prevPos->next = object;
2094 object->prev = prevPos;
2095 object->next = insertAt;
2096 insertAt->prev = object;
2100 /* Initialze the object */
2101 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,
2102 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2103 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2104 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2105 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2106 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2107 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2109 /* Save away the information */
2110 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2112 switch (pLight->Type) {
2113 case D3DLIGHT_POINT:
2115 object->lightPosn[0] = pLight->Position.x;
2116 object->lightPosn[1] = pLight->Position.y;
2117 object->lightPosn[2] = pLight->Position.z;
2118 object->lightPosn[3] = 1.0f;
2119 object->cutoff = 180.0f;
2123 case D3DLIGHT_DIRECTIONAL:
2125 object->lightPosn[0] = -pLight->Direction.x;
2126 object->lightPosn[1] = -pLight->Direction.y;
2127 object->lightPosn[2] = -pLight->Direction.z;
2128 object->lightPosn[3] = 0.0;
2129 object->exponent = 0.0f;
2130 object->cutoff = 180.0f;
2135 object->lightPosn[0] = pLight->Position.x;
2136 object->lightPosn[1] = pLight->Position.y;
2137 object->lightPosn[2] = pLight->Position.z;
2138 object->lightPosn[3] = 1.0;
2141 object->lightDirn[0] = pLight->Direction.x;
2142 object->lightDirn[1] = pLight->Direction.y;
2143 object->lightDirn[2] = pLight->Direction.z;
2144 object->lightDirn[3] = 1.0;
2147 * opengl-ish and d3d-ish spot lights use too different models for the
2148 * light "intensity" as a function of the angle towards the main light direction,
2149 * so we only can approximate very roughly.
2150 * however spot lights are rather rarely used in games (if ever used at all).
2151 * furthermore if still used, probably nobody pays attention to such details.
2153 if (pLight->Falloff == 0) {
2156 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2158 if (rho < 0.0001) rho = 0.0001f;
2159 object->exponent = -0.3/log(cos(rho/2));
2160 object->cutoff = pLight->Phi*90/M_PI;
2166 FIXME("Unrecognized light type %d\n", pLight->Type);
2169 /* Update the live definitions if the light is currently assigned a glIndex */
2170 if (object->glIndex != -1) {
2171 setup_light(iface, object->glIndex, object);
2176 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2177 PLIGHTINFOEL *lightInfo = NULL;
2178 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2179 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2181 /* Locate the light in the live lights */
2182 lightInfo = This->stateBlock->lights;
2183 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2185 if (lightInfo == NULL) {
2186 TRACE("Light information requested but light not defined\n");
2187 return D3DERR_INVALIDCALL;
2190 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
2195 * Get / Set Light Enable
2196 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2198 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2199 PLIGHTINFOEL *lightInfo = NULL;
2200 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2201 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2203 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2204 if (This->isRecordingState) {
2205 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2206 if (NULL == lightInfo) {
2207 return D3DERR_OUTOFVIDEOMEMORY;
2209 lightInfo->OriginalIndex = Index;
2210 lightInfo->glIndex = -1;
2211 lightInfo->enabledChanged = TRUE;
2213 /* Add to the END of the chain of lights changes to be replayed */
2214 if (This->updateStateBlock->lights == NULL) {
2215 This->updateStateBlock->lights = lightInfo;
2217 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2218 while (temp->next != NULL) temp=temp->next;
2219 temp->next = lightInfo;
2221 TRACE("Recording... not performing anything more\n");
2225 /* Not recording... So, locate the light in the live lights */
2226 lightInfo = This->stateBlock->lights;
2227 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2229 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2230 if (lightInfo == NULL) {
2231 D3DLIGHT9 lightParms;
2232 /* Warning - untested code :-) Prob safe to change fixme to a trace but
2233 wait until someone confirms it seems to work! */
2234 TRACE("Light enabled requested but light not defined, so defining one!\n");
2235 lightParms.Type = D3DLIGHT_DIRECTIONAL;
2236 lightParms.Diffuse.r = 1.0;
2237 lightParms.Diffuse.g = 1.0;
2238 lightParms.Diffuse.b = 1.0;
2239 lightParms.Diffuse.a = 0.0;
2240 lightParms.Specular.r = 0.0;
2241 lightParms.Specular.g = 0.0;
2242 lightParms.Specular.b = 0.0;
2243 lightParms.Specular.a = 0.0;
2244 lightParms.Ambient.r = 0.0;
2245 lightParms.Ambient.g = 0.0;
2246 lightParms.Ambient.b = 0.0;
2247 lightParms.Ambient.a = 0.0;
2248 lightParms.Position.x = 0.0;
2249 lightParms.Position.y = 0.0;
2250 lightParms.Position.z = 0.0;
2251 lightParms.Direction.x = 0.0;
2252 lightParms.Direction.y = 0.0;
2253 lightParms.Direction.z = 1.0;
2254 lightParms.Range = 0.0;
2255 lightParms.Falloff = 0.0;
2256 lightParms.Attenuation0 = 0.0;
2257 lightParms.Attenuation1 = 0.0;
2258 lightParms.Attenuation2 = 0.0;
2259 lightParms.Theta = 0.0;
2260 lightParms.Phi = 0.0;
2261 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
2263 /* Search for it again! Should be fairly quick as near head of list */
2264 lightInfo = This->stateBlock->lights;
2265 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2266 if (lightInfo == NULL) {
2267 FIXME("Adding default lights has failed dismally\n");
2268 return D3DERR_INVALIDCALL;
2272 /* OK, we now have a light... */
2273 if (Enable == FALSE) {
2275 /* If we are disabling it, check it was enabled, and
2276 still only do something if it has assigned a glIndex (which it should have!) */
2277 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2278 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2280 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2281 checkGLcall("glDisable GL_LIGHT0+Index");
2284 TRACE("Nothing to do as light was not enabled\n");
2286 lightInfo->lightEnabled = FALSE;
2289 /* We are enabling it. If it is enabled, it's really simple */
2290 if (lightInfo->lightEnabled) {
2292 TRACE("Nothing to do as light was enabled\n");
2294 /* If it already has a glIndex, it's still simple */
2295 } else if (lightInfo->glIndex != -1) {
2296 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2297 lightInfo->lightEnabled = TRUE;
2299 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2300 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2303 /* Otherwise got to find space - lights are ordered gl indexes first */
2305 PLIGHTINFOEL *bsf = NULL;
2306 PLIGHTINFOEL *pos = This->stateBlock->lights;
2307 PLIGHTINFOEL *prev = NULL;
2311 /* Try to minimize changes as much as possible */
2312 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2314 /* Try to remember which index can be replaced if necessary */
2315 if (bsf==NULL && pos->lightEnabled == FALSE) {
2316 /* Found a light we can replace, save as best replacement */
2320 /* Step to next space */
2326 /* If we have too many active lights, fail the call */
2327 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2328 FIXME("Program requests too many concurrent lights\n");
2329 return D3DERR_INVALIDCALL;
2331 /* If we have allocated all lights, but not all are enabled,
2332 reuse one which is not enabled */
2333 } else if (Index == This->maxConcurrentLights) {
2334 /* use bsf - Simply swap the new light and the BSF one */
2335 PLIGHTINFOEL *bsfNext = bsf->next;
2336 PLIGHTINFOEL *bsfPrev = bsf->prev;
2339 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2340 if (bsf->prev != NULL) {
2341 bsf->prev->next = lightInfo;
2343 This->stateBlock->lights = lightInfo;
2346 /* If not side by side, lots of chains to update */
2347 if (bsf->next != lightInfo) {
2348 lightInfo->prev->next = bsf;
2349 bsf->next->prev = lightInfo;
2350 bsf->next = lightInfo->next;
2351 bsf->prev = lightInfo->prev;
2352 lightInfo->next = bsfNext;
2353 lightInfo->prev = bsfPrev;
2357 bsf->prev = lightInfo;
2358 bsf->next = lightInfo->next;
2359 lightInfo->next = bsf;
2360 lightInfo->prev = bsfPrev;
2365 glIndex = bsf->glIndex;
2367 lightInfo->glIndex = glIndex;
2368 lightInfo->lightEnabled = TRUE;
2370 /* Finally set up the light in gl itself */
2371 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2373 setup_light(iface, glIndex, lightInfo);
2374 glEnable(GL_LIGHT0 + glIndex);
2375 checkGLcall("glEnable GL_LIGHT0 new setup");
2378 /* If we reached the end of the allocated lights, with space in the
2379 gl lights, setup a new light */
2380 } else if (pos->glIndex == -1) {
2382 /* We reached the end of the allocated gl lights, so already
2383 know the index of the next one! */
2385 lightInfo->glIndex = glIndex;
2386 lightInfo->lightEnabled = TRUE;
2388 /* In an ideal world, it's already in the right place */
2389 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2390 /* No need to move it */
2392 /* Remove this light from the list */
2393 lightInfo->prev->next = lightInfo->next;
2394 if (lightInfo->next != NULL) {
2395 lightInfo->next->prev = lightInfo->prev;
2398 /* Add in at appropriate place (inbetween prev and pos) */
2399 lightInfo->prev = prev;
2400 lightInfo->next = pos;
2402 This->stateBlock->lights = lightInfo;
2404 prev->next = lightInfo;
2407 pos->prev = lightInfo;
2411 /* Finally set up the light in gl itself */
2412 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2414 setup_light(iface, glIndex, lightInfo);
2415 glEnable(GL_LIGHT0 + glIndex);
2416 checkGLcall("glEnable GL_LIGHT0 new setup");
2425 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2427 PLIGHTINFOEL *lightInfo = NULL;
2428 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2429 TRACE("(%p) : for idx(%ld)\n", This, Index);
2431 /* Locate the light in the live lights */
2432 lightInfo = This->stateBlock->lights;
2433 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2435 if (lightInfo == NULL) {
2436 TRACE("Light enabled state requested but light not defined\n");
2437 return D3DERR_INVALIDCALL;
2439 *pEnable = lightInfo->lightEnabled;
2444 * Get / Set Clip Planes
2446 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2447 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2448 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2450 /* Validate Index */
2451 if (Index >= GL_LIMITS(clipplanes)) {
2452 TRACE("Application has requested clipplane this device doesn't support\n");
2453 return D3DERR_INVALIDCALL;
2456 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2457 This->updateStateBlock->set.clipplane[Index] = TRUE;
2458 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2459 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2460 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2461 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2463 /* Handle recording of state blocks */
2464 if (This->isRecordingState) {
2465 TRACE("Recording... not performing anything\n");
2473 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2474 glMatrixMode(GL_MODELVIEW);
2476 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2478 TRACE("Clipplane [%f,%f,%f,%f]\n",
2479 This->updateStateBlock->clipplane[Index][0],
2480 This->updateStateBlock->clipplane[Index][1],
2481 This->updateStateBlock->clipplane[Index][2],
2482 This->updateStateBlock->clipplane[Index][3]);
2483 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2484 checkGLcall("glClipPlane");
2492 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2493 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2494 TRACE("(%p) : for idx %ld\n", This, Index);
2496 /* Validate Index */
2497 if (Index >= GL_LIMITS(clipplanes)) {
2498 TRACE("Application has requested clipplane this device doesn't support\n");
2499 return D3DERR_INVALIDCALL;
2502 pPlane[0] = This->stateBlock->clipplane[Index][0];
2503 pPlane[1] = This->stateBlock->clipplane[Index][1];
2504 pPlane[2] = This->stateBlock->clipplane[Index][2];
2505 pPlane[3] = This->stateBlock->clipplane[Index][3];
2510 * Get / Set Clip Plane Status
2511 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2513 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2514 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2515 FIXME("(%p) : stub\n", This);
2516 if (NULL == pClipStatus) {
2517 return D3DERR_INVALIDCALL;
2519 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2520 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2524 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2525 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2526 FIXME("(%p) : stub\n", This);
2527 if (NULL == pClipStatus) {
2528 return D3DERR_INVALIDCALL;
2530 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2531 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2536 * Get / Set Material
2537 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2539 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2540 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2542 This->updateStateBlock->changed.material = TRUE;
2543 This->updateStateBlock->set.material = TRUE;
2544 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2546 /* Handle recording of state blocks */
2547 if (This->isRecordingState) {
2548 TRACE("Recording... not performing anything\n");
2553 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2554 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2555 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2556 pMaterial->Ambient.b, pMaterial->Ambient.a);
2557 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2558 pMaterial->Specular.b, pMaterial->Specular.a);
2559 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2560 pMaterial->Emissive.b, pMaterial->Emissive.a);
2561 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2563 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2564 checkGLcall("glMaterialfv(GL_AMBIENT)");
2565 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2566 checkGLcall("glMaterialfv(GL_DIFFUSE)");
2568 /* Only change material color if specular is enabled, otherwise it is set to black */
2569 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2570 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2571 checkGLcall("glMaterialfv(GL_SPECULAR");
2573 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2574 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2575 checkGLcall("glMaterialfv(GL_SPECULAR");
2577 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2578 checkGLcall("glMaterialfv(GL_EMISSION)");
2579 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2580 checkGLcall("glMaterialf(GL_SHININESS");
2586 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2587 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2588 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2589 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2590 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2591 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2592 pMaterial->Ambient.b, pMaterial->Ambient.a);
2593 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2594 pMaterial->Specular.b, pMaterial->Specular.a);
2595 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2596 pMaterial->Emissive.b, pMaterial->Emissive.a);
2597 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2605 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2606 UINT BaseVertexIndex) {
2607 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2608 IWineD3DIndexBuffer *oldIdxs;
2610 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2611 oldIdxs = This->updateStateBlock->pIndexData;
2613 This->updateStateBlock->changed.indices = TRUE;
2614 This->updateStateBlock->set.indices = TRUE;
2615 This->updateStateBlock->pIndexData = pIndexData;
2616 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2618 /* Handle recording of state blocks */
2619 if (This->isRecordingState) {
2620 TRACE("Recording... not performing anything\n");
2625 IUnknown *indexBufferParent;
2626 /* Getting the parent causes a addRef... it gets released when the indicies are clear */
2627 IWineD3DIndexBuffer_GetParent(pIndexData, &indexBufferParent);
2630 IUnknown *indexBufferParent;
2631 IWineD3DIndexBuffer_GetParent(oldIdxs, &indexBufferParent);
2632 IUnknown_Release(indexBufferParent);
2633 IUnknown_Release(indexBufferParent);
2638 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2639 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2641 *ppIndexData = This->stateBlock->pIndexData;
2643 /* up ref count on ppindexdata */
2645 IWineD3DIndexBuffer_AddRef(*ppIndexData);
2646 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2647 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
2649 TRACE("(%p) No index data set\n", This);
2651 TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
2657 * Get / Set Viewports
2659 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2660 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2662 TRACE("(%p)\n", This);
2663 This->updateStateBlock->changed.viewport = TRUE;
2664 This->updateStateBlock->set.viewport = TRUE;
2665 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2667 /* Handle recording of state blocks */
2668 if (This->isRecordingState) {
2669 TRACE("Recording... not performing anything\n");
2675 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2676 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2678 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2679 checkGLcall("glDepthRange");
2680 /* Note: GL requires lower left, DirectX supplies upper left */
2681 /* TODO: replace usage of renderTarget with context management */
2682 glViewport(pViewport->X,
2683 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2684 pViewport->Width, pViewport->Height);
2686 checkGLcall("glViewport");
2694 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2695 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2696 TRACE("(%p)\n", This);
2697 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2702 * Get / Set Render States
2703 * TODO: Verify against dx9 definitions
2705 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2707 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2708 DWORD OldValue = This->stateBlock->renderState[State];
2710 /* Simple way of referring to either a DWORD or a 4 byte float */
2716 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2717 This->updateStateBlock->changed.renderState[State] = TRUE;
2718 This->updateStateBlock->set.renderState[State] = TRUE;
2719 This->updateStateBlock->renderState[State] = Value;
2721 /* Handle recording of state blocks */
2722 if (This->isRecordingState) {
2723 TRACE("Recording... not performing anything\n");
2730 case WINED3DRS_FILLMODE :
2731 switch ((D3DFILLMODE) Value) {
2732 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2733 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2734 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2736 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
2738 checkGLcall("glPolygonMode (fillmode)");
2741 case WINED3DRS_LIGHTING :
2743 glEnable(GL_LIGHTING);
2744 checkGLcall("glEnable GL_LIGHTING");
2746 glDisable(GL_LIGHTING);
2747 checkGLcall("glDisable GL_LIGHTING");
2751 case WINED3DRS_ZENABLE :
2752 switch ((D3DZBUFFERTYPE) Value) {
2754 glDisable(GL_DEPTH_TEST);
2755 checkGLcall("glDisable GL_DEPTH_TEST");
2758 glEnable(GL_DEPTH_TEST);
2759 checkGLcall("glEnable GL_DEPTH_TEST");
2762 glEnable(GL_DEPTH_TEST);
2763 checkGLcall("glEnable GL_DEPTH_TEST");
2764 FIXME("W buffer is not well handled\n");
2767 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2771 case WINED3DRS_CULLMODE :
2773 /* If we are culling "back faces with clockwise vertices" then
2774 set front faces to be counter clockwise and enable culling
2776 switch ((D3DCULL) Value) {
2778 glDisable(GL_CULL_FACE);
2779 checkGLcall("glDisable GL_CULL_FACE");
2782 glEnable(GL_CULL_FACE);
2783 checkGLcall("glEnable GL_CULL_FACE");
2784 if (This->renderUpsideDown) {
2786 checkGLcall("glFrontFace GL_CW");
2788 glFrontFace(GL_CCW);
2789 checkGLcall("glFrontFace GL_CCW");
2791 glCullFace(GL_BACK);
2794 glEnable(GL_CULL_FACE);
2795 checkGLcall("glEnable GL_CULL_FACE");
2796 if (This->renderUpsideDown) {
2797 glFrontFace(GL_CCW);
2798 checkGLcall("glFrontFace GL_CCW");
2801 checkGLcall("glFrontFace GL_CW");
2803 glCullFace(GL_BACK);
2806 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2810 case WINED3DRS_SHADEMODE :
2811 switch ((D3DSHADEMODE) Value) {
2813 glShadeModel(GL_FLAT);
2814 checkGLcall("glShadeModel");
2816 case D3DSHADE_GOURAUD:
2817 glShadeModel(GL_SMOOTH);
2818 checkGLcall("glShadeModel");
2820 case D3DSHADE_PHONG:
2821 FIXME("D3DSHADE_PHONG isn't supported?\n");
2824 return D3DERR_INVALIDCALL;
2826 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2830 case WINED3DRS_DITHERENABLE :
2832 glEnable(GL_DITHER);
2833 checkGLcall("glEnable GL_DITHER");
2835 glDisable(GL_DITHER);
2836 checkGLcall("glDisable GL_DITHER");
2840 case WINED3DRS_ZWRITEENABLE :
2843 checkGLcall("glDepthMask");
2846 checkGLcall("glDepthMask");
2850 case WINED3DRS_ZFUNC :
2852 int glParm = GL_LESS;
2854 switch ((D3DCMPFUNC) Value) {
2855 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2856 case D3DCMP_LESS: glParm=GL_LESS; break;
2857 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2858 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2859 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2860 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2861 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2862 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2864 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2866 glDepthFunc(glParm);
2867 checkGLcall("glDepthFunc");
2871 case WINED3DRS_AMBIENT :
2874 D3DCOLORTOGLFLOAT4(Value, col);
2875 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2876 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2877 checkGLcall("glLightModel for MODEL_AMBIENT");
2882 case WINED3DRS_ALPHABLENDENABLE :
2885 checkGLcall("glEnable GL_BLEND");
2887 glDisable(GL_BLEND);
2888 checkGLcall("glDisable GL_BLEND");
2892 case WINED3DRS_SRCBLEND :
2893 case WINED3DRS_DESTBLEND :
2895 int newVal = GL_ZERO;
2897 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2898 case D3DBLEND_ONE : newVal = GL_ONE; break;
2899 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2900 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2901 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2902 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2903 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2904 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2905 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2906 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2907 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2909 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2910 This->srcBlend = newVal;
2911 This->dstBlend = newVal;
2914 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2915 This->srcBlend = newVal;
2916 This->dstBlend = newVal;
2919 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2922 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2923 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2924 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2925 glBlendFunc(This->srcBlend, This->dstBlend);
2927 checkGLcall("glBlendFunc");
2931 case WINED3DRS_ALPHATESTENABLE :
2933 glEnable(GL_ALPHA_TEST);
2934 checkGLcall("glEnable GL_ALPHA_TEST");
2936 glDisable(GL_ALPHA_TEST);
2937 checkGLcall("glDisable GL_ALPHA_TEST");
2941 case WINED3DRS_ALPHAFUNC :
2943 int glParm = GL_LESS;
2944 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2946 switch ((D3DCMPFUNC) Value) {
2947 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2948 case D3DCMP_LESS: glParm = GL_LESS; break;
2949 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2950 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2951 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2952 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2953 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2954 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2956 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2958 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2959 glAlphaFunc(glParm, ref);
2960 This->alphafunc = glParm;
2961 checkGLcall("glAlphaFunc");
2965 case WINED3DRS_ALPHAREF :
2967 int glParm = This->alphafunc;
2970 ref = ((float) Value) / 255.0f;
2971 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2972 glAlphaFunc(glParm, ref);
2973 checkGLcall("glAlphaFunc");
2977 case WINED3DRS_CLIPPLANEENABLE :
2978 case WINED3DRS_CLIPPING :
2980 /* Ensure we only do the changed clip planes */
2981 DWORD enable = 0xFFFFFFFF;
2982 DWORD disable = 0x00000000;
2984 /* If enabling / disabling all */
2985 if (State == WINED3DRS_CLIPPING) {
2987 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2990 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2994 enable = Value & ~OldValue;
2995 disable = ~Value & OldValue;
2998 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2999 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
3000 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
3001 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
3002 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
3003 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
3005 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
3006 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
3007 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
3008 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
3009 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
3010 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
3012 /** update clipping status */
3014 This->stateBlock->clip_status.ClipUnion = 0;
3015 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
3017 This->stateBlock->clip_status.ClipUnion = 0;
3018 This->stateBlock->clip_status.ClipIntersection = 0;
3023 case WINED3DRS_BLENDOP :
3025 int glParm = GL_FUNC_ADD;
3027 switch ((D3DBLENDOP) Value) {
3028 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
3029 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
3030 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3031 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
3032 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
3034 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
3036 TRACE("glBlendEquation(%x)\n", glParm);
3037 glBlendEquation(glParm);
3038 checkGLcall("glBlendEquation");
3042 case WINED3DRS_TEXTUREFACTOR :
3046 /* Note the texture color applies to all textures whereas
3047 GL_TEXTURE_ENV_COLOR applies to active only */
3049 D3DCOLORTOGLFLOAT4(Value, col);
3050 /* Set the default alpha blend color */
3051 glBlendColor(col[0], col[1], col[2], col[3]);
3052 checkGLcall("glBlendColor");
3054 /* And now the default texture color as well */
3055 for (i = 0; i < GL_LIMITS(textures); i++) {
3057 /* Note the D3DRS value applies to all textures, but GL has one
3058 per texture, so apply it now ready to be used! */
3059 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3062 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3065 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3066 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3071 case WINED3DRS_SPECULARENABLE :
3073 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3074 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3075 specular color. This is wrong:
3076 Separate specular color means the specular colour is maintained separately, whereas
3077 single color means it is merged in. However in both cases they are being used to
3079 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3080 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3084 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3085 checkGLcall("glMaterialfv");
3086 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3087 glEnable(GL_COLOR_SUM_EXT);
3089 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3091 checkGLcall("glEnable(GL_COLOR_SUM)");
3093 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3095 /* for the case of enabled lighting: */
3096 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3097 checkGLcall("glMaterialfv");
3099 /* for the case of disabled lighting: */
3100 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3101 glDisable(GL_COLOR_SUM_EXT);
3103 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3105 checkGLcall("glDisable(GL_COLOR_SUM)");
3110 case WINED3DRS_STENCILENABLE :
3112 glEnable(GL_STENCIL_TEST);
3113 checkGLcall("glEnable GL_STENCIL_TEST");
3115 glDisable(GL_STENCIL_TEST);
3116 checkGLcall("glDisable GL_STENCIL_TEST");
3120 case WINED3DRS_STENCILFUNC :
3122 int glParm = GL_ALWAYS;
3123 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3124 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3126 switch ((D3DCMPFUNC) Value) {
3127 case D3DCMP_NEVER: glParm=GL_NEVER; break;
3128 case D3DCMP_LESS: glParm=GL_LESS; break;
3129 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
3130 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
3131 case D3DCMP_GREATER: glParm=GL_GREATER; break;
3132 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
3133 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
3134 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
3136 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3138 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3139 This->stencilfunc = glParm;
3140 glStencilFunc(glParm, ref, mask);
3141 checkGLcall("glStencilFunc");
3145 case WINED3DRS_STENCILREF :
3147 int glParm = This->stencilfunc;
3149 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3152 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3153 glStencilFunc(glParm, ref, mask);
3154 checkGLcall("glStencilFunc");
3158 case WINED3DRS_STENCILMASK :
3160 int glParm = This->stencilfunc;
3161 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3162 GLuint mask = Value;
3164 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3165 glStencilFunc(glParm, ref, mask);
3166 checkGLcall("glStencilFunc");
3170 case WINED3DRS_STENCILFAIL :
3176 fail = StencilOp(Value);
3177 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
3178 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
3179 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
3180 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
3182 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3183 glStencilOp(fail, zfail, zpass);
3184 checkGLcall("glStencilOp(fail, zfail, zpass);");
3187 case WINED3DRS_STENCILZFAIL :
3193 glGetIntegerv(GL_STENCIL_FAIL, &fail);
3194 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
3195 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
3196 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
3197 zfail = StencilOp(Value);
3199 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3200 glStencilOp(fail, zfail, zpass);
3201 checkGLcall("glStencilOp(fail, zfail, zpass);");
3204 case WINED3DRS_STENCILPASS :
3210 glGetIntegerv(GL_STENCIL_FAIL, &fail);
3211 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
3212 zpass = StencilOp(Value);
3213 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
3214 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
3216 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3217 glStencilOp(fail, zfail, zpass);
3218 checkGLcall("glStencilOp(fail, zfail, zpass);");
3222 case WINED3DRS_STENCILWRITEMASK :
3224 glStencilMask(Value);
3225 TRACE("glStencilMask(%lu)\n", Value);
3226 checkGLcall("glStencilMask");
3230 case WINED3DRS_FOGENABLE :
3232 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
3234 checkGLcall("glEnable GL_FOG");
3237 checkGLcall("glDisable GL_FOG");
3242 case WINED3DRS_RANGEFOGENABLE :
3245 TRACE("Enabled RANGEFOG");
3247 TRACE("Disabled RANGEFOG");
3252 case WINED3DRS_FOGCOLOR :
3255 D3DCOLORTOGLFLOAT4(Value, col);
3256 /* Set the default alpha blend color */
3257 glFogfv(GL_FOG_COLOR, &col[0]);
3258 checkGLcall("glFog GL_FOG_COLOR");
3262 case WINED3DRS_FOGTABLEMODE :
3264 glHint(GL_FOG_HINT, GL_NICEST);
3266 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3267 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3268 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3269 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3271 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3273 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3274 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3279 case WINED3DRS_FOGVERTEXMODE :
3281 glHint(GL_FOG_HINT, GL_FASTEST);
3283 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3284 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3285 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3286 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3288 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3290 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3291 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
3296 case WINED3DRS_FOGSTART :
3299 glFogfv(GL_FOG_START, &tmpvalue.f);
3300 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3301 TRACE("Fog Start == %f\n", tmpvalue.f);
3305 case WINED3DRS_FOGEND :
3308 glFogfv(GL_FOG_END, &tmpvalue.f);
3309 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3310 TRACE("Fog End == %f\n", tmpvalue.f);
3314 case WINED3DRS_FOGDENSITY :
3317 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3318 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3322 case WINED3DRS_VERTEXBLEND :
3324 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3325 TRACE("Vertex Blending state to %ld\n", Value);
3329 case WINED3DRS_TWEENFACTOR :
3332 This->updateStateBlock->tween_factor = tmpvalue.f;
3333 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3337 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
3339 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3343 case WINED3DRS_COLORVERTEX :
3344 case WINED3DRS_DIFFUSEMATERIALSOURCE :
3345 case WINED3DRS_SPECULARMATERIALSOURCE :
3346 case WINED3DRS_AMBIENTMATERIALSOURCE :
3347 case WINED3DRS_EMISSIVEMATERIALSOURCE :
3349 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3351 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3352 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3353 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3354 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3355 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3356 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3358 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3359 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3360 Parm = GL_AMBIENT_AND_DIFFUSE;
3364 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3366 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3368 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3375 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3377 This->tracking_color = NEEDS_TRACKING;
3378 This->tracking_parm = Parm;
3382 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3387 case WINED3DRS_LINEPATTERN :
3393 tmppattern.d = Value;
3395 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3397 if (tmppattern.lp.wRepeatFactor) {
3398 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3399 checkGLcall("glLineStipple(repeat, linepattern)");
3400 glEnable(GL_LINE_STIPPLE);
3401 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3403 glDisable(GL_LINE_STIPPLE);
3404 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3409 case WINED3DRS_ZBIAS : /* D3D8 only */
3413 TRACE("ZBias value %f\n", tmpvalue.f);
3414 glPolygonOffset(0, -tmpvalue.f);
3415 checkGLcall("glPolygonOffset(0, -Value)");
3416 glEnable(GL_POLYGON_OFFSET_FILL);
3417 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3418 glEnable(GL_POLYGON_OFFSET_LINE);
3419 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3420 glEnable(GL_POLYGON_OFFSET_POINT);
3421 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3423 glDisable(GL_POLYGON_OFFSET_FILL);
3424 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3425 glDisable(GL_POLYGON_OFFSET_LINE);
3426 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3427 glDisable(GL_POLYGON_OFFSET_POINT);
3428 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3433 case WINED3DRS_NORMALIZENORMALS :
3435 glEnable(GL_NORMALIZE);
3436 checkGLcall("glEnable(GL_NORMALIZE);");
3438 glDisable(GL_NORMALIZE);
3439 checkGLcall("glDisable(GL_NORMALIZE);");
3443 case WINED3DRS_POINTSIZE :
3444 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
3446 TRACE("Set point size to %f\n", tmpvalue.f);
3447 glPointSize(tmpvalue.f);
3448 checkGLcall("glPointSize(...);");
3451 case WINED3DRS_POINTSIZE_MIN :
3452 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3454 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3455 checkGLcall("glPointParameterfEXT(...);");
3457 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3461 case WINED3DRS_POINTSIZE_MAX :
3462 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3464 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3465 checkGLcall("glPointParameterfEXT(...);");
3467 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3471 case WINED3DRS_POINTSCALE_A :
3472 case WINED3DRS_POINTSCALE_B :
3473 case WINED3DRS_POINTSCALE_C :
3474 case WINED3DRS_POINTSCALEENABLE :
3476 /* If enabled, supply the parameters, otherwise fall back to defaults */
3477 if (This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3478 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3479 /* TODO: Correct the scaling (this hack seems to be good enough for every demo that uses point sprites!) */
3480 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A])/ This->stateBlock->viewport.Width;
3481 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B])/ This->stateBlock->viewport.Height;
3482 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) *
3483 2.0f /(This->stateBlock->viewport.Width * This->stateBlock->viewport.Height);
3485 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3486 TRACE("glPointParameterfvARB %f %f %f\n", att[0], att[1], att[2]);
3487 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3488 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3490 TRACE("WINED3DRS_POINTSCALEENABLE not supported on this opengl\n");
3493 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3494 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3495 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3496 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3498 TRACE("WINED3DRS_POINTSCALEENABLE not supported, but not on either\n");
3504 case WINED3DRS_COLORWRITEENABLE :
3506 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3507 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3508 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3509 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3510 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3511 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3512 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3513 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3514 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3515 checkGLcall("glColorMask(...)");
3519 case WINED3DRS_LOCALVIEWER :
3521 GLint state = (Value) ? 1 : 0;
3522 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3523 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3527 case WINED3DRS_LASTPIXEL :
3530 TRACE("Last Pixel Drawing Enabled\n");
3532 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3537 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3540 TRACE("Software Processing Enabled\n");
3542 TRACE("Software Processing Disabled\n");
3547 /** not supported */
3548 case WINED3DRS_ZVISIBLE :
3551 return D3DERR_INVALIDCALL;
3553 case WINED3DRS_POINTSPRITEENABLE :
3554 /* TODO: NV_POINT_SPRITE */
3555 if (GL_SUPPORT(ARB_POINT_SPRITE)) {
3556 if (Value != FALSE) {
3557 /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
3558 glDisable(GL_POINT_SMOOTH);
3559 /* Centre the texture on the vertex */
3560 VTRACE("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
3561 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
3563 VTRACE("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
3564 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
3565 checkGLcall("glTexEnvf(...)");
3566 VTRACE("glEnable( GL_POINT_SPRITE_ARB )\n");
3567 glEnable( GL_POINT_SPRITE_ARB );
3568 checkGLcall("glEnable(...)");
3570 VTRACE("glDisable( GL_POINT_SPRITE_ARB )\n");
3571 glDisable( GL_POINT_SPRITE_ARB );
3572 checkGLcall("glEnable(...)");
3576 /* Unhandled yet...! */
3577 case WINED3DRS_EDGEANTIALIAS :
3578 case WINED3DRS_WRAP0 :
3579 case WINED3DRS_WRAP1 :
3580 case WINED3DRS_WRAP2 :
3581 case WINED3DRS_WRAP3 :
3582 case WINED3DRS_WRAP4 :
3583 case WINED3DRS_WRAP5 :
3584 case WINED3DRS_WRAP6 :
3585 case WINED3DRS_WRAP7 :
3587 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
3588 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
3589 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
3590 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
3591 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
3593 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
3595 TRACE("(%p)->(%d,%ld) Texture wraping not yet supported\n",This, State, Value);
3597 case WINED3DRS_MULTISAMPLEANTIALIAS :
3598 case WINED3DRS_MULTISAMPLEMASK :
3599 case WINED3DRS_PATCHEDGESTYLE :
3600 case WINED3DRS_PATCHSEGMENTS :
3601 case WINED3DRS_DEBUGMONITORTOKEN :
3602 case WINED3DRS_POSITIONORDER :
3603 case WINED3DRS_NORMALORDER :
3604 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3605 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3608 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3616 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3617 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3618 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3619 *pValue = This->stateBlock->renderState[State];
3624 * Get / Set Sampler States
3625 * TODO: Verify against dx9 definitions
3628 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3629 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3631 * SetSampler is designed to allow for more than the standard up to 8 textures
3632 * and Geforce has stopped supporting more than 6 standard textures in openGL.
3633 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3635 * http://developer.nvidia.com/object/General_FAQ.html#t6
3637 * There are two new settings for GForce
3639 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3640 * and the texture one:
3641 * GL_MAX_TEXTURE_COORDS_ARB.
3642 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3644 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
3645 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
3647 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
3648 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE, Sampler, Type);
3649 return D3DERR_INVALIDCALL;
3651 TRACE("Setting sampler %ld %d to %ld\n", Sampler, Type, Value);
3652 This->updateStateBlock->samplerState[Sampler][Type] = Value;
3653 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
3654 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
3656 /* Handle recording of state blocks */
3657 if (This->isRecordingState) {
3658 TRACE("Recording... not performing anything\n");
3665 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3666 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3667 /** TODO: check that sampler is in range **/
3668 *Value = This->updateStateBlock->samplerState[Sampler][Type];
3669 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
3674 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3675 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3678 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3679 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3680 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3686 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3687 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3688 GLint scissorBox[4];
3691 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3692 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
3693 pRect->left = scissorBox[1];
3694 pRect->top = scissorBox[2];
3695 pRect->right = scissorBox[1] + scissorBox[3];
3696 pRect->bottom = scissorBox[2] + scissorBox[4];
3697 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3702 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3703 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3705 TRACE("(%p) : pDecl=%p\n", This, pDecl);
3707 /* TODO: what about recording stateblocks? */
3708 if (NULL != pDecl) {
3709 IWineD3DVertexDeclaration_AddRef(pDecl);
3711 if (NULL != This->updateStateBlock->vertexDecl) {
3712 IWineD3DVertexDeclaration_Release(This->updateStateBlock->vertexDecl);
3714 This->updateStateBlock->vertexDecl = pDecl;
3715 This->updateStateBlock->changed.vertexDecl = TRUE;
3716 This->updateStateBlock->set.vertexDecl = TRUE;
3720 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3721 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3723 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3725 *ppDecl = This->updateStateBlock->vertexDecl;
3726 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3730 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
3731 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3732 IWineD3DVertexShader *oldShader = This->updateStateBlock->vertexShader;
3734 This->updateStateBlock->vertexShader = pShader;
3735 This->updateStateBlock->changed.vertexShader = TRUE;
3736 This->updateStateBlock->set.vertexShader = TRUE;
3738 if (This->isRecordingState) {
3739 TRACE("Recording... not performing anything\n");
3743 if (pShader != NULL) {
3744 IUnknown *newVertexShaderParent;
3745 /* GetParent will add a ref, so leave it hanging until the vertex buffer is cleared */
3746 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3747 IWineD3DVertexShader_GetParent(pShader, &newVertexShaderParent);
3749 TRACE("Clear down the shader\n");
3751 if (oldShader != NULL) {
3752 IUnknown *oldVertexShaderParent;
3753 IWineD3DVertexShader_GetParent(oldShader, &oldVertexShaderParent);
3754 IUnknown_Release(oldVertexShaderParent);
3755 IUnknown_Release(oldVertexShaderParent);
3758 * TODO: merge HAL shaders context switching from prototype
3763 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
3764 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3766 if (NULL == ppShader) {
3767 return D3DERR_INVALIDCALL;
3769 *ppShader = This->stateBlock->vertexShader;
3770 if( NULL != *ppShader)
3771 IWineD3DVertexShader_AddRef(*ppShader);
3773 TRACE("(%p) : returning %p\n", This, *ppShader);
3777 #define GET_SHADER_CONSTANT(_vertexshaderconstant, _count, _sizecount) \
3778 count = min(_count, MAX_VSHADER_CONSTANTS - (StartRegister + 1)); \
3779 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3780 return D3DERR_INVALIDCALL; \
3781 memcpy(pConstantData, This->updateStateBlock->_vertexshaderconstant + (StartRegister * _sizecount), count * (sizeof(*pConstantData) * _sizecount));
3783 #define SET_SHADER_CONSTANT(_vertexshaderconstant, _count, _sizecount) \
3784 int count = min(_count, MAX_VSHADER_CONSTANTS - (StartRegister + 1)); \
3785 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3786 return D3DERR_INVALIDCALL; \
3787 memcpy(This->updateStateBlock->_vertexshaderconstant + (StartRegister * _sizecount), pConstantData, count * (sizeof(*pConstantData) * _sizecount)); \
3788 This->updateStateBlock->changed.vertexShader = TRUE; \
3789 This->updateStateBlock->set.vertexShader = TRUE;
3791 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
3792 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3794 SET_SHADER_CONSTANT(vertexShaderConstantB, BoolCount, 1);
3796 /* populate the bitmap that says which constant type we should load */
3797 for (i = StartRegister; i < BoolCount + StartRegister; ++i) {
3798 This->updateStateBlock->changed.vertexShaderConstants[i] = TRUE;
3799 This->updateStateBlock->set.vertexShaderConstants[i] = TRUE;
3800 This->updateStateBlock->vertexShaderConstantT[i] = WINESHADERCNST_BOOL;
3801 TRACE("(%p) : Setting vsb %d to %d\n", This->updateStateBlock, i, pConstantData[i - StartRegister]);
3807 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
3808 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3811 /* verify that the requested shader constant was populated with a boolean */
3812 for (i = StartRegister; i < BoolCount; ++i) {
3813 if (This->updateStateBlock->vertexShaderConstantT[i] != WINESHADERCNST_BOOL) {
3815 /* the constant for this register isn't a boolean */
3816 WARN("(%p) : Caller requested a boolean where stateblock (%p) entry is a %s. Returning D3DERR_INVALIDCALL\n", This,This->updateStateBlock,
3817 This->updateStateBlock->vertexShaderConstantT[i] == WINESHADERCNST_INTEGER ? "integer" : "float");
3818 return D3DERR_INVALIDCALL;
3822 GET_SHADER_CONSTANT(vertexShaderConstantB, BoolCount, 1);
3826 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
3827 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3830 SET_SHADER_CONSTANT(vertexShaderConstantI, Vector4iCount, 4);
3832 /* populate the bitmap that says which constant type we should load */
3833 for (i = StartRegister; i < StartRegister + Vector4iCount; ++i) {
3834 This->updateStateBlock->changed.vertexShaderConstants[i] = TRUE;
3835 This->updateStateBlock->set.vertexShaderConstants[i] = TRUE;
3836 This->updateStateBlock->vertexShaderConstantT[i] = WINESHADERCNST_INTEGER;
3837 TRACE("(%p) : Setting vsi %d to %d\n", This->updateStateBlock, i, pConstantData[i - StartRegister]);
3843 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
3844 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3847 /* verify that the requested shader constant was populated with a integer */
3848 for (i = StartRegister; i < Vector4iCount; ++i) {
3849 if (This->updateStateBlock->vertexShaderConstantT[i] != WINESHADERCNST_INTEGER) {
3851 /* the constant for this register isn't a integer */
3852 WARN("(%p) : Caller requested a integer where stateblock (%p) entry is a %s. Returning D3DERR_INVALIDCALL\n", This, This->updateStateBlock,
3853 This->updateStateBlock->vertexShaderConstantT[i] == WINESHADERCNST_BOOL ? "boolean" : "float");
3854 return D3DERR_INVALIDCALL;
3858 GET_SHADER_CONSTANT(vertexShaderConstantI, Vector4iCount, 4);
3863 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
3864 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3867 SET_SHADER_CONSTANT(vertexShaderConstantF, Vector4fCount, 4);
3869 /* populate the bitmap that says which constant type we should load */
3870 for (i = StartRegister; i < StartRegister + Vector4fCount; ++i) {
3871 This->updateStateBlock->changed.vertexShaderConstants[i] = TRUE;
3872 This->updateStateBlock->set.vertexShaderConstants[i] = TRUE;
3873 This->updateStateBlock->vertexShaderConstantT[i] = WINESHADERCNST_FLOAT;
3874 TRACE("(%p) : Setting vsf %d to %f\n", This->updateStateBlock, i, pConstantData[i - StartRegister]);
3879 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
3880 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3883 /* verify that the requested shader constant was populated with a float */
3884 for (i = StartRegister; i < Vector4fCount; ++i) {
3885 if (This->updateStateBlock->vertexShaderConstantT[i] != WINESHADERCNST_FLOAT) {
3887 /* the constant for this register isn't a float */
3888 WARN("(%p) : Caller requested a float where stateblock (%p) entry is a %s. Returning D3DERR_INVALIDCALL\n", This, This->updateStateBlock,
3889 This->updateStateBlock->vertexShaderConstantT[i] == WINESHADERCNST_BOOL ? "boolean" : "integer");
3890 return D3DERR_INVALIDCALL;
3896 GET_SHADER_CONSTANT(vertexShaderConstantF, Vector4fCount, 4);
3901 #undef SET_SHADER_CONSTANT
3902 #undef GET_SHADER_CONSTANT
3905 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
3907 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3908 IWineD3DPixelShader *oldpShader = This->updateStateBlock->pixelShader;
3909 static BOOL showFixmes = TRUE;
3911 This->updateStateBlock->pixelShader = pShader;
3912 This->updateStateBlock->changed.pixelShader = TRUE;
3913 This->updateStateBlock->set.pixelShader = TRUE;
3915 if (pShader == NULL) {
3916 /* clear down the shader */
3917 TRACE("Clear down the shader\n");
3920 FIXME("(%p) : stub pShader(%p)\n", This, pShader);
3925 /* Handle recording of state blocks */
3926 if (This->isRecordingState) {
3927 TRACE("Recording... not performing anything\n");
3931 * TODO: merge HAL shaders context switching from prototype
3934 /* manage reference counting. */
3935 if (pShader != NULL) {
3936 IWineD3DPixelShader_GetParent(pShader, &parent); /* get parent adds a ref for us*/
3939 if (oldpShader != NULL) {
3940 IWineD3DPixelShader_GetParent(oldpShader, &parent);
3941 IUnknown_Release(parent); /* once for the getparent */
3942 IUnknown_Release(parent); /* and once for the ref */
3948 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3949 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3951 if (ppShader == NULL) {
3952 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
3953 return D3DERR_INVALIDCALL;
3956 *ppShader = This->updateStateBlock->pixelShader;
3957 if (NULL != ppShader) {
3958 IWineD3DPixelShader_AddRef(*ppShader);
3960 TRACE("(%p) : returning %p\n", This, *ppShader);
3964 #define GET_SHADER_CONSTANT(_pixelshaderconstant, _count, _sizecount) \
3965 count = min(_count, MAX_PSHADER_CONSTANTS - (StartRegister + 1)); \
3966 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3967 return D3DERR_INVALIDCALL; \
3968 memcpy(pConstantData, This->updateStateBlock->_pixelshaderconstant + (StartRegister * _sizecount), count * (sizeof(*pConstantData) * _sizecount)); \
3971 #define SET_SHADER_CONSTANT(_pixelshaderconstant, _count, _sizecount) \
3972 int count = min(_count, MAX_PSHADER_CONSTANTS - (StartRegister + 1)); \
3973 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3974 return D3DERR_INVALIDCALL; \
3975 memcpy(This->updateStateBlock->_pixelshaderconstant + (StartRegister * _sizecount), pConstantData, count * (sizeof(*pConstantData) * _sizecount)); \
3976 This->updateStateBlock->changed.pixelShader = TRUE; \
3977 This->updateStateBlock->set.pixelShader = TRUE;
3980 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
3981 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3984 SET_SHADER_CONSTANT(pixelShaderConstantB, BoolCount, 1);
3986 /* populate the bitmap that says which constant type we should load */
3987 for (i = StartRegister; i < BoolCount + StartRegister; ++i) {
3988 This->updateStateBlock->changed.pixelShaderConstants[i] = TRUE;
3989 This->updateStateBlock->set.pixelShaderConstants[i] = TRUE;
3990 This->updateStateBlock->pixelShaderConstantT[i] = WINESHADERCNST_BOOL;
3991 TRACE("(%p) : Setting psb %d to %d\n", This->updateStateBlock, i, pConstantData[i - StartRegister]);
3998 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
3999 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4002 /* populate the bitmap that says which constant type we should load */
4003 for (i = StartRegister; i < BoolCount + StartRegister; ++i) {
4004 This->updateStateBlock->changed.pixelShaderConstants[i] = TRUE;
4005 This->updateStateBlock->set.pixelShaderConstants[i] = TRUE;
4006 This->updateStateBlock->pixelShaderConstantT[i] = WINESHADERCNST_BOOL;
4007 TRACE("(%p) : Setting psb %d to %d\n", This->updateStateBlock, i, pConstantData[i - StartRegister]);
4010 GET_SHADER_CONSTANT(pixelShaderConstantB, BoolCount, 1);
4015 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
4016 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4019 SET_SHADER_CONSTANT(pixelShaderConstantI, Vector4iCount, 4);
4021 /* populate the bitmap that says which constant type we should load */
4022 for (i = StartRegister; i < Vector4iCount + StartRegister; ++i) {
4023 This->updateStateBlock->changed.pixelShaderConstants[i] = TRUE;
4024 This->updateStateBlock->set.pixelShaderConstants[i] = TRUE;
4025 This->updateStateBlock->pixelShaderConstantT[i] = WINESHADERCNST_INTEGER;
4026 TRACE("(%p) : Setting psb %d to %d\n", This->updateStateBlock, i, pConstantData[i - StartRegister]);
4032 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
4033 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4036 /* verify that the requested shader constant was populated with a integer */
4037 for (i = StartRegister; i < Vector4iCount; ++i) {
4038 if (WINESHADERCNST_INTEGER != This->updateStateBlock->pixelShaderConstantT[i]) {
4040 /* the constant for this register isn't a integer */
4041 WARN("(%p) : Caller requested a integer where stateblock (%p) entry is a %s. Returning D3DERR_INVALIDCALL\n", This, This->updateStateBlock,
4042 WINESHADERCNST_BOOL == This->updateStateBlock->vertexShaderConstantT[i] ? "boolean" : "float");
4043 return D3DERR_INVALIDCALL;
4047 GET_SHADER_CONSTANT(pixelShaderConstantI, Vector4iCount, 4);
4052 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
4053 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4055 SET_SHADER_CONSTANT(pixelShaderConstantF, Vector4fCount, 4);
4057 /* populate the bitmap that says which constant type we should load */
4058 for (i = StartRegister; i < Vector4fCount + StartRegister; ++i) {
4059 This->updateStateBlock->changed.pixelShaderConstants[i] = TRUE;
4060 This->updateStateBlock->set.pixelShaderConstants[i] = TRUE;
4061 This->updateStateBlock->pixelShaderConstantT[i] = WINESHADERCNST_FLOAT;
4062 TRACE("(%p) : Setting psb %d to %f\n", This->updateStateBlock, i, pConstantData[i - StartRegister]);
4068 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
4069 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4072 /* verify that the requested shader constant was populated with a integer */
4073 for (i = StartRegister; i < Vector4fCount; ++i) {
4074 if (WINESHADERCNST_FLOAT != This->updateStateBlock->pixelShaderConstantT[i]) {
4076 /* the constant for this register isn't a float */
4077 WARN("(%p) : Caller requested a integer where stateblock (%p) entry is a %s. Returning D3DERR_INVALIDCALL\n", This, This->updateStateBlock,
4078 WINESHADERCNST_BOOL == This->updateStateBlock->vertexShaderConstantT[i] ? "boolean" : "integer");
4079 return D3DERR_INVALIDCALL;
4083 GET_SHADER_CONSTANT(pixelShaderConstantF, Vector4fCount, 4);
4088 #undef SET_SHADER_CONSTANT
4089 #undef GET_SHADER_CONSTANT
4091 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
4092 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4093 FIXME("(%p) : stub\n", This);
4098 * Apply / Get / Set Texture Stage States
4099 * TODO: Verify against dx9 definitions
4102 /* NOTE: It's expected that this function is going to be called lots of times with the same stage active, so make it the callers responsibility to GLACTIVETEXTURE(Stage) for better state management. Set the correct Texture unit active before callnig ApplyTextureStageState */
4103 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
4104 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4105 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
4106 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4108 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4110 /* Check that the stage is within limits */
4111 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4112 TRACE("Attempt to access invalid texture rejected\n");
4119 case WINED3DTSS_ALPHAOP :
4120 case WINED3DTSS_COLOROP :
4121 /* nothing to do as moved to drawprim for now */
4123 case WINED3DTSS_ADDRESSW :
4124 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
4125 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
4126 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
4129 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
4130 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
4131 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
4132 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
4135 case WINED3DTSS_TEXCOORDINDEX :
4137 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
4139 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
4140 one flag, you can still specify an index value, which the system uses to
4141 determine the texture wrapping mode.
4142 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
4143 means use the vertex position (camera-space) as the input texture coordinates
4144 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
4145 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
4146 to the TEXCOORDINDEX value */
4149 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
4151 switch (Value & 0xFFFF0000) {
4152 case D3DTSS_TCI_PASSTHRU:
4153 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
4154 glDisable(GL_TEXTURE_GEN_S);
4155 glDisable(GL_TEXTURE_GEN_T);
4156 glDisable(GL_TEXTURE_GEN_R);
4157 glDisable(GL_TEXTURE_GEN_Q);
4158 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
4161 case D3DTSS_TCI_CAMERASPACEPOSITION:
4162 /* CameraSpacePosition means use the vertex position, transformed to camera space,
4163 as the input texture coordinates for this stage's texture transformation. This
4164 equates roughly to EYE_LINEAR */
4166 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4167 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4168 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4169 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4170 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4172 glMatrixMode(GL_MODELVIEW);
4175 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4176 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4177 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4178 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4181 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
4182 glEnable(GL_TEXTURE_GEN_S);
4183 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4184 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4185 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4186 glEnable(GL_TEXTURE_GEN_T);
4187 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4188 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4189 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4190 glEnable(GL_TEXTURE_GEN_R);
4191 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4192 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4193 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4197 case D3DTSS_TCI_CAMERASPACENORMAL:
4199 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4200 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4201 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4202 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4203 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4204 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
4206 glMatrixMode(GL_MODELVIEW);
4209 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4210 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4211 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4212 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4215 glEnable(GL_TEXTURE_GEN_S);
4216 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4217 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4218 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4219 glEnable(GL_TEXTURE_GEN_T);
4220 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4221 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4222 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4223 glEnable(GL_TEXTURE_GEN_R);
4224 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4225 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4226 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4231 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
4233 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4234 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4235 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4236 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4237 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4238 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
4240 glMatrixMode(GL_MODELVIEW);
4243 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4244 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4245 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4246 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4249 glEnable(GL_TEXTURE_GEN_S);
4250 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4251 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4252 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4253 glEnable(GL_TEXTURE_GEN_T);
4254 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4255 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4256 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4257 glEnable(GL_TEXTURE_GEN_R);
4258 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4259 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4260 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4265 /* Unhandled types: */
4268 /* ? disable GL_TEXTURE_GEN_n ? */
4269 glDisable(GL_TEXTURE_GEN_S);
4270 glDisable(GL_TEXTURE_GEN_T);
4271 glDisable(GL_TEXTURE_GEN_R);
4272 glDisable(GL_TEXTURE_GEN_Q);
4273 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
4280 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
4281 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);
4284 case WINED3DTSS_BUMPENVMAT00 :
4285 case WINED3DTSS_BUMPENVMAT01 :
4286 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
4288 case WINED3DTSS_BUMPENVMAT10 :
4289 case WINED3DTSS_BUMPENVMAT11 :
4290 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
4293 case WINED3DTSS_BUMPENVLSCALE :
4294 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4297 case WINED3DTSS_BUMPENVLOFFSET :
4298 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4301 case WINED3DTSS_RESULTARG :
4302 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4306 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
4307 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4316 * Get / Set Texture Stage States
4317 * TODO: Verify against dx9 definitions
4319 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
4320 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4322 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4324 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4326 /* Reject invalid texture units */
4327 if (Stage >= GL_LIMITS(textures)) {
4328 TRACE("Attempt to access invalid texture rejected\n");
4329 return D3DERR_INVALIDCALL;
4332 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
4333 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
4334 This->updateStateBlock->textureState[Stage][Type] = Value;
4339 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4340 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4341 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4342 *pValue = This->updateStateBlock->textureState[Stage][Type];
4349 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4351 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4352 IWineD3DBaseTexture *oldTexture;
4354 oldTexture = This->updateStateBlock->textures[Stage];
4355 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
4357 #if 0 /* TODO: check so vertex textures */
4358 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
4359 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
4364 /* Reject invalid texture units */
4365 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4366 WARN("Attempt to access invalid texture rejected\n");
4367 return D3DERR_INVALIDCALL;
4370 oldTexture = This->updateStateBlock->textures[Stage];
4371 TRACE("GL_LIMITS %d\n",GL_LIMITS(textures));
4372 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
4374 This->updateStateBlock->set.textures[Stage] = TRUE;
4375 This->updateStateBlock->changed.textures[Stage] = TRUE;
4376 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
4377 This->updateStateBlock->textures[Stage] = pTexture;
4379 /* Handle recording of state blocks */
4380 if (This->isRecordingState) {
4381 TRACE("Recording... not performing anything\n");
4385 /** NOTE: MSDN says that setTexture increases the reference count,
4386 * and the the application nust set the texture back to null (or have a leaky application),
4387 * This means we should pass the refcount upto the parent
4388 *******************************/
4389 if (NULL != This->updateStateBlock->textures[Stage]) {
4390 IUnknown *textureParent;
4391 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[Stage], (IUnknown **)&textureParent);
4392 /** NOTE: GetParent will increase the ref count for me, I won't clean up until the texture is set to NULL **/
4395 if (NULL != oldTexture) {
4396 IUnknown *textureParent;
4397 IWineD3DBaseTexture_GetParent(oldTexture, (IUnknown **)&textureParent);
4398 IUnknown_Release(textureParent);
4399 IUnknown_Release(textureParent); /** NOTE: Twice because GetParent adds a ref **/
4406 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4407 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4408 TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
4410 /* Reject invalid texture units */
4411 if (Stage >= GL_LIMITS(textures)) {
4412 TRACE("Attempt to access invalid texture rejected\n");
4413 return D3DERR_INVALIDCALL;
4415 *ppTexture=This->updateStateBlock->textures[Stage];
4417 IWineD3DBaseTexture_AddRef(*ppTexture);
4419 return D3DERR_INVALIDCALL;
4426 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type,
4427 IWineD3DSurface **ppBackBuffer) {
4428 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4429 IWineD3DSwapChain *swapChain;
4432 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4434 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4436 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4437 IWineD3DSwapChain_Release(swapChain);
4439 *ppBackBuffer = NULL;
4444 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4445 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4446 WARN("(%p) : stub, calling idirect3d for now\n", This);
4447 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4450 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
4451 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4452 IWineD3DSwapChain *swapChain;
4455 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4457 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4458 IWineD3DSwapChain_Release(swapChain);
4460 FIXME("(%p) Error getting display mode\n", This);
4465 * Stateblock related functions
4468 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4469 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4470 IWineD3DStateBlockImpl *object;
4471 TRACE("(%p)", This);
4472 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4473 if (NULL == object ) {
4474 FIXME("(%p)Error allocating memory for stateblock\n", This);
4475 return E_OUTOFMEMORY;
4477 TRACE("(%p) creted object %p\n", This, object);
4478 object->wineD3DDevice= This;
4479 /** FIXME: object->parent = parent; **/
4480 object->parent = NULL;
4481 object->blockType = WINED3DSBT_ALL;
4483 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
4485 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4486 This->updateStateBlock = object;
4487 This->isRecordingState = TRUE;
4489 TRACE("(%p) recording stateblock %p\n",This , object);
4493 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4494 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4496 if (!This->isRecordingState) {
4497 FIXME("(%p) not recording! returning error\n", This);
4498 *ppStateBlock = NULL;
4499 return D3DERR_INVALIDCALL;
4502 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4503 This->isRecordingState = FALSE;
4504 This->updateStateBlock = This->stateBlock;
4505 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4506 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4507 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4512 * Scene related functions
4514 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4515 /* At the moment we have no need for any functionality at the beginning
4517 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4518 TRACE("(%p) : stub\n", This);
4522 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4523 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4524 TRACE("(%p)\n", This);
4526 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4528 checkGLcall("glFlush");
4530 TRACE("End Scene\n");
4531 if(This->renderTarget != NULL) {
4533 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4534 IUnknown *targetContainer = NULL;
4535 if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
4536 || D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
4537 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
4538 /** always dirtify for now. we must find a better way to see that surface have been modified
4539 (Modifications should will only occur via draw-primitive, but we do need better locking
4540 switching to render-to-texture should remove the overhead though.
4542 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4543 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
4544 IWineD3DSurface_PreLoad(This->renderTarget);
4545 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4546 IUnknown_Release(targetContainer);
4549 This->sceneEnded = TRUE;
4554 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4555 CONST RECT* pSourceRect, CONST RECT* pDestRect,
4556 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4557 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4558 IWineD3DSwapChain *swapChain = NULL;
4560 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4562 TRACE("(%p) Presenting the frame\n", This);
4564 for(i = 0 ; i < swapchains ; i ++) {
4566 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4567 TRACE("presentinng chain %d, %p\n", i, swapChain);
4568 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4569 IWineD3DSwapChain_Release(swapChain);
4575 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4576 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4577 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4579 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4580 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4581 when the depth-buffer format does not contain stencil buffer information, this method fails. */
4582 GLbitfield glMask = 0;
4583 GLboolean old_ztest;
4584 GLfloat old_z_clear_value;
4585 GLint old_stencil_clear_value;
4586 GLfloat old_color_clear_value[4];
4588 CONST D3DRECT* curRect;
4590 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4591 Count, pRects, Flags, Z, Stencil);
4595 glEnable(GL_SCISSOR_TEST);
4596 checkGLcall("glEnable GL_SCISSOR_TEST");
4598 if (Count > 0 && pRects) {
4604 /* Only set the values up once, as they are not changing */
4605 if (Flags & D3DCLEAR_STENCIL) {
4606 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4607 glClearStencil(Stencil);
4608 checkGLcall("glClearStencil");
4609 glMask = glMask | GL_STENCIL_BUFFER_BIT;
4610 glStencilMask(0xFFFFFFFF);
4613 if (Flags & D3DCLEAR_ZBUFFER) {
4614 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4615 glDepthMask(GL_TRUE);
4616 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4618 checkGLcall("glClearDepth");
4619 glMask = glMask | GL_DEPTH_BUFFER_BIT;
4622 if (Flags & D3DCLEAR_TARGET) {
4623 TRACE("Clearing screen with glClear to color %lx\n", Color);
4624 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4625 glClearColor(D3DCOLOR_R(Color),
4629 checkGLcall("glClearColor");
4631 /* Clear ALL colors! */
4632 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4633 glMask = glMask | GL_COLOR_BUFFER_BIT;
4636 /* Now process each rect in turn */
4637 for (i = 0; i < Count || i == 0; i++) {
4640 /* Note gl uses lower left, width/height */
4641 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4642 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4643 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4644 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4645 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4646 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4647 checkGLcall("glScissor");
4649 glScissor(This->stateBlock->viewport.X,
4650 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
4651 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4652 This->stateBlock->viewport.Width,
4653 This->stateBlock->viewport.Height);
4654 checkGLcall("glScissor");
4657 /* Clear the selected rectangle (or full screen) */
4659 checkGLcall("glClear");
4661 /* Step to the next rectangle */
4662 if (curRect) curRect = curRect + sizeof(D3DRECT);
4665 /* Restore the old values (why..?) */
4666 if (Flags & D3DCLEAR_STENCIL) {
4667 glClearStencil(old_stencil_clear_value);
4668 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4670 if (Flags & D3DCLEAR_ZBUFFER) {
4671 glDepthMask(old_ztest);
4672 glClearDepth(old_z_clear_value);
4674 if (Flags & D3DCLEAR_TARGET) {
4675 glClearColor(old_color_clear_value[0],
4676 old_color_clear_value[1],
4677 old_color_clear_value[2],
4678 old_color_clear_value[3]);
4679 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4680 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4681 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4682 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4685 glDisable(GL_SCISSOR_TEST);
4686 checkGLcall("glDisable");
4695 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4696 UINT PrimitiveCount) {
4698 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4699 This->stateBlock->streamIsUP = FALSE;
4701 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4702 debug_d3dprimitivetype(PrimitiveType),
4703 StartVertex, PrimitiveCount);
4704 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
4705 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
4711 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4712 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4713 D3DPRIMITIVETYPE PrimitiveType,
4714 INT baseVIndex, UINT minIndex,
4715 UINT NumVertices, UINT startIndex, UINT primCount) {
4717 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4719 IWineD3DIndexBuffer *pIB;
4720 D3DINDEXBUFFER_DESC IdxBufDsc;
4722 pIB = This->stateBlock->pIndexData;
4723 This->stateBlock->streamIsUP = FALSE;
4725 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
4726 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4727 minIndex, NumVertices, startIndex, baseVIndex, primCount);
4729 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4730 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4736 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
4737 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
4742 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4743 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4744 UINT VertexStreamZeroStride) {
4745 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4747 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4748 debug_d3dprimitivetype(PrimitiveType),
4749 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4751 if (This->stateBlock->streamSource[0] != NULL) {
4752 IUnknown *vertexBufferParent;
4753 IWineD3DVertexBuffer_GetParent(This->stateBlock->streamSource[0], &vertexBufferParent);
4754 IUnknown_Release(vertexBufferParent);
4755 IUnknown_Release(vertexBufferParent);
4758 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4759 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4760 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4761 This->stateBlock->streamIsUP = TRUE;
4763 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
4764 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
4765 /* stream zero settings set to null at end, as per the msdn
4766 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
4768 This->stateBlock->streamStride[0] = 0;
4769 This->stateBlock->streamSource[0] = NULL;
4771 /*stream zero settings set to null at end, as per the msdn */
4775 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4776 UINT MinVertexIndex, UINT NumVertices,
4777 UINT PrimitiveCount, CONST void* pIndexData,
4778 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4779 UINT VertexStreamZeroStride) {
4781 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4783 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4784 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4785 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
4786 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4788 if (IndexDataFormat == WINED3DFMT_INDEX16) {
4794 if (This->stateBlock->streamSource[0] != NULL) {
4795 IUnknown *vertexBufferParent;
4796 IWineD3DVertexBuffer_GetParent(This->stateBlock->streamSource[0], &vertexBufferParent);
4797 This->stateBlock->streamSource[0] = NULL;
4798 IUnknown_Release(vertexBufferParent);
4799 IUnknown_Release(vertexBufferParent);
4802 if (This->stateBlock->pIndexData) {
4803 IUnknown *indexBufferParent;
4804 IWineD3DIndexBuffer_GetParent(This->stateBlock->pIndexData, &indexBufferParent);
4805 This->stateBlock->pIndexData = NULL;
4806 IUnknown_Release(indexBufferParent);
4807 IUnknown_Release(indexBufferParent);
4810 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4811 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4812 This->stateBlock->streamIsUP = TRUE;
4813 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4815 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
4816 /* stream zero settings set to null at end as per the msdn
4817 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
4820 /* stream zero settings set to null at end as per the msdn */
4821 This->stateBlock->streamSource[0] = NULL;
4822 This->stateBlock->streamStride[0] = 0;
4827 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4828 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
4829 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4830 HRESULT hr = D3D_OK;
4831 D3DRESOURCETYPE sourceType;
4832 D3DRESOURCETYPE destinationType;
4835 /* TODO: think about moving the code into IWineD3DBaseTexture */
4837 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
4839 /* verify that the source and destination textures arebn't NULL */
4840 if (NULL == pSourceTexture || NULL == pDestinationTexture) {
4841 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning D3DERR_INVALIDCALL\n",
4842 This, pSourceTexture, pDestinationTexture);
4843 hr = D3DERR_INVALIDCALL;
4846 if (pSourceTexture == pDestinationTexture) {
4847 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning D3DERR_INVALIDCALL\n",
4848 This, pSourceTexture, pDestinationTexture);
4849 hr = D3DERR_INVALIDCALL;
4851 /* Verify that the source and destination textures are the same type */
4852 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
4853 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
4855 if (sourceType != destinationType) {
4856 WARN("(%p) Sorce and destination types must match, returning D3DERR_INVALIDCALL\n",
4858 hr = D3DERR_INVALIDCALL;
4861 /* check that both textures have the identical numbers of levels */
4862 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
4863 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning D3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
4864 hr = D3DERR_INVALIDCALL;
4869 /* Make sure that the destination texture is loaded */
4870 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
4872 /* Update every surface level of the texture */
4873 levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
4875 switch (sourceType) {
4876 case D3DRTYPE_TEXTURE:
4878 IWineD3DSurface *srcSurface;
4879 IWineD3DSurface *destSurface;
4881 for (i = 0 ; i < levels ; ++i) {
4882 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture, i, &srcSurface);
4883 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
4884 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4885 IWineD3DSurface_Release(srcSurface);
4886 IWineD3DSurface_Release(destSurface);
4888 WARN("(%p) : Call to update surface failed\n", This);
4894 case D3DRTYPE_CUBETEXTURE:
4896 IWineD3DSurface *srcSurface;
4897 IWineD3DSurface *destSurface;
4898 D3DCUBEMAP_FACES faceType;
4900 for (i = 0 ; i < levels ; ++i) {
4901 /* Update each cube face */
4902 for (faceType = D3DCUBEMAP_FACE_POSITIVE_X; faceType <= D3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
4903 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture, faceType, i, &srcSurface);
4905 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4907 TRACE("Got srcSurface %p\n", srcSurface);
4909 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
4911 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4913 TRACE("Got desrSurface %p\n", destSurface);
4915 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4916 IWineD3DSurface_Release(srcSurface);
4917 IWineD3DSurface_Release(destSurface);
4919 WARN("(%p) : Call to update surface failed\n", This);
4926 #if 0 /* TODO: Add support for volume textures */
4927 case D3DRTYPE_VOLUMETEXTURE:
4929 IWineD3DVolume srcVolume = NULL;
4930 IWineD3DSurface destVolume = NULL;
4932 for (i = 0 ; i < levels ; ++i) {
4933 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture, i, &srcVolume);
4934 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
4935 hr = IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
4936 IWineD3DVolume_Release(srcSurface);
4937 IWineD3DVolume_Release(destSurface);
4939 WARN("(%p) : Call to update volume failed\n", This);
4947 FIXME("(%p) : Unsupported source and destination type\n", This);
4948 hr = D3DERR_INVALIDCALL;
4955 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
4956 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
4957 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
4958 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4960 TRACE("(%p) : stub\n", This);
4963 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
4964 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4965 /** TODO: remove remove casts to IWineD3DSurfaceImpl *
4966 * NOTE It may be best to move the code into surface to occomplish this
4967 ****************************************/
4969 WINED3DSURFACE_DESC surfaceDesc;
4970 unsigned int surfaceWidth, surfaceHeight;
4971 glDescriptor *targetGlDescription = NULL;
4972 glDescriptor *surfaceGlDescription = NULL;
4973 IWineD3DSwapChainImpl *container = NULL;
4975 IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
4976 IWineD3DSurface_GetGlDesc(pSurface, &surfaceGlDescription);
4977 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
4979 surfaceDesc.Width = &surfaceWidth;
4980 surfaceDesc.Height = &surfaceHeight;
4981 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
4982 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sureteh data is upto date)*/
4984 /* Ok, I may need to setup some kind of active swapchain reference on the device */
4985 IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
4987 /* TODO: opengl Context switching for swapchains etc... */
4988 if (NULL != container || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
4989 if (NULL != container && (pRenderTarget == container->backBuffer)) {
4990 glReadBuffer(GL_BACK);
4991 vcheckGLcall("glReadBuffer(GL_BACK)");
4992 } else if ((NULL != container && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
4993 glReadBuffer(GL_FRONT);
4994 vcheckGLcall("glReadBuffer(GL_FRONT)");
4995 } else if (pRenderTarget == This->depthStencilBuffer) {
4996 FIXME("Reading of depthstencil not yet supported\n");
4999 glReadPixels(surfaceGlDescription->target,
5000 surfaceGlDescription->level,
5003 surfaceGlDescription->glFormat,
5004 surfaceGlDescription->glType,
5005 (void *)IWineD3DSurface_GetData(pSurface));
5006 vcheckGLcall("glReadPixels(...)");
5007 if(NULL != container ){
5008 IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
5011 IWineD3DBaseTexture *container;
5012 GLenum textureDimensions = GL_TEXTURE_2D;
5014 if (D3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
5015 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
5016 IWineD3DBaseTexture_Release(container);
5018 /* TODO: 2D -> Cube surface coppies etc.. */
5019 if (surfaceGlDescription->target != textureDimensions) {
5020 FIXME("(%p) : Texture dimension mismatch\n", This);
5022 glEnable(textureDimensions);
5023 vcheckGLcall("glEnable(GL_TEXTURE_...)");
5024 /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
5025 glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
5026 vcheckGLcall("glBindTexture");
5027 glGetTexImage(surfaceGlDescription->target,
5028 surfaceGlDescription->level,
5029 surfaceGlDescription->glFormat,
5030 surfaceGlDescription->glType,
5031 (void *)IWineD3DSurface_GetData(pSurface));
5032 glDisable(textureDimensions);
5033 vcheckGLcall("glDisable(GL_TEXTURE_...)");
5040 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
5041 IWineD3DSwapChain *swapChain;
5043 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5045 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
5046 IWineD3DSwapChain_Release(swapChain);
5051 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5052 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5053 /* return a sensible default */
5055 /* TODO: If the window is minimized then validate device shold return something other than d3d_ok */
5056 FIXME("(%p) : stub\n", This);
5060 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5061 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5063 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5064 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5065 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5066 return D3DERR_INVALIDCALL;
5068 for (j = 0; j < 256; ++j) {
5069 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
5070 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5071 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
5072 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5074 TRACE("(%p) : returning\n", This);
5078 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5079 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5081 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5082 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5083 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5084 return D3DERR_INVALIDCALL;
5086 for (j = 0; j < 256; ++j) {
5087 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
5088 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5089 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
5090 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5092 TRACE("(%p) : returning\n", This);
5096 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5097 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5098 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5099 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5100 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5101 return D3DERR_INVALIDCALL;
5103 /*TODO: stateblocks */
5104 This->currentPalette = PaletteNumber;
5105 TRACE("(%p) : returning\n", This);
5109 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
5110 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5111 if (PaletteNumber == NULL) {
5112 WARN("(%p) : returning Invalid Call\n", This);
5113 return D3DERR_INVALIDCALL;
5115 /*TODO: stateblocks */
5116 *PaletteNumber = This->currentPalette;
5117 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
5121 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
5122 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5123 static BOOL showFixmes = TRUE;
5125 FIXME("(%p) : stub\n", This);
5129 This->softwareVertexProcessing = bSoftware;
5134 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
5135 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5136 static BOOL showFixmes = TRUE;
5138 FIXME("(%p) : stub\n", This);
5141 return This->softwareVertexProcessing;
5145 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
5146 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5147 IWineD3DSwapChain *swapChain;
5150 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
5152 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5154 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
5155 IWineD3DSwapChain_Release(swapChain);
5157 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
5163 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
5164 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5165 static BOOL showfixmes = TRUE;
5166 if(nSegments != 0.0f) {
5168 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
5175 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
5176 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5177 static BOOL showfixmes = TRUE;
5179 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
5185 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
5186 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5187 /** TODO: remove casts to IWineD3DSurfaceImpl
5188 * NOTE: move code to surface to accomplish this
5189 ****************************************/
5190 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
5191 int srcWidth, srcHeight;
5192 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
5193 WINED3DFORMAT destFormat, srcFormat;
5195 int destLeft, destTop;
5196 D3DPOOL srcPool, destPool;
5198 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
5199 glDescriptor *glDescription = NULL;
5200 GLenum textureDimensions = GL_TEXTURE_2D;
5201 IWineD3DBaseTexture *baseTexture;
5203 WINED3DSURFACE_DESC winedesc;
5205 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
5206 memset(&winedesc, 0, sizeof(winedesc));
5207 winedesc.Width = &srcSurfaceWidth;
5208 winedesc.Height = &srcSurfaceHeight;
5209 winedesc.Pool = &srcPool;
5210 winedesc.Format = &srcFormat;
5212 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5214 winedesc.Width = &destSurfaceWidth;
5215 winedesc.Height = &destSurfaceHeight;
5216 winedesc.Pool = &destPool;
5217 winedesc.Format = &destFormat;
5218 winedesc.Size = &destSize;
5220 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5222 if(srcPool != D3DPOOL_SYSTEMMEM || destPool != D3DPOOL_DEFAULT){
5223 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning D3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
5224 return D3DERR_INVALIDCALL;
5227 if (destFormat == WINED3DFMT_UNKNOWN) {
5228 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5229 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5231 /* Get the update surface description */
5232 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5235 /* Make sure the surface is loaded and upto date */
5236 IWineD3DSurface_PreLoad(pDestinationSurface);
5238 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
5242 /* this needs to be done in lines if the sourceRect != the sourceWidth */
5243 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
5244 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
5245 destLeft = pDestPoint ? pDestPoint->x : 0;
5246 destTop = pDestPoint ? pDestPoint->y : 0;
5249 /* This function doesn't support compressed textures
5250 the pitch is just bytesPerPixel * width */
5251 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
5252 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
5253 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
5254 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
5256 /* TODO DXT formats */
5258 if(pSourceRect != NULL && pSourceRect->top != 0){
5259 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
5261 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
5263 ,glDescription->level
5268 ,glDescription->glFormat
5269 ,glDescription->glType
5270 ,IWineD3DSurface_GetData(pSourceSurface)
5274 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
5276 /* need to lock the surface to get the data */
5277 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5280 /* TODO: Cube and volume support */
5282 /* not a whole row so we have to do it a line at a time */
5285 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
5286 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5288 for(j = destTop ; j < (srcHeight + destTop) ; j++){
5290 glTexSubImage2D(glDescription->target
5291 ,glDescription->level
5296 ,glDescription->glFormat
5297 ,glDescription->glType
5298 ,data /* could be quicker using */
5303 } else { /* Full width, so just write out the whole texture */
5305 if (WINED3DFMT_DXT1 == destFormat ||
5306 WINED3DFMT_DXT2 == destFormat ||
5307 WINED3DFMT_DXT3 == destFormat ||
5308 WINED3DFMT_DXT4 == destFormat ||
5309 WINED3DFMT_DXT5 == destFormat) {
5310 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
5311 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
5312 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
5313 FIXME("Updating part of a compressed texture is not supported at the moment\n");
5314 } if (destFormat != srcFormat) {
5315 FIXME("Updating mixed format compressed texture is not curretly support\n");
5317 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
5318 glDescription->level,
5319 glDescription->glFormatInternal,
5324 IWineD3DSurface_GetData(pSourceSurface));
5327 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
5332 if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
5334 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
5335 to repack the data from pow2Width/Height to expected Width,Height, this makes the
5336 data returned by GetData non-power2 width/height with hardware non-power2
5337 pow2Width/height are set to surface width height, repacking isn't needed so it
5338 doesn't matter which function gets called. */
5339 glTexSubImage2D(glDescription->target
5340 ,glDescription->level
5345 ,glDescription->glFormat
5346 ,glDescription->glType
5347 ,IWineD3DSurface_GetData(pSourceSurface)
5351 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
5352 glTexSubImage2D(glDescription->target
5353 ,glDescription->level
5356 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
5357 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
5358 ,glDescription->glFormat
5359 ,glDescription->glType
5360 ,IWineD3DSurface_GetData(pSourceSurface)
5366 checkGLcall("glTexSubImage2D");
5368 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
5369 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
5370 * surface bigger than it needs to be hmm.. */
5371 if (D3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
5372 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
5373 IWineD3DBaseTexture_Release(baseTexture);
5376 glDisable(textureDimensions); /* This needs to be managed better.... */
5382 /* Implementation details at http://developer.nvidia.com/attach/6494
5384 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
5385 hmm.. no longer supported use
5386 OpenGL evaluators or tessellate surfaces within your application.
5389 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
5390 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
5391 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5392 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
5393 FIXME("(%p) : Stub\n", This);
5398 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
5399 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
5400 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5401 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
5402 FIXME("(%p) : Stub\n", This);
5406 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5407 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5408 TRACE("(%p) Handle(%d)\n", This, Handle);
5409 FIXME("(%p) : Stub\n", This);
5413 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
5414 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
5415 fill a surface with a block of color! */
5416 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5417 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
5418 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
5419 IWineD3DSwapChainImpl *container = NULL;
5420 BOOL isRenderTarget = FALSE;
5421 unsigned int width, height;
5422 unsigned int top, left;
5425 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
5427 if (surface->resource.pool != D3DPOOL_DEFAULT) {
5428 FIXME("call to colorfill with non D3DPOOL_DEFAULT surface\n");
5429 return D3DERR_INVALIDCALL;
5432 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
5433 if (D3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
5434 if (D3DUSAGE_RENDERTARGET & surface->resource.usage) {
5435 /* TODO: make sure we set everything back to the way it was, and context management!
5436 glGetIntegerv(GL_READ_BUFFER, &prev_read);
5437 vcheckGLcall("glIntegerv");
5438 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
5439 vcheckGLcall("glIntegerv");
5441 TRACE("Color fill to render targets may cause some graphics issues\n");
5442 if (pSurface == container->frontBuffer) {
5443 glDrawBuffer(GL_FRONT);
5445 glDrawBuffer(GL_BACK);
5448 if (D3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
5449 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld\n", surface, surface->resource.usage);
5451 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
5453 if (container != NULL) {
5454 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5456 /* we can use GL_STENCIL_INDEX etc...*/
5459 if (container != NULL) {
5460 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5462 isRenderTarget = TRUE;
5464 /* TODO: drawing to GL_FRONT and GL_BACK */
5465 /* TODO: see if things can be speeded up by using the correct
5466 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
5467 if (pRect == NULL) {
5470 width = surface->currentDesc.Width;
5471 height = surface->currentDesc.Height;
5475 width = pRect->x2 - left;
5476 height = pRect->y2 - top;
5479 data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
5480 /* Create a 'line' of color color, in the correct format for the surface */
5481 for (u = 0 ; u < width ; u ++) {
5486 if (isRenderTarget == FALSE) {
5487 glDescriptor *glDesc;
5488 IWineD3DSurface_PreLoad(pSurface);
5490 /* draw a block of the coloured line on the sufrace */
5491 IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
5492 for (v = 0 ; v< height;v++) {
5493 glTexSubImage2D(glDesc->target
5494 ,glDesc->level /* level */
5504 checkGLcall("glTexSubImage2D");
5506 glDisable(glDesc->target);
5508 /** FIXME: Using GLClear may be faster **/
5509 glRasterPos2i(left, top);
5510 glPixelZoom((float)width ,(float)height);
5511 glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
5512 checkGLcall("glDrawPixels");
5514 HeapFree(GetProcessHeap(), 0, data);
5520 /* rendertarget and deptth stencil functions */
5521 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
5522 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5524 /* FIXME: Implelent RenderTargetIndex >0 */
5525 if(RenderTargetIndex > 0)
5526 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
5528 *ppRenderTarget = This->renderTarget;
5529 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
5530 /* Note inc ref on returned surface */
5531 if(*ppRenderTarget != NULL)
5532 IWineD3DSurface_AddRef(*ppRenderTarget);
5536 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5537 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5538 *ppZStencilSurface = This->depthStencilBuffer;
5539 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
5541 if(*ppZStencilSurface != NULL) {
5542 /* Note inc ref on returned surface */
5543 IWineD3DSurface_AddRef(*ppZStencilSurface);
5548 /* internal static helper functions */
5549 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5550 IWineD3DSurface *RenderSurface);
5552 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5553 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5554 HRESULT hr = D3D_OK;
5555 WINED3DVIEWPORT viewport;
5557 TRACE("(%p) Swapping rendertarget\n",This);
5558 if (RenderTargetIndex > 0) {
5559 FIXME("(%p) Render targets other than the first are not supported\n",This);
5560 RenderTargetIndex = 0;
5563 /* MSDN says that null disables the render target
5564 but a device must always be associated with a render target
5565 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5567 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5570 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5571 FIXME("Trying to set render target 0 to NULL\n");
5572 return D3DERR_INVALIDCALL;
5574 /* TODO: replace Impl* usage with interface usage */
5575 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & D3DUSAGE_RENDERTARGET) {
5576 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);
5577 return D3DERR_INVALIDCALL;
5579 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
5580 * builds, but I think wine counts as a 'debug' build for now.
5581 ******************************/
5582 /* If we are trying to set what we already have, don't bother */
5583 if (pRenderTarget == This->renderTarget) {
5584 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5586 /* Otherwise, set the render target up */
5588 if (FALSE == This->sceneEnded) {
5589 IWineD3DDevice_EndScene(iface);
5591 TRACE("clearing renderer\n");
5592 /* IWineD3DDeviceImpl_CleanRender(iface); */
5593 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5594 depending on the renter target implementation being used.
5595 A shared context implementation will share all buffers between all rendertargets (including swapchains),
5596 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5597 stencil buffer and incure an extra memory overhead */
5598 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
5601 if (SUCCEEDED(hr)) {
5602 /* Finally, reset the viewport as the MSDN states. */
5603 /* TODO: Replace impl usage */
5604 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
5605 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
5608 viewport.MaxZ = 1.0f;
5609 viewport.MinZ = 0.0f;
5610 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
5612 FIXME("Unknown error setting the render target\n");
5614 This->sceneEnded = FALSE;
5618 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
5619 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5620 HRESULT hr = D3D_OK;
5621 IWineD3DSurface *tmp;
5623 TRACE("(%p) Swapping z-buffer\n",This);
5625 if (pNewZStencil == This->stencilBufferTarget) {
5626 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5628 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5629 * depending on the renter target implementation being used.
5630 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5631 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5632 * stencil buffer and incure an extra memory overhead
5633 ******************************************************/
5636 tmp = This->stencilBufferTarget;
5637 This->stencilBufferTarget = pNewZStencil;
5638 /* should we be calling the parent or the wined3d surface? */
5639 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
5640 if (NULL != tmp) IWineD3DSurface_Release(tmp);
5642 /** TODO: glEnable/glDisable on depth/stencil depending on
5643 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
5644 **********************************************************/
5651 #ifdef GL_VERSION_1_3
5652 /* Internal functions not in DirectX */
5653 /** TODO: move this off to the opengl context manager
5654 *(the swapchain doesn't need to know anything about offscreen rendering!)
5655 ****************************************************/
5657 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
5659 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5661 TRACE("(%p), %p\n", This, swapchain);
5663 if (swapchain->win != swapchain->drawable) {
5664 /* Set everything back the way it ws */
5665 swapchain->render_ctx = swapchain->glCtx;
5666 swapchain->drawable = swapchain->win;
5671 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
5672 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
5673 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5676 unsigned int height;
5677 WINED3DFORMAT format;
5678 WINED3DSURFACE_DESC surfaceDesc;
5679 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5680 surfaceDesc.Width = &width;
5681 surfaceDesc.Height = &height;
5682 surfaceDesc.Format = &format;
5683 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5685 /* I need a get width/height function (and should do something with the format) */
5686 for (i = 0; i < CONTEXT_CACHE; ++i) {
5687 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
5688 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
5689 the pSurface can be set to 0 allowing it to be reused from cache **/
5690 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
5691 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
5692 *context = &This->contextCache[i];
5695 if (This->contextCache[i].Width == 0) {
5696 This->contextCache[i].pSurface = pSurface;
5697 This->contextCache[i].Width = width;
5698 This->contextCache[i].Height = height;
5699 *context = &This->contextCache[i];
5703 if (i == CONTEXT_CACHE) {
5704 int minUsage = 0x7FFFFFFF; /* MAX_INT */
5705 glContext *dropContext = 0;
5706 for (i = 0; i < CONTEXT_CACHE; i++) {
5707 if (This->contextCache[i].usedcount < minUsage) {
5708 dropContext = &This->contextCache[i];
5709 minUsage = This->contextCache[i].usedcount;
5712 /* clean up the context (this doesn't work for ATI at the moment */
5714 glXDestroyContext(swapchain->display, dropContext->context);
5715 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
5718 dropContext->Width = 0;
5719 dropContext->pSurface = pSurface;
5720 *context = dropContext;
5722 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
5723 for (i = 0; i < CONTEXT_CACHE; i++) {
5724 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
5728 if (*context != NULL)
5731 return E_OUTOFMEMORY;
5735 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
5736 * the functionality needs splitting up so that we don't do more than we should do.
5737 * this only seems to impact performance a little.
5738 ******************************/
5739 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5740 IWineD3DSurface *RenderSurface) {
5741 HRESULT ret = D3DERR_INVALIDCALL;
5744 * Currently only active for GLX >= 1.3
5745 * for others versions we'll have to use GLXPixmaps
5747 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
5748 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
5749 * so only check OpenGL version
5750 * ..........................
5751 * I don't believe that it is a problem with NVidia headers,
5752 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
5753 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
5755 * Your application will report GLX version 1.2 on glXQueryVersion.
5756 * However, it is safe to call the GLX 1.3 functions as described below.
5758 #if defined(GL_VERSION_1_3)
5760 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5761 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
5762 IWineD3DSurface *tmp;
5763 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
5764 GLXFBConfig* cfgs = NULL;
5768 IWineD3DSwapChain *currentSwapchain;
5769 IWineD3DSwapChainImpl *swapchain;
5770 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
5771 * but switch them off if the StencilSurface is set to NULL
5772 ** *********************************************************/
5773 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
5774 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
5777 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
5778 it StencilSurface != NULL && zBufferTarget == NULL switch it on
5781 #define PUSH1(att) attribs[nAttribs++] = (att);
5782 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
5784 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
5786 /** TODO: remove the reff to Impl (context manager should fix this!) **/
5787 IWineD3DSwapChainImpl *impSwapChain;
5788 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
5789 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
5790 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
5795 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
5796 PUSH2(GLX_X_RENDERABLE, TRUE);
5797 PUSH2(GLX_DOUBLEBUFFER, TRUE);
5798 TRACE("calling makeglcfg\n");
5799 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
5802 TRACE("calling chooseFGConfig\n");
5803 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5806 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
5807 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
5808 why we failed and only show this message once! */
5809 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"); /**/
5811 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
5812 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
5813 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
5814 PUSH2(GLX_DOUBLEBUFFER, FALSE);
5815 TRACE("calling makeglcfg\n");
5816 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
5818 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5825 for (i = 0; i < nCfgs; ++i) {
5826 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
5827 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
5828 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
5831 if (NULL != This->renderTarget) {
5833 vcheckGLcall("glFlush");
5834 /** This is only useful if the old render target was a swapchain,
5835 * we need to supercede this with a function that displays
5836 * the current buffer on the screen. This is easy to do in glx1.3 but
5837 * we need to do copy-write pixels in glx 1.2.
5838 ************************************************/
5839 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
5841 printf("Hit Enter to get next frame ...\n");
5847 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain) != D3D_OK) {
5848 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
5849 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
5853 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
5854 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
5855 **********************************************************************/
5856 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == D3D_OK) {
5857 /* We also need to make sure that the lights &co are also in the context of the swapchains */
5858 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
5859 TRACE("making swapchain active\n");
5860 if (RenderSurface != This->renderTarget) {
5861 if (RenderSurface == swapchain->backBuffer) {
5863 /* This could be flagged so that some operations work directly with the front buffer */
5864 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
5866 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
5868 TRACE("Error in setting current context: context %p drawable %ld !\n",
5869 impSwapChain->glCtx, impSwapChain->win);
5872 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5874 checkGLcall("glXMakeContextCurrent");
5876 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5878 else if (pbuffer_support == TRUE && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
5880 /** ********************************************************************
5881 * This is a quickly hacked out implementation of offscreen textures.
5882 * It will work in most cases but there may be problems if the client
5883 * modifies the texture directly, or expects the contents of the rendertarget
5886 * There are some real speed vs compatibility issues here:
5887 * we should really use a new context for every texture, but that eats ram.
5888 * we should also be restoring the texture to the pbuffer but that eats CPU
5889 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
5890 * but if this means reusing the display backbuffer then we need to make sure that
5891 * states are correctly preserved.
5892 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
5893 * and gain a good performance increase at the cost of compatibility.
5894 * I would suggest that, when this is the case, a user configurable flag be made
5895 * available, allowing the user to choose the best emulated experience for them.
5896 *********************************************************************/
5898 XVisualInfo *visinfo;
5899 glContext *newContext;
5901 /* Here were using a shared context model */
5902 if (D3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
5903 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5906 /* If the context doesn't exist then create a new one */
5907 /* TODO: This should really be part of findGlContext */
5908 if (NULL == newContext->context) {
5910 TRACE("making new buffer\n");
5912 PUSH2(GLX_PBUFFER_WIDTH, newContext->Width);
5913 PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
5916 newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
5918 /** ****************************************
5919 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
5921 * In future releases, we may provide the calls glXCreateNewContext,
5922 * glXQueryDrawable and glXMakeContextCurrent.
5923 * so until then we have to use glXGetVisualFromFBConfig &co..
5924 ********************************************/
5927 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
5929 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
5931 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
5935 if (NULL == newContext || NULL == newContext->context) {
5936 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5938 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
5939 if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
5940 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
5943 /* Clean up the old context */
5944 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5945 /* Set the current context of the swapchain to the new context */
5946 impSwapChain->drawable = newContext->drawable;
5947 impSwapChain->render_ctx = newContext->context;
5951 #if 1 /* Apply the stateblock to the new context
5952 FIXME: This is a bit of a hack, each context should know it's own state,
5953 the directX current directX state should then be applied to the context */
5956 IWineD3DStateBlockImpl *oldUpdateStateBlock;
5957 oldUpdateStateBlock = This->updateStateBlock;
5958 oldRecording= This->isRecordingState;
5959 This->isRecordingState = FALSE;
5960 This->updateStateBlock = This->stateBlock;
5961 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
5963 This->isRecordingState = oldRecording;
5964 This->updateStateBlock = oldUpdateStateBlock;
5969 /* clean up the current rendertargets swapchain (if it belonged to one) */
5970 if (currentSwapchain != NULL) {
5971 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
5974 /* Were done with the opengl context management, setup the rendertargets */
5976 tmp = This->renderTarget;
5977 This->renderTarget = RenderSurface;
5978 IWineD3DSurface_AddRef(This->renderTarget);
5979 IWineD3DSurface_Release(tmp);
5985 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
5986 /* Check that the container is not a swapchain member */
5988 IWineD3DSwapChain *tmpSwapChain;
5989 if (D3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
5990 This->renderUpsideDown = TRUE;
5992 This->renderUpsideDown = FALSE;
5993 IWineD3DSwapChain_Release(tmpSwapChain);
5995 /* Force updating the cull mode */
5996 TRACE("setting render state\n");
5997 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
5998 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
6000 /* Force updating projection matrix */
6001 This->last_was_rhw = FALSE;
6002 This->proj_valid = FALSE;
6010 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
6011 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
6016 if ( NULL != impSwapChain) {
6017 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
6025 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
6026 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
6027 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6028 /* TODO: the use of Impl is deprecated. */
6029 /* some basic validation checks */
6030 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
6032 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
6034 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
6035 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
6036 return D3DERR_INVALIDCALL;
6038 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
6039 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
6040 return D3DERR_INVALIDCALL;
6042 /* TODO: make the cursor 'real' */
6044 This->xHotSpot = XHotSpot;
6045 This->yHotSpot = YHotSpot;
6050 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
6051 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6052 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
6054 This->xScreenSpace = XScreenSpace;
6055 This->yScreenSpace = YScreenSpace;
6061 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
6062 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6063 TRACE("(%p) : visible(%d)\n", This, bShow);
6065 This->bCursorVisible = bShow;
6070 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
6071 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6072 TRACE("(%p) : state (%lu)\n", This, This->state);
6073 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
6074 switch (This->state) {
6077 case D3DERR_DEVICELOST:
6079 ResourceList *resourceList = This->resources;
6080 while (NULL != resourceList) {
6081 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == D3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
6082 return D3DERR_DEVICENOTRESET;
6083 resourceList = resourceList->next;
6085 return D3DERR_DEVICELOST;
6087 case D3DERR_DRIVERINTERNALERROR:
6088 return D3DERR_DRIVERINTERNALERROR;
6092 return D3DERR_DRIVERINTERNALERROR;
6096 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
6097 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6098 /** FIXME: Resource tracking needs to be done,
6099 * The closes we can do to this is set the priorities of all managed textures low
6100 * and then reset them.
6101 ***********************************************************/
6102 FIXME("(%p) : stub\n", This);
6106 HRESULT WINAPI IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
6107 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6108 /** FIXME: Resource trascking needs to be done.
6109 * in effect this pulls all non only default
6110 * textures out of video memory and deletes all glTextures (glDeleteTextures)
6111 * and should clear down the context and set it up according to pPresentationParameters
6112 ***********************************************************/
6113 FIXME("(%p) : stub\n", This);
6117 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
6118 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6119 /** FIXME: always true at the moment **/
6120 if(bEnableDialogs == FALSE) {
6121 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
6127 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
6128 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6130 FIXME("(%p) : stub\n", This);
6131 /* Setup some reasonable defaults */
6132 pParameters->AdapterOrdinal = 0; /* always for now */
6133 pParameters->DeviceType = D3DDEVTYPE_HAL; /* always for now */
6134 pParameters->hFocusWindow = 0;
6135 pParameters->BehaviorFlags =0;
6139 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
6140 IWineD3DSwapChain *swapchain;
6141 HRESULT hrc = D3D_OK;
6143 TRACE("Relaying to swapchain\n");
6145 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
6146 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (D3DGAMMARAMP *)pRamp);
6147 IWineD3DSwapChain_Release(swapchain);
6152 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
6153 IWineD3DSwapChain *swapchain;
6154 HRESULT hrc = D3D_OK;
6156 TRACE("Relaying to swapchain\n");
6158 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
6159 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
6160 IWineD3DSwapChain_Release(swapchain);
6166 /** ********************************************************
6167 * Notification functions
6168 ** ********************************************************/
6169 /** This function must be called in the release of a resource when ref == 0,
6170 * the contents of resource must still be correct,
6171 * any handels to other resource held by the caller must be closed
6172 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
6173 *****************************************************/
6174 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6175 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6176 ResourceList* resourceList;
6178 TRACE("(%p) : resource %p\n", This, resource);
6180 EnterCriticalSection(&resourceStoreCriticalSection);
6182 /* add a new texture to the frot of the linked list */
6183 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
6184 resourceList->resource = resource;
6186 /* Get the old head */
6187 resourceList->next = This->resources;
6189 This->resources = resourceList;
6190 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
6193 LeaveCriticalSection(&resourceStoreCriticalSection);
6198 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6199 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6200 ResourceList* resourceList = NULL;
6201 ResourceList* previousResourceList = NULL;
6203 TRACE("(%p) : resource %p\n", This, resource);
6206 EnterCriticalSection(&resourceStoreCriticalSection);
6208 resourceList = This->resources;
6210 while (resourceList != NULL) {
6211 if(resourceList->resource == resource) break;
6212 previousResourceList = resourceList;
6213 resourceList = resourceList->next;
6216 if (resourceList == NULL) {
6217 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
6219 LeaveCriticalSection(&resourceStoreCriticalSection);
6223 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
6225 /* make sure we don't leave a hole in the list */
6226 if (previousResourceList != NULL) {
6227 previousResourceList->next = resourceList->next;
6229 This->resources = resourceList->next;
6233 LeaveCriticalSection(&resourceStoreCriticalSection);
6239 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
6240 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6243 TRACE("(%p) : resource %p\n", This, resource);
6244 switch(IWineD3DResource_GetType(resource)){
6245 case D3DRTYPE_SURFACE:
6246 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
6248 case D3DRTYPE_TEXTURE:
6249 case D3DRTYPE_CUBETEXTURE:
6250 case D3DRTYPE_VOLUMETEXTURE:
6251 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
6252 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6253 IUnknown *textureParent;
6254 IWineD3DBaseTexture_GetParent(This->stateBlock->textures[counter], &textureParent);
6255 /* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
6256 FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter, resource, textureParent);
6257 IUnknown_Release(textureParent);
6258 This->stateBlock->textures[counter] = NULL;
6260 if (This->updateStateBlock != This->stateBlock ){
6261 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6262 IUnknown *textureParent;
6263 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[counter], &textureParent);
6264 /* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
6265 FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter, resource, textureParent);
6266 IUnknown_Release(textureParent);
6267 This->updateStateBlock->textures[counter] = NULL;
6272 case D3DRTYPE_VOLUME:
6273 /* TODO: nothing really? */
6275 case D3DRTYPE_VERTEXBUFFER:
6276 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
6279 TRACE("Cleaning up stream pointers\n");
6281 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
6282 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
6283 FINDOUT: should changes.streamSource[StreamNumber] be set ?
6285 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6286 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
6287 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
6288 This->updateStateBlock->streamSource[streamNumber] = 0;
6289 /* Set changed flag? */
6292 if (This->stateBlock != NULL ) { /* only happens if their is an error in the application, or on reset/release (because we don't manage internal tracknig properly) */
6293 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
6294 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
6295 This->stateBlock->streamSource[streamNumber] = 0;
6298 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
6299 else { /* This shouldn't happen */
6300 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
6307 case D3DRTYPE_INDEXBUFFER:
6308 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
6309 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6310 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6311 This->updateStateBlock->pIndexData = NULL;
6314 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
6315 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6316 This->stateBlock->pIndexData = NULL;
6322 FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
6327 /* Remove the resoruce from the resourceStore */
6328 IWineD3DDeviceImpl_RemoveResource(iface, resource);
6330 TRACE("Resource released\n");
6335 /** This function is to be called by the swapchain when it is released and it's ref = 0
6336 *****************************************************/
6337 void WINAPI IWineD3DDeviceImpl_SwapChainReleased(IWineD3DDevice *iface, IWineD3DSwapChain *swapChain){
6338 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6339 SwapChainList **nextSwapchain;
6340 nextSwapchain = &This->swapchains;
6342 /* Check to see if the swapchian is being used as the render target */
6343 if (This->renderTarget != NULL) {
6344 IWineD3DSurface *swapchainBackBuffer;
6346 IWineD3DSwapChain_GetBackBuffer(swapChain, 0 ,( D3DBACKBUFFER_TYPE) 0, &swapchainBackBuffer);
6347 if (This->renderTarget == swapchainBackBuffer) {
6348 /* Don't know what to do, so warn and carry on as usual (which in this case leaves the renderterget in limbo) */
6349 FIXME("Atempting to release a swapchain that is currently beuing used as a render target, behaviour is undefined\n");
6353 /* Go through the swapchain list and try to find the swapchain being released */
6354 while(*nextSwapchain != NULL && (*nextSwapchain)->swapchain != swapChain) {
6355 nextSwapchain = &(*nextSwapchain)->next;
6358 /* Check to see if we found the swapchain */
6359 if (NULL != *nextSwapchain) {
6360 /* We found the swapchain so remove it from the list */
6361 TRACE("(%p) releasing swapchain(%p)\n", iface, swapChain);
6362 HeapFree(GetProcessHeap(), 0 , *nextSwapchain);
6363 *nextSwapchain = (*nextSwapchain)->next;
6365 /* We didn't find the swapchain on the list, this can only heppen because of a programming error in wined3d */
6366 FIXME("(%p) Attempting to release a swapchain (%p) that hasn't been stored\n", iface, swapChain);
6369 TRACE("swapchain (%p) released\n", swapChain);
6373 /**********************************************************
6374 * IWineD3DDevice VTbl follows
6375 **********************************************************/
6377 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
6379 /*** IUnknown methods ***/
6380 IWineD3DDeviceImpl_QueryInterface,
6381 IWineD3DDeviceImpl_AddRef,
6382 IWineD3DDeviceImpl_Release,
6383 /*** IWineD3DDevice methods ***/
6384 IWineD3DDeviceImpl_GetParent,
6385 /*** Creation methods**/
6386 IWineD3DDeviceImpl_CreateVertexBuffer,
6387 IWineD3DDeviceImpl_CreateIndexBuffer,
6388 IWineD3DDeviceImpl_CreateStateBlock,
6389 IWineD3DDeviceImpl_CreateSurface,
6390 IWineD3DDeviceImpl_CreateTexture,
6391 IWineD3DDeviceImpl_CreateVolumeTexture,
6392 IWineD3DDeviceImpl_CreateVolume,
6393 IWineD3DDeviceImpl_CreateCubeTexture,
6394 IWineD3DDeviceImpl_CreateQuery,
6395 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
6396 IWineD3DDeviceImpl_CreateVertexDeclaration,
6397 IWineD3DDeviceImpl_CreateVertexShader,
6398 IWineD3DDeviceImpl_CreatePixelShader,
6399 /*** Odd functions **/
6400 IWineD3DDeviceImpl_EvictManagedResources,
6401 IWineD3DDeviceImpl_GetAvailableTextureMem,
6402 IWineD3DDeviceImpl_GetBackBuffer,
6403 IWineD3DDeviceImpl_GetCreationParameters,
6404 IWineD3DDeviceImpl_GetDeviceCaps,
6405 IWineD3DDeviceImpl_GetDirect3D,
6406 IWineD3DDeviceImpl_GetDisplayMode,
6407 IWineD3DDeviceImpl_GetNumberOfSwapChains,
6408 IWineD3DDeviceImpl_GetRasterStatus,
6409 IWineD3DDeviceImpl_GetSwapChain,
6410 IWineD3DDeviceImpl_Reset,
6411 IWineD3DDeviceImpl_SetDialogBoxMode,
6412 IWineD3DDeviceImpl_SetCursorProperties,
6413 IWineD3DDeviceImpl_SetCursorPosition,
6414 IWineD3DDeviceImpl_ShowCursor,
6415 IWineD3DDeviceImpl_TestCooperativeLevel,
6416 /*** Getters and setters **/
6417 IWineD3DDeviceImpl_SetClipPlane,
6418 IWineD3DDeviceImpl_GetClipPlane,
6419 IWineD3DDeviceImpl_SetClipStatus,
6420 IWineD3DDeviceImpl_GetClipStatus,
6421 IWineD3DDeviceImpl_SetCurrentTexturePalette,
6422 IWineD3DDeviceImpl_GetCurrentTexturePalette,
6423 IWineD3DDeviceImpl_SetDepthStencilSurface,
6424 IWineD3DDeviceImpl_GetDepthStencilSurface,
6425 IWineD3DDeviceImpl_SetFVF,
6426 IWineD3DDeviceImpl_GetFVF,
6427 IWineD3DDeviceImpl_SetGammaRamp,
6428 IWineD3DDeviceImpl_GetGammaRamp,
6429 IWineD3DDeviceImpl_SetIndices,
6430 IWineD3DDeviceImpl_GetIndices,
6431 IWineD3DDeviceImpl_SetLight,
6432 IWineD3DDeviceImpl_GetLight,
6433 IWineD3DDeviceImpl_SetLightEnable,
6434 IWineD3DDeviceImpl_GetLightEnable,
6435 IWineD3DDeviceImpl_SetMaterial,
6436 IWineD3DDeviceImpl_GetMaterial,
6437 IWineD3DDeviceImpl_SetNPatchMode,
6438 IWineD3DDeviceImpl_GetNPatchMode,
6439 IWineD3DDeviceImpl_SetPaletteEntries,
6440 IWineD3DDeviceImpl_GetPaletteEntries,
6441 IWineD3DDeviceImpl_SetPixelShader,
6442 IWineD3DDeviceImpl_GetPixelShader,
6443 IWineD3DDeviceImpl_SetPixelShaderConstantB,
6444 IWineD3DDeviceImpl_GetPixelShaderConstantB,
6445 IWineD3DDeviceImpl_SetPixelShaderConstantI,
6446 IWineD3DDeviceImpl_GetPixelShaderConstantI,
6447 IWineD3DDeviceImpl_SetPixelShaderConstantF,
6448 IWineD3DDeviceImpl_GetPixelShaderConstantF,
6449 IWineD3DDeviceImpl_SetRenderState,
6450 IWineD3DDeviceImpl_GetRenderState,
6451 IWineD3DDeviceImpl_SetRenderTarget,
6452 IWineD3DDeviceImpl_GetRenderTarget,
6453 IWineD3DDeviceImpl_SetSamplerState,
6454 IWineD3DDeviceImpl_GetSamplerState,
6455 IWineD3DDeviceImpl_SetScissorRect,
6456 IWineD3DDeviceImpl_GetScissorRect,
6457 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
6458 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
6459 IWineD3DDeviceImpl_SetStreamSource,
6460 IWineD3DDeviceImpl_GetStreamSource,
6461 IWineD3DDeviceImpl_SetStreamSourceFreq,
6462 IWineD3DDeviceImpl_GetStreamSourceFreq,
6463 IWineD3DDeviceImpl_SetTexture,
6464 IWineD3DDeviceImpl_GetTexture,
6465 IWineD3DDeviceImpl_SetTextureStageState,
6466 IWineD3DDeviceImpl_GetTextureStageState,
6467 IWineD3DDeviceImpl_SetTransform,
6468 IWineD3DDeviceImpl_GetTransform,
6469 IWineD3DDeviceImpl_SetVertexDeclaration,
6470 IWineD3DDeviceImpl_GetVertexDeclaration,
6471 IWineD3DDeviceImpl_SetVertexShader,
6472 IWineD3DDeviceImpl_GetVertexShader,
6473 IWineD3DDeviceImpl_SetVertexShaderConstantB,
6474 IWineD3DDeviceImpl_GetVertexShaderConstantB,
6475 IWineD3DDeviceImpl_SetVertexShaderConstantI,
6476 IWineD3DDeviceImpl_GetVertexShaderConstantI,
6477 IWineD3DDeviceImpl_SetVertexShaderConstantF,
6478 IWineD3DDeviceImpl_GetVertexShaderConstantF,
6479 IWineD3DDeviceImpl_SetViewport,
6480 IWineD3DDeviceImpl_GetViewport,
6481 IWineD3DDeviceImpl_MultiplyTransform,
6482 IWineD3DDeviceImpl_ValidateDevice,
6483 IWineD3DDeviceImpl_ProcessVertices,
6484 /*** State block ***/
6485 IWineD3DDeviceImpl_BeginStateBlock,
6486 IWineD3DDeviceImpl_EndStateBlock,
6487 /*** Scene management ***/
6488 IWineD3DDeviceImpl_BeginScene,
6489 IWineD3DDeviceImpl_EndScene,
6490 IWineD3DDeviceImpl_Present,
6491 IWineD3DDeviceImpl_Clear,
6493 IWineD3DDeviceImpl_DrawPrimitive,
6494 IWineD3DDeviceImpl_DrawIndexedPrimitive,
6495 IWineD3DDeviceImpl_DrawPrimitiveUP,
6496 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
6497 IWineD3DDeviceImpl_DrawRectPatch,
6498 IWineD3DDeviceImpl_DrawTriPatch,
6499 IWineD3DDeviceImpl_DeletePatch,
6500 IWineD3DDeviceImpl_ColorFill,
6501 IWineD3DDeviceImpl_UpdateTexture,
6502 IWineD3DDeviceImpl_UpdateSurface,
6503 IWineD3DDeviceImpl_StretchRect,
6504 IWineD3DDeviceImpl_GetRenderTargetData,
6505 IWineD3DDeviceImpl_GetFrontBufferData,
6506 /*** Internal use IWineD3DDevice methods ***/
6507 IWineD3DDeviceImpl_SetupTextureStates,
6508 /*** object tracking ***/
6509 IWineD3DDeviceImpl_SwapChainReleased,
6510 IWineD3DDeviceImpl_ResourceReleased
6514 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
6515 WINED3DRS_ALPHABLENDENABLE ,
6516 WINED3DRS_ALPHAFUNC ,
6517 WINED3DRS_ALPHAREF ,
6518 WINED3DRS_ALPHATESTENABLE ,
6520 WINED3DRS_COLORWRITEENABLE ,
6521 WINED3DRS_DESTBLEND ,
6522 WINED3DRS_DITHERENABLE ,
6523 WINED3DRS_FILLMODE ,
6524 WINED3DRS_FOGDENSITY ,
6526 WINED3DRS_FOGSTART ,
6527 WINED3DRS_LASTPIXEL ,
6528 WINED3DRS_SHADEMODE ,
6529 WINED3DRS_SRCBLEND ,
6530 WINED3DRS_STENCILENABLE ,
6531 WINED3DRS_STENCILFAIL ,
6532 WINED3DRS_STENCILFUNC ,
6533 WINED3DRS_STENCILMASK ,
6534 WINED3DRS_STENCILPASS ,
6535 WINED3DRS_STENCILREF ,
6536 WINED3DRS_STENCILWRITEMASK ,
6537 WINED3DRS_STENCILZFAIL ,
6538 WINED3DRS_TEXTUREFACTOR ,
6549 WINED3DRS_ZWRITEENABLE
6552 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
6553 WINED3DTSS_ADDRESSW ,
6554 WINED3DTSS_ALPHAARG0 ,
6555 WINED3DTSS_ALPHAARG1 ,
6556 WINED3DTSS_ALPHAARG2 ,
6557 WINED3DTSS_ALPHAOP ,
6558 WINED3DTSS_BUMPENVLOFFSET ,
6559 WINED3DTSS_BUMPENVLSCALE ,
6560 WINED3DTSS_BUMPENVMAT00 ,
6561 WINED3DTSS_BUMPENVMAT01 ,
6562 WINED3DTSS_BUMPENVMAT10 ,
6563 WINED3DTSS_BUMPENVMAT11 ,
6564 WINED3DTSS_COLORARG0 ,
6565 WINED3DTSS_COLORARG1 ,
6566 WINED3DTSS_COLORARG2 ,
6567 WINED3DTSS_COLOROP ,
6568 WINED3DTSS_RESULTARG ,
6569 WINED3DTSS_TEXCOORDINDEX ,
6570 WINED3DTSS_TEXTURETRANSFORMFLAGS
6573 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
6574 WINED3DSAMP_ADDRESSU ,
6575 WINED3DSAMP_ADDRESSV ,
6576 WINED3DSAMP_ADDRESSW ,
6577 WINED3DSAMP_BORDERCOLOR ,
6578 WINED3DSAMP_MAGFILTER ,
6579 WINED3DSAMP_MINFILTER ,
6580 WINED3DSAMP_MIPFILTER ,
6581 WINED3DSAMP_MIPMAPLODBIAS ,
6582 WINED3DSAMP_MAXMIPLEVEL ,
6583 WINED3DSAMP_MAXANISOTROPY ,
6584 WINED3DSAMP_SRGBTEXTURE ,
6585 WINED3DSAMP_ELEMENTINDEX
6588 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
6590 WINED3DRS_AMBIENTMATERIALSOURCE ,
6591 WINED3DRS_CLIPPING ,
6592 WINED3DRS_CLIPPLANEENABLE ,
6593 WINED3DRS_COLORVERTEX ,
6594 WINED3DRS_DIFFUSEMATERIALSOURCE ,
6595 WINED3DRS_EMISSIVEMATERIALSOURCE ,
6596 WINED3DRS_FOGDENSITY ,
6598 WINED3DRS_FOGSTART ,
6599 WINED3DRS_FOGTABLEMODE ,
6600 WINED3DRS_FOGVERTEXMODE ,
6601 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
6602 WINED3DRS_LIGHTING ,
6603 WINED3DRS_LOCALVIEWER ,
6604 WINED3DRS_MULTISAMPLEANTIALIAS ,
6605 WINED3DRS_MULTISAMPLEMASK ,
6606 WINED3DRS_NORMALIZENORMALS ,
6607 WINED3DRS_PATCHEDGESTYLE ,
6608 WINED3DRS_POINTSCALE_A ,
6609 WINED3DRS_POINTSCALE_B ,
6610 WINED3DRS_POINTSCALE_C ,
6611 WINED3DRS_POINTSCALEENABLE ,
6612 WINED3DRS_POINTSIZE ,
6613 WINED3DRS_POINTSIZE_MAX ,
6614 WINED3DRS_POINTSIZE_MIN ,
6615 WINED3DRS_POINTSPRITEENABLE ,
6616 WINED3DRS_RANGEFOGENABLE ,
6617 WINED3DRS_SPECULARMATERIALSOURCE ,
6618 WINED3DRS_TWEENFACTOR ,
6619 WINED3DRS_VERTEXBLEND
6622 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
6623 WINED3DTSS_TEXCOORDINDEX ,
6624 WINED3DTSS_TEXTURETRANSFORMFLAGS
6627 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
6628 WINED3DSAMP_DMAPOFFSET