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
28 #include "wined3d_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
31 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
33 /* x11drv GDI escapes */
34 #define X11DRV_ESCAPE 6789
35 enum x11drv_escape_codes
37 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
38 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
39 X11DRV_GET_FONT, /* get current X font for a DC */
42 /* retrieve the X display to use on a given DC */
43 inline static Display *get_display( HDC hdc )
46 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
48 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
49 sizeof(display), (LPSTR)&display )) display = NULL;
53 /* Memory tracking and object counting */
54 static unsigned int emulated_textureram = 64*1024*1024;
56 /* TODO: setup some flags in the regestry to enable, disable pbuffer support */
57 /* enable pbuffer support for offscreen textures */
58 BOOL pbuffer_support = FALSE;
59 /* allocate one pbuffer per surface */
60 BOOL pbuffer_per_surface = FALSE;
62 /* static function declarations */
63 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
65 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type);
68 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return WINED3DERR_OUTOFVIDEOMEMORY;}
70 #define D3DCREATEOBJECTINSTANCE(object, type) { \
71 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
72 D3DMEMCHECK(object, pp##type); \
73 object->lpVtbl = &IWineD3D##type##_Vtbl; \
74 object->wineD3DDevice = This; \
75 object->parent = parent; \
77 *pp##type = (IWineD3D##type *) object; \
80 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
81 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
82 D3DMEMCHECK(object, pp##type); \
83 object->lpVtbl = &IWineD3D##type##_Vtbl; \
84 object->resource.wineD3DDevice = This; \
85 object->resource.parent = parent; \
86 object->resource.resourceType = d3dtype; \
87 object->resource.ref = 1; \
88 object->resource.pool = Pool; \
89 object->resource.format = Format; \
90 object->resource.usage = Usage; \
91 object->resource.size = _size; \
92 /* Check that we have enough video ram left */ \
93 if (Pool == WINED3DPOOL_DEFAULT) { \
94 if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
95 WARN("Out of 'bogus' video memory\n"); \
96 HeapFree(GetProcessHeap(), 0, object); \
98 return WINED3DERR_OUTOFVIDEOMEMORY; \
100 globalChangeGlRam(_size); \
102 object->resource.allocatedMemory = (0 == _size ? NULL : Pool == WINED3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
103 if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != WINED3DPOOL_DEFAULT) { \
104 FIXME("Out of memory!\n"); \
105 HeapFree(GetProcessHeap(), 0, object); \
107 return WINED3DERR_OUTOFVIDEOMEMORY; \
109 *pp##type = (IWineD3D##type *) object; \
110 IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
111 TRACE("(%p) : Created resource %p\n", This, object); \
114 #define D3DINITIALIZEBASETEXTURE(_basetexture) { \
115 _basetexture.levels = Levels; \
116 _basetexture.filterType = (Usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE; \
117 _basetexture.LOD = 0; \
118 _basetexture.dirty = TRUE; \
121 /**********************************************************
122 * Global variable / Constants follow
123 **********************************************************/
124 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
126 /**********************************************************
127 * Utility functions follow
128 **********************************************************/
129 /* Convert the D3DLIGHT properties into equivalent gl lights */
130 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
133 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
134 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
136 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
137 glMatrixMode(GL_MODELVIEW);
139 glLoadMatrixf((float *)&This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
142 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
143 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
144 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
145 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
146 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
147 checkGLcall("glLightfv");
150 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
151 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
152 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
153 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
154 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
155 checkGLcall("glLightfv");
158 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
159 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
160 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
161 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
162 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
163 checkGLcall("glLightfv");
165 /* Attenuation - Are these right? guessing... */
166 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
167 checkGLcall("glLightf");
168 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
169 checkGLcall("glLightf");
171 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
172 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
174 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
177 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
178 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
179 checkGLcall("glLightf");
181 switch (lightInfo->OriginalParms.Type) {
184 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
185 checkGLcall("glLightfv");
186 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
187 checkGLcall("glLightf");
193 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
194 checkGLcall("glLightfv");
196 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
197 checkGLcall("glLightfv");
198 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
199 checkGLcall("glLightf");
200 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
201 checkGLcall("glLightf");
205 case D3DLIGHT_DIRECTIONAL:
207 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
208 checkGLcall("glLightfv");
209 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
210 checkGLcall("glLightf");
211 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
212 checkGLcall("glLightf");
216 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
219 /* Restore the modelview matrix */
223 /* Apply the current values to the specified texture stage */
224 void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Sampler, DWORD Flags) {
225 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
233 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
234 clamping, MIPLOD, etc. This will work for up to 16 samplers.
237 if (Sampler >= GL_LIMITS(samplers)) {
238 FIXME("Trying to set the state of more samplers %ld than are supported %d by this openGL implementation\n", Sampler, GL_LIMITS(samplers));
241 VTRACE(("Activating appropriate texture state %ld\n", Sampler));
242 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
244 GLACTIVETEXTURE(Sampler);
246 /* Could we use bindTexture and then apply the states instead of GLACTIVETEXTURE */
247 } else if (Sampler > 0) {
248 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
252 /* TODO: change this to a lookup table
253 LOOKUP_TEXTURE_STATES lists all texture states that should be applied.
254 LOOKUP_CONTEXT_SATES list all context applicable states that can be applied
255 etc.... it's a lot cleaner, quicker and possibly easier to maintain than running a switch and setting a skip flag...
256 especially when there are a number of groups of states. */
258 TRACE("-----------------------> Updating the texture at Sampler %ld to have new texture state information\n", Sampler);
260 /* The list of states not to apply is a big as the list of states to apply, so it makes sense to produce an inclusive list */
261 #define APPLY_STATE(_state) IWineD3DDeviceImpl_ApplyTextureUnitState(iface, Sampler, _state)
262 /* these are the only two supported states that need to be applied */
263 APPLY_STATE(WINED3DTSS_TEXCOORDINDEX);
264 APPLY_STATE(WINED3DTSS_TEXTURETRANSFORMFLAGS);
265 #if 0 /* not supported at the moment */
266 APPLY_STATE(WINED3DTSS_BUMPENVMAT00);
267 APPLY_STATE(WINED3DTSS_BUMPENVMAT01);
268 APPLY_STATE(WINED3DTSS_BUMPENVMAT10);
269 APPLY_STATE(WINED3DTSS_BUMPENVMAT11);
270 APPLY_STATE(WINED3DTSS_BUMPENVLSCALE);
271 APPLY_STATE(WINED3DTSS_BUMPENVLOFFSET);
272 APPLY_STATE(WINED3DTSS_RESULTARG);
273 APPLY_STATE(WINED3DTSS_CONSTANT);
275 /* a quick sanity check in case someone forgot to update this function */
276 if (WINED3D_HIGHEST_TEXTURE_STATE > WINED3DTSS_CONSTANT) {
277 FIXME("(%p) : There are more texture states than expected, update device.c to match\n", This);
281 /* apply any sampler states that always need applying */
282 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
283 tmpvalue.d = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPMAPLODBIAS];
284 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
285 GL_TEXTURE_LOD_BIAS_EXT,
287 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
290 /* Note the D3DRS value applies to all textures, but GL has one
291 * per texture, so apply it now ready to be used!
293 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
294 /* Set the default alpha blend color */
295 glBlendColor(col[0], col[1], col[2], col[3]);
296 checkGLcall("glBlendColor");
298 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
299 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
300 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
302 /* TODO: NV_POINT_SPRITE */
303 if (GL_SUPPORT(ARB_POINT_SPRITE)) {
304 if (This->stateBlock->renderState[WINED3DRS_POINTSPRITEENABLE] != FALSE) {
305 /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
306 glDisable(GL_POINT_SMOOTH);
308 /* Centre the texture on the vertex */
309 VTRACE("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
310 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
312 VTRACE("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
313 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
314 checkGLcall("glTexEnvf(...)");
315 VTRACE("glEnable( GL_POINT_SPRITE_ARB )\n");
316 glEnable( GL_POINT_SPRITE_ARB );
317 checkGLcall("glEnable(...)");
319 VTRACE("glDisable( GL_POINT_SPRITE_ARB )\n");
320 glDisable( GL_POINT_SPRITE_ARB );
321 checkGLcall("glEnable(...)");
325 TRACE("-----------------------> Updated the texture at Sampler %ld to have new texture state information\n", Sampler);
328 /**********************************************************
329 * IUnknown parts follows
330 **********************************************************/
332 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
334 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
336 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
337 if (IsEqualGUID(riid, &IID_IUnknown)
338 || IsEqualGUID(riid, &IID_IWineD3DBase)
339 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
340 IUnknown_AddRef(iface);
345 return E_NOINTERFACE;
348 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
349 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
350 ULONG refCount = InterlockedIncrement(&This->ref);
352 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
356 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
357 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
358 ULONG refCount = InterlockedDecrement(&This->ref);
360 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
363 /* TODO: Clean up all the surfaces and textures! */
364 /* FIXME: Create targets and state blocks in d3d8 */
365 if (((IWineD3DImpl *)This->wineD3D)->dxVersion >= 8) { /*We don't create state blocks for d3d7 yet*/
366 /* NOTE: You must release the parent if the object was created via a callback
367 ** ***************************/
368 /* 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... */
369 /* Release all of the swapchains, except the implicit swapchain */
370 IUnknown* stencilBufferParent;
371 IUnknown* swapChainParent;
373 /* NOTE: Don't release swapchain 0 here, it's 'special' */
374 SwapChainList *nextSwapchain = This->swapchains;
375 if (nextSwapchain != NULL) {
376 nextSwapchain = nextSwapchain->next;
378 WARN("Expected to find the implicit swapchain\n");
381 /* release all the other swapchains */
382 while (nextSwapchain != NULL) {
383 SwapChainList *prevSwapchain = nextSwapchain;
384 nextSwapchain = nextSwapchain->next;
385 IWineD3DSwapChain_Release(prevSwapchain->swapchain);
386 /* NOTE: no need to free the list element, it will be done by the release callback
387 HeapFree(GetProcessHeap(), 0, prevSwapchain); */
389 /* Release the buffers (with sanity checks)*/
390 if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
391 if(This->depthStencilBuffer != This->stencilBufferTarget)
392 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
394 This->stencilBufferTarget = NULL;
396 if(IWineD3DSurface_Release(This->renderTarget) >0){
397 /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
399 This->renderTarget = NULL;
401 IWineD3DSurface_GetParent(This->depthStencilBuffer, &stencilBufferParent);
402 IUnknown_Release(stencilBufferParent); /* once for the get parent */
403 if(IUnknown_Release(stencilBufferParent) >0){ /* the second time for when it was created */
404 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
406 This->depthStencilBuffer = NULL;
408 /* Release the update stateblock */
409 if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){
410 if(This->updateStateBlock != This->stateBlock)
411 FIXME("(%p) Something's still holding the Update stateblock\n",This);
413 This->updateStateBlock = NULL;
414 { /* because were not doing proper internal refcounts releasing the primary state block
415 causes recursion with the extra checks in ResourceReleased, to avoid this we have
416 to set this->stateBlock = NULL; first */
417 IWineD3DStateBlock *stateBlock = (IWineD3DStateBlock *)This->stateBlock;
418 This->stateBlock = NULL;
420 /* Release the stateblock */
421 if(IWineD3DStateBlock_Release(stateBlock) > 0){
422 FIXME("(%p) Something's still holding the Update stateblock\n",This);
426 if (This->swapchains != NULL) {
427 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
428 IWineD3DSwapChain_GetParent(This->swapchains->swapchain, &swapChainParent);
429 IUnknown_Release(swapChainParent); /* once for the get parent */
430 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
431 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
435 if (This->resources != NULL ) {
436 FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This);
437 dumpResources(This->resources);
441 IWineD3D_Release(This->wineD3D);
442 This->wineD3D = NULL;
443 HeapFree(GetProcessHeap(), 0, This);
444 TRACE("Freed device %p\n", This);
450 /**********************************************************
451 * IWineD3DDevice implementation follows
452 **********************************************************/
453 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
454 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
455 *pParent = This->parent;
456 IUnknown_AddRef(This->parent);
460 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
461 DWORD FVF, WINED3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
463 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
464 IWineD3DVertexBufferImpl *object;
465 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
466 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, WINED3DRTYPE_VERTEXBUFFER, Size)
469 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
470 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
474 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
475 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
480 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
481 WINED3DFORMAT Format, WINED3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
482 HANDLE *sharedHandle, IUnknown *parent) {
483 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
484 IWineD3DIndexBufferImpl *object;
485 TRACE("(%p) Creating index buffer\n", This);
487 /* Allocate the storage for the device */
488 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,WINED3DRTYPE_INDEXBUFFER, Length)
491 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
492 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
495 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
496 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
497 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
502 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
504 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
505 IWineD3DStateBlockImpl *object;
508 D3DCREATEOBJECTINSTANCE(object, StateBlock)
509 object->blockType = Type;
511 /* Special case - Used during initialization to produce a placeholder stateblock
512 so other functions called can update a state block */
513 if (Type == WINED3DSBT_INIT) {
514 /* Don't bother increasing the reference count otherwise a device will never
515 be freed due to circular dependencies */
519 /* Otherwise, might as well set the whole state block to the appropriate values */
520 if ( This->stateBlock != NULL) {
521 memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
523 memset(object->streamFreq, 1, sizeof(object->streamFreq));
526 /* Reset the ref and type after kludging it */
527 object->wineD3DDevice = This;
529 object->blockType = Type;
531 TRACE("Updating changed flags appropriate for type %d\n", Type);
533 if (Type == WINED3DSBT_ALL) {
535 TRACE("ALL => Pretend everything has changed\n");
536 memset(&object->changed, TRUE, sizeof(This->stateBlock->changed));
537 } else if (Type == WINED3DSBT_PIXELSTATE) {
539 TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
540 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
542 object->changed.pixelShader = TRUE;
544 /* Pixel Shader Constants */
545 for (i = 0; i < MAX_PSHADER_CONSTANTS; ++i) {
546 object->changed.pixelShaderConstants[i] = TRUE;
548 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
549 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
551 for (j = 0; j < GL_LIMITS(textures); j++) {
552 for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
553 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
556 for (j = 0 ; j < 16; j++) {
557 for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
559 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
563 } else if (Type == WINED3DSBT_VERTEXSTATE) {
565 TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
566 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
568 object->changed.vertexShader = TRUE;
570 /* Vertex Shader Constants */
571 for (i = 0; i < MAX_VSHADER_CONSTANTS; ++i) {
572 object->changed.vertexShaderConstants[i] = TRUE;
574 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
575 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
577 for (j = 0; j < GL_LIMITS(textures); j++) {
578 for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
579 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
582 for (j = 0 ; j < 16; j++){
583 for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
584 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
588 /* Duplicate light chain */
590 PLIGHTINFOEL *src = NULL;
591 PLIGHTINFOEL *dst = NULL;
592 PLIGHTINFOEL *newEl = NULL;
593 src = This->stateBlock->lights;
594 object->lights = NULL;
598 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
599 if (newEl == NULL) return WINED3DERR_OUTOFVIDEOMEMORY;
600 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
602 newEl->changed = TRUE;
603 newEl->enabledChanged = TRUE;
605 object->lights = newEl;
616 FIXME("Unrecognized state block type %d\n", Type);
619 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
624 /* ************************************
626 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
629 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
631 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.
633 ******************************** */
635 HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height, WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **ppSurface,WINED3DRESOURCETYPE Type, DWORD Usage, WINED3DPOOL Pool, WINED3DMULTISAMPLE_TYPE MultiSample ,DWORD MultisampleQuality, HANDLE* pSharedHandle, IUnknown *parent) {
636 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
637 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
638 unsigned int pow2Width, pow2Height;
639 unsigned int Size = 1;
640 TRACE("(%p) Create surface\n",This);
642 /** FIXME: Check ranges on the inputs are valid
645 * [in] Quality level. The valid range is between zero and one less than the level
646 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
647 * Passing a larger value returns the error WINED3DERR_INVALIDCALL. The MultisampleQuality
648 * values of paired render targets, depth stencil surfaces, and the MultiSample type
650 *******************************/
655 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
657 * If this flag is set, the contents of the depth stencil buffer will be
658 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
659 * with a different depth surface.
661 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
662 ***************************/
664 if(MultisampleQuality < 0) {
665 FIXME("Invalid multisample level %ld\n", MultisampleQuality);
666 return WINED3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
669 if(MultisampleQuality > 0) {
670 FIXME("MultisampleQuality set to %ld, substituting 0\n", MultisampleQuality);
671 MultisampleQuality=0;
674 /** FIXME: Check that the format is supported
676 *******************************/
678 /* Non-power2 support */
680 /* Find the nearest pow2 match */
681 pow2Width = pow2Height = 1;
682 while (pow2Width < Width) pow2Width <<= 1;
683 while (pow2Height < Height) pow2Height <<= 1;
685 if (pow2Width > Width || pow2Height > Height) {
686 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
687 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
688 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
689 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
690 This, Width, Height);
691 return WINED3DERR_NOTAVAILABLE;
695 /** Check against the maximum texture sizes supported by the video card **/
696 if (pow2Width > GL_LIMITS(texture_size) || pow2Height > GL_LIMITS(texture_size)) {
697 /* one of three options
698 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)
699 2: Set the texture to the maxium size (bad idea)
700 3: WARN and return WINED3DERR_NOTAVAILABLE;
702 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));
703 return WINED3DERR_NOTAVAILABLE;
708 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
709 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
711 *********************************/
712 if (WINED3DFMT_UNKNOWN == Format) {
714 } else if (Format == WINED3DFMT_DXT1) {
715 /* DXT1 is half byte per pixel */
716 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4)) >> 1;
718 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
719 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
720 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4));
722 Size = (pow2Width * D3DFmtGetBpp(This, Format)) * pow2Height;
725 /** Create and initialise the surface resource **/
726 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,WINED3DRTYPE_SURFACE, Size)
727 /* "Standalone" surface */
728 IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL);
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, WINED3DPOOL_DEFAULT, WINED3DPOOL_MANAGED, WINED3DPOOL_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 WINED3DPOOL_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 WINED3DPOOL_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 WINED3DPOOL_MANAGED:
784 if(Usage == WINED3DUSAGE_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 WINED3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
789 if(!(Usage & WINED3DUSAGE_DYNAMIC) && !(Usage & WINED3DUSAGE_RENDERTARGET)
790 && !(Usage && WINED3DUSAGE_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 & WINED3DUSAGE_RENDERTARGET && Pool != WINED3DPOOL_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, WINED3DPOOL 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 WINED3DERR_INVALIDCALL;
839 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, WINED3DRTYPE_TEXTURE, 0);
840 D3DINITIALIZEBASETEXTURE(object->baseTexture);
841 object->width = Width;
842 object->height = Height;
844 /** Non-power2 support **/
845 /* Find the nearest pow2 match */
846 pow2Width = pow2Height = 1;
847 while (pow2Width < Width) pow2Width <<= 1;
848 while (pow2Height < Height) pow2Height <<= 1;
850 /** FIXME: add support for real non-power-two if it's provided by the video card **/
851 /* Precalculated scaling for 'faked' non power of two texture coords */
852 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
853 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
854 TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
856 /* Calculate levels for mip mapping */
858 TRACE("calculating levels %d\n", object->baseTexture.levels);
859 object->baseTexture.levels++;
862 while (tmpW > 1 && tmpH > 1) {
863 tmpW = max(1, tmpW >> 1);
864 tmpH = max(1, tmpH >> 1);
865 object->baseTexture.levels++;
867 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
870 /* Generate all the surfaces */
873 for (i = 0; i < object->baseTexture.levels; i++)
875 /* use the callback to create the texture surface */
876 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
877 if (hr!= WINED3D_OK) {
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], (IWineD3DBase *)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, WINED3DPOOL 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 WINED3DERR_INVALIDCALL;
924 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, WINED3DRTYPE_VOLUMETEXTURE, 0);
925 D3DINITIALIZEBASETEXTURE(object->baseTexture);
927 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
928 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
930 object->width = Width;
931 object->height = Height;
932 object->depth = Depth;
934 /* Calculate levels for mip mapping */
936 object->baseTexture.levels++;
940 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
941 tmpW = max(1, tmpW >> 1);
942 tmpH = max(1, tmpH >> 1);
943 tmpD = max(1, tmpD >> 1);
944 object->baseTexture.levels++;
946 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
949 /* Generate all the surfaces */
954 for (i = 0; i < object->baseTexture.levels; i++)
956 /* Create the volume */
957 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
958 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
960 /* Set it's container to this object */
961 IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)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, WINED3DPOOL 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, WINED3DRTYPE_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(WINED3DBOX));
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, WINED3DPOOL 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 WINED3DERR_INVALIDCALL;
1024 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, WINED3DRTYPE_CUBETEXTURE, 0);
1025 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1027 TRACE("(%p) Create Cube Texture\n", This);
1029 /** Non-power2 support **/
1031 /* Find the nearest pow2 match */
1033 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
1035 object->edgeLength = EdgeLength;
1036 /* TODO: support for native non-power 2 */
1037 /* Precalculated scaling for 'faked' non power of two texture coords */
1038 object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
1040 /* Calculate levels for mip mapping */
1042 object->baseTexture.levels++;
1045 tmpW = max(1, tmpW >> 1);
1046 object->baseTexture.levels++;
1048 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1051 /* Generate all the surfaces */
1053 for (i = 0; i < object->baseTexture.levels; i++) {
1055 /* Create the 6 faces */
1056 for (j = 0; j < 6; j++) {
1058 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
1059 i /* Level */, &object->surfaces[j][i],pSharedHandle);
1061 if(hr!= WINED3D_OK) {
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], (IWineD3DBase *)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 = WINED3DERR_NOTAVAILABLE;
1098 case WINED3DQUERYTYPE_OCCLUSION:
1099 TRACE("(%p) occlusion query\n", This);
1100 if (GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY))
1103 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1105 case WINED3DQUERYTYPE_VCACHE:
1106 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1107 case WINED3DQUERYTYPE_VERTEXSTATS:
1108 case WINED3DQUERYTYPE_EVENT:
1109 case WINED3DQUERYTYPE_TIMESTAMP:
1110 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1111 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1112 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1113 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1114 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1115 case WINED3DQUERYTYPE_PIXELTIMINGS:
1116 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1117 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1119 FIXME("(%p) Unhandled query type %d\n", This, Type);
1124 D3DCREATEOBJECTINSTANCE(object, Query)
1125 object->type = Type;
1126 /* allocated the 'extended' data based on the type of query requested */
1128 case D3DQUERYTYPE_OCCLUSION:
1129 if(GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY)) {
1130 TRACE("(%p) Allocating data for an occlusion query\n", This);
1131 object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1134 case D3DQUERYTYPE_VCACHE:
1135 case D3DQUERYTYPE_RESOURCEMANAGER:
1136 case D3DQUERYTYPE_VERTEXSTATS:
1137 case D3DQUERYTYPE_EVENT:
1138 case D3DQUERYTYPE_TIMESTAMP:
1139 case D3DQUERYTYPE_TIMESTAMPDISJOINT:
1140 case D3DQUERYTYPE_TIMESTAMPFREQ:
1141 case D3DQUERYTYPE_PIPELINETIMINGS:
1142 case D3DQUERYTYPE_INTERFACETIMINGS:
1143 case D3DQUERYTYPE_VERTEXTIMINGS:
1144 case D3DQUERYTYPE_PIXELTIMINGS:
1145 case D3DQUERYTYPE_BANDWIDTHTIMINGS:
1146 case D3DQUERYTYPE_CACHEUTILIZATION:
1148 object->extendedData = 0;
1149 FIXME("(%p) Unhandled query type %d\n",This , Type);
1151 TRACE("(%p) : Created Query %p\n", This, object);
1155 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1156 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1158 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1159 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1160 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1163 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1165 XVisualInfo template;
1166 GLXContext oldContext;
1167 Drawable oldDrawable;
1168 HRESULT hr = WINED3D_OK;
1170 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1172 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1173 * does a device hold a reference to a swap chain giving them a lifetime of the device
1174 * or does the swap chain notify the device of its destruction.
1175 *******************************/
1177 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1179 /* Initialize other useful values */
1180 object->presentParms.BackBufferCount = 1; /* TODO:? support for gl_aux buffers */
1182 /*********************
1183 * Lookup the window Handle and the relating X window handle
1184 ********************/
1186 /* Setup hwnd we are using, plus which display this equates to */
1187 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1188 if (!object->win_handle) {
1189 object->win_handle = This->createParms.hFocusWindow;
1192 object->win_handle = GetAncestor(object->win_handle, GA_ROOT);
1193 if ( !( object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window") ) ) {
1194 ERR("Can't get drawable (window), HWND:%p doesn't have the property __wine_x11_whole_window\n", object->win_handle);
1195 return WINED3DERR_NOTAVAILABLE;
1197 hDc = GetDC(object->win_handle);
1198 object->display = get_display(hDc);
1199 ReleaseDC(object->win_handle, hDc);
1200 TRACE("Using a display of %p %p\n", object->display, hDc);
1202 if (NULL == object->display || NULL == hDc) {
1203 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1204 return WINED3DERR_NOTAVAILABLE;
1207 if (object->win == 0) {
1208 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1209 return WINED3DERR_NOTAVAILABLE;
1212 * Create an opengl context for the display visual
1213 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1214 * use different properties after that point in time. FIXME: How to handle when requested format
1215 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1216 * it chooses is identical to the one already being used!
1217 **********************************/
1219 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1222 /* Create a new context for this swapchain */
1223 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1224 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1225 (or the best possible if none is requested) */
1226 TRACE("Found x visual ID : %ld\n", template.visualid);
1228 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1229 if (NULL == object->visInfo) {
1230 ERR("cannot really get XVisual\n");
1232 return WINED3DERR_NOTAVAILABLE;
1235 /* Write out some debug info about the visual/s */
1236 TRACE("Using x visual ID : %ld\n", template.visualid);
1237 TRACE(" visual info: %p\n", object->visInfo);
1238 TRACE(" num items : %d\n", num);
1239 for (n = 0;n < num; n++) {
1240 TRACE("=====item=====: %d\n", n + 1);
1241 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1242 TRACE(" screen : %d\n", object->visInfo[n].screen);
1243 TRACE(" depth : %u\n", object->visInfo[n].depth);
1244 TRACE(" class : %d\n", object->visInfo[n].class);
1245 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1246 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1247 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1248 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1249 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1250 /* log some extra glx info */
1251 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1252 TRACE(" gl_aux_buffers : %d\n", value);
1253 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1254 TRACE(" gl_buffer_size : %d\n", value);
1255 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1256 TRACE(" gl_red_size : %d\n", value);
1257 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1258 TRACE(" gl_green_size : %d\n", value);
1259 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1260 TRACE(" gl_blue_size : %d\n", value);
1261 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1262 TRACE(" gl_alpha_size : %d\n", value);
1263 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1264 TRACE(" gl_depth_size : %d\n", value);
1265 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1266 TRACE(" gl_stencil_size : %d\n", value);
1268 /* Now choose a simila visual ID*/
1270 #ifdef USE_CONTEXT_MANAGER
1272 /** TODO: use a context mamager **/
1276 IWineD3DSwapChain *implSwapChain;
1277 if (WINED3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1278 /* The first time around we create the context that is shared with all other swapchains and render targets */
1279 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1280 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1283 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1284 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1285 /* and create a new context with the implicit swapchains context as the shared context */
1286 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1287 IWineD3DSwapChain_Release(implSwapChain);
1292 XFree(object->visInfo);
1293 object->visInfo = NULL;
1295 if (NULL == object->glCtx) {
1296 ERR("cannot create glxContext\n");
1298 return WINED3DERR_NOTAVAILABLE;
1302 if (object->glCtx == NULL) {
1303 ERR("Error in context creation !\n");
1304 return WINED3DERR_INVALIDCALL;
1306 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1307 object->win_handle, object->glCtx, object->win, object->visInfo);
1310 /*********************
1311 * Windowed / Fullscreen
1312 *******************/
1315 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1316 * so we should really check to see if there is a fullscreen swapchain already
1317 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1318 **************************************/
1320 if (!*(pPresentationParameters->Windowed)) {
1326 /* Get info on the current display setup */
1327 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1328 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1331 /* Change the display settings */
1332 memset(&devmode, 0, sizeof(DEVMODEW));
1333 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1334 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1335 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1336 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1337 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1338 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1340 /* Make popup window */
1341 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1342 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1343 *(pPresentationParameters->BackBufferWidth),
1344 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1350 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1351 * then the corresponding dimension of the client area of the hDeviceWindow
1352 * (or the focus window, if hDeviceWindow is NULL) is taken.
1353 **********************/
1355 if (*(pPresentationParameters->Windowed) &&
1356 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1357 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1360 GetClientRect(object->win_handle, &Rect);
1362 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1363 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1364 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1366 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1367 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1368 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1372 /*********************
1373 * finish off parameter initialization
1374 *******************/
1376 /* Put the correct figures in the presentation parameters */
1377 TRACE("Coppying accross presentaion paraneters\n");
1378 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1379 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1380 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1381 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1382 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1383 object->presentParms.MultiSampleQuality = NULL == pPresentationParameters->MultiSampleQuality ? 0 : *(pPresentationParameters->MultiSampleQuality);
1384 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1385 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1386 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1387 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1388 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1389 object->presentParms.Flags = *(pPresentationParameters->Flags);
1390 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1391 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1394 /*********************
1395 * Create the back, front and stencil buffers
1396 *******************/
1397 TRACE("calling rendertarget CB\n");
1398 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1399 object->presentParms.BackBufferWidth,
1400 object->presentParms.BackBufferHeight,
1401 object->presentParms.BackBufferFormat,
1402 object->presentParms.MultiSampleType,
1403 object->presentParms.MultiSampleQuality,
1404 TRUE /* Lockable */,
1405 &object->frontBuffer,
1406 NULL /* pShared (always null)*/);
1407 if (object->frontBuffer != NULL)
1408 IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
1409 TRACE("calling rendertarget CB\n");
1410 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1411 object->presentParms.BackBufferWidth,
1412 object->presentParms.BackBufferHeight,
1413 object->presentParms.BackBufferFormat,
1414 object->presentParms.MultiSampleType,
1415 object->presentParms.MultiSampleQuality,
1416 TRUE /* Lockable */,
1417 &object->backBuffer,
1418 NULL /* pShared (always null)*/);
1419 if (object->backBuffer != NULL)
1420 IWineD3DSurface_SetContainer(object->backBuffer, (IWineD3DBase *)object);
1422 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1423 if (pPresentationParameters->EnableAutoDepthStencil) {
1424 TRACE("Creating depth stencil buffer\n");
1425 if (This->depthStencilBuffer == NULL ) {
1426 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1427 object->presentParms.BackBufferWidth,
1428 object->presentParms.BackBufferHeight,
1429 object->presentParms.AutoDepthStencilFormat,
1430 object->presentParms.MultiSampleType,
1431 object->presentParms.MultiSampleQuality,
1432 FALSE /* FIXME: Discard */,
1433 &This->depthStencilBuffer,
1434 NULL /* pShared (always null)*/ );
1435 if (This->depthStencilBuffer != NULL)
1436 IWineD3DSurface_SetContainer(This->depthStencilBuffer, 0);
1439 /** TODO: A check on width, height and multisample types
1440 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1441 ****************************/
1442 object->wantsDepthStencilBuffer = TRUE;
1444 object->wantsDepthStencilBuffer = FALSE;
1447 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1450 /*********************
1451 * init the default renderTarget management
1452 *******************/
1453 object->drawable = object->win;
1454 object->render_ctx = object->glCtx;
1456 if (hr == WINED3D_OK) {
1457 /*********************
1458 * Setup some defaults and clear down the buffers
1459 *******************/
1461 /** save current context and drawable **/
1462 oldContext = glXGetCurrentContext();
1463 oldDrawable = glXGetCurrentDrawable();
1465 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1466 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1467 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1469 checkGLcall("glXMakeCurrent");
1471 TRACE("Setting up the screen\n");
1472 /* Clear the screen */
1473 glClearColor(1.0, 0.0, 0.0, 0.0);
1474 checkGLcall("glClearColor");
1477 glClearStencil(0xffff);
1479 checkGLcall("glClear");
1481 glColor3f(1.0, 1.0, 1.0);
1482 checkGLcall("glColor3f");
1484 glEnable(GL_LIGHTING);
1485 checkGLcall("glEnable");
1487 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1488 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1490 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1491 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1493 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1494 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1496 /* switch back to the original context (if there was one)*/
1497 if (This->swapchains != NULL) {
1498 /** TODO: restore the context and drawable **/
1499 glXMakeCurrent(object->display, oldDrawable, oldContext);
1504 { /* Finally add the swapchain to the end of the devices' swapchain list */
1505 SwapChainList **nextSwapchain;
1506 nextSwapchain = &This->swapchains;
1507 while (*nextSwapchain != NULL) {
1508 nextSwapchain = &((*nextSwapchain)->next);
1510 (*nextSwapchain) = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->swapchains));
1511 (*nextSwapchain)->swapchain = (IWineD3DSwapChain *)object;
1513 TRACE("Set swapchain to %p\n", object);
1514 } else { /* something went wrong so clean up */
1515 IUnknown* bufferParent;
1516 if (object->frontBuffer) {
1518 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1519 IUnknown_Release(bufferParent); /* once for the get parent */
1520 if (IUnknown_Release(bufferParent) > 0) {
1521 FIXME("(%p) Something's still holding the front buffer\n",This);
1524 if (object->backBuffer) {
1525 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1526 IUnknown_Release(bufferParent); /* once for the get parent */
1527 if (IUnknown_Release(bufferParent) > 0) {
1528 FIXME("(%p) Something's still holding the back buffer\n",This);
1531 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1532 /* Clean up the context */
1533 /* check that we are the current context first (we shouldn't be though!) */
1534 if (object->glCtx != 0) {
1535 if(glXGetCurrentContext() == object->glCtx) {
1536 glXMakeCurrent(object->display, None, NULL);
1538 glXDestroyContext(object->display, object->glCtx);
1540 HeapFree(GetProcessHeap(), 0, object);
1547 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1548 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1549 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1550 unsigned int numberOfSwapChains = 0;
1551 SwapChainList *swapchain;
1553 swapchain = This->swapchains;
1554 /* itterate through the list to get a count */
1555 while (swapchain != NULL) {
1556 swapchain = swapchain->next;
1557 numberOfSwapChains++;
1560 TRACE("(%p) returning %d\n", This, numberOfSwapChains);
1561 return numberOfSwapChains;
1564 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1565 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1566 SwapChainList *swapchain;
1568 HRESULT hr = WINED3DERR_INVALIDCALL;
1569 swapchain = This->swapchains;
1570 TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1573 TRACE("(%p) Finding swapchain %d\n", This, iSwapChain);
1574 while (i > 0 && swapchain != NULL) {
1575 swapchain = swapchain->next;
1580 FIXME("(%p) Unable to find swapchain %d\n", This, iSwapChain);
1582 } else if (swapchain != NULL) {
1583 /** TODO: move off to a linkesList implementation **/
1584 *pSwapChain = swapchain->swapchain;
1585 IWineD3DSwapChain_AddRef(*pSwapChain);
1589 TRACE("(%p) returning %p\n", This, *pSwapChain);
1594 * Vertex Declaration
1596 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1597 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1598 IWineD3DVertexDeclarationImpl *object = NULL;
1599 HRESULT hr = WINED3D_OK;
1600 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1601 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1604 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1609 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1610 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pDeclaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1611 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1612 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1613 HRESULT hr = WINED3D_OK;
1614 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1615 object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins;
1617 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1619 /* If a vertex declaration has been passed, save it to the vertex shader, this affects d3d8 only. */
1620 /* Further it needs to be set before calling SetFunction as SetFunction needs the declaration. */
1621 if (pDeclaration != NULL) {
1622 IWineD3DVertexDeclaration *vertexDeclaration;
1623 hr = IWineD3DDevice_CreateVertexDeclaration(iface, pDeclaration, &vertexDeclaration ,NULL);
1624 if (WINED3D_OK == hr) {
1625 TRACE("(%p) : Setting vertex declaration to %p\n", This, vertexDeclaration);
1626 object->vertexDeclaration = vertexDeclaration;
1628 FIXME("(%p) : Failed to set the declaration, returning WINED3DERR_INVALIDCALL\n", iface);
1629 IWineD3DVertexShader_Release(*ppVertexShader);
1630 return WINED3DERR_INVALIDCALL;
1634 hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1636 if (WINED3D_OK != hr) {
1637 FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface);
1638 IWineD3DVertexShader_Release(*ppVertexShader);
1639 return WINED3DERR_INVALIDCALL;
1642 #if 0 /* TODO: In D3D* SVP is atatched to the shader, in D3D9 it's attached to the device and isn't stored in the stateblock. */
1643 if(Usage == WINED3DUSAGE_SOFTWAREVERTEXPROCESSING) {
1654 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
1655 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1656 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1657 HRESULT hr = WINED3D_OK;
1659 D3DCREATEOBJECTINSTANCE(object, PixelShader)
1660 object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins;
1661 hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
1662 if (WINED3D_OK == hr) {
1663 TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
1665 WARN("(%p) : Failed to create pixel shader\n", This);
1671 HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) {
1672 FIXME("This call is a d3d7 merge stub. It will be implemented later\n");
1673 return WINED3DERR_INVALIDCALL;
1676 HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface) {
1677 FIXME("This call is a d3d7 merge stub. It will be implemented later\n");
1678 return WINED3DERR_INVALIDCALL;
1681 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
1682 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1683 *ppD3D= This->wineD3D;
1684 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1685 IWineD3D_AddRef(*ppD3D);
1689 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1690 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1691 * Into the video ram as possible and seeing how many fit
1692 * you can also get the correct initial value from via X and ATI's driver
1693 *******************/
1694 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1695 static BOOL showfixmes = TRUE;
1697 FIXME("(%p) : stub, emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1698 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1701 TRACE("(%p) : emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1702 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1703 /* videomemory is simulated videomemory + AGP memory left */
1704 return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1712 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1713 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1714 HRESULT hr = WINED3D_OK;
1716 /* Update the current state block */
1717 This->updateStateBlock->fvf = fvf;
1718 This->updateStateBlock->changed.fvf = TRUE;
1719 This->updateStateBlock->set.fvf = TRUE;
1721 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1724 /* clear down the vertex declaration
1725 NOTE: Axis and Allies doesn't work properly otherwise
1726 (may be a stateblock problem though!)
1728 hr = IWineD3DDevice_SetVertexDeclaration(iface, NULL);
1735 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1736 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1737 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1738 *pfvf = This->stateBlock->fvf;
1743 * Get / Set Stream Source
1745 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1746 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1747 IWineD3DVertexBuffer *oldSrc;
1749 /**TODO: instance and index data, see
1750 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1752 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
1755 /* D3d9 only, but shouldn't hurt d3d8 */
1758 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1760 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1761 FIXME("stream index data not supported\n");
1763 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1764 FIXME("stream instance data not supported\n");
1768 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1770 if (StreamNumber >= MAX_STREAMS) {
1771 WARN("Stream out of range %d\n", StreamNumber);
1772 return WINED3DERR_INVALIDCALL;
1775 oldSrc = This->stateBlock->streamSource[StreamNumber];
1776 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1778 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
1779 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
1780 This->updateStateBlock->streamStride[StreamNumber] = Stride;
1781 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
1782 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
1783 This->updateStateBlock->streamFlags[StreamNumber] = streamFlags;
1785 /* Handle recording of state blocks */
1786 if (This->isRecordingState) {
1787 TRACE("Recording... not performing anything\n");
1791 /* Not recording... */
1792 /* Need to do a getParent and pass the reffs up */
1793 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
1794 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
1795 so for now, just count internally */
1796 if (pStreamData != NULL) {
1797 IWineD3DVertexBuffer_AddRef(pStreamData);
1799 if (oldSrc != NULL) {
1800 IWineD3DVertexBuffer_Release(oldSrc);
1806 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
1807 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1810 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
1811 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
1814 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1816 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1817 FIXME("stream index data not supported\n");
1819 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1820 FIXME("stream instance data not supported\n");
1824 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1826 if (StreamNumber >= MAX_STREAMS) {
1827 WARN("Stream out of range %d\n", StreamNumber);
1828 return WINED3DERR_INVALIDCALL;
1830 *pStream = This->stateBlock->streamSource[StreamNumber];
1831 *pStride = This->stateBlock->streamStride[StreamNumber];
1832 *pOffset = This->stateBlock->streamOffset[StreamNumber];
1834 if (*pStream == NULL) {
1835 FIXME("Attempting to get an empty stream %d, returning WINED3DERR_INVALIDCALL\n", StreamNumber);
1836 return WINED3DERR_INVALIDCALL;
1839 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
1843 /*Should be quite easy, just an extension of vertexdata
1845 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1847 The divider is a bit odd though
1849 VertexOffset = StartVertex / Divider * StreamStride +
1850 VertexIndex / Divider * StreamStride + StreamOffset
1853 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
1854 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1856 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
1857 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (D3DSTREAMSOURCE_INSTANCEDATA | D3DSTREAMSOURCE_INDEXEDDATA );
1859 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
1860 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
1861 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
1863 if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
1864 FIXME("Stream indexing not fully supported\n");
1870 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
1871 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1873 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
1874 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
1876 TRACE("(%p) : returning %d\n", This, *Divider);
1882 * Get / Set & Multiply Transform
1884 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1885 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1887 /* Most of this routine, comments included copied from ddraw tree initially: */
1888 TRACE("(%p) : Transform State=%d\n", This, d3dts);
1890 /* Handle recording of state blocks */
1891 if (This->isRecordingState) {
1892 TRACE("Recording... not performing anything\n");
1893 This->updateStateBlock->changed.transform[d3dts] = TRUE;
1894 This->updateStateBlock->set.transform[d3dts] = TRUE;
1895 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1900 * If the new matrix is the same as the current one,
1901 * we cut off any further processing. this seems to be a reasonable
1902 * optimization because as was noticed, some apps (warcraft3 for example)
1903 * tend towards setting the same matrix repeatedly for some reason.
1905 * From here on we assume that the new matrix is different, wherever it matters.
1907 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1908 TRACE("The app is setting the same matrix over again\n");
1911 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1915 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1916 where ViewMat = Camera space, WorldMat = world space.
1918 In OpenGL, camera and world space is combined into GL_MODELVIEW
1919 matrix. The Projection matrix stay projection matrix.
1922 /* Capture the times we can just ignore the change for now */
1923 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1924 This->modelview_valid = FALSE;
1927 } else if (d3dts == D3DTS_PROJECTION) {
1928 This->proj_valid = FALSE;
1931 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1932 /* Indexed Vertex Blending Matrices 256 -> 511 */
1933 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1934 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1938 /* Now we really are going to have to change a matrix */
1941 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1942 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
1943 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1946 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1947 * NOTE: We have to reset the positions even if the light/plane is not currently
1948 * enabled, since the call to enable it will not reset the position.
1949 * NOTE2: Apparently texture transforms do NOT need reapplying
1952 PLIGHTINFOEL *lightChain = NULL;
1953 This->modelview_valid = FALSE;
1954 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
1956 glMatrixMode(GL_MODELVIEW);
1957 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1959 glLoadMatrixf((float *)lpmatrix);
1960 checkGLcall("glLoadMatrixf(...)");
1963 lightChain = This->stateBlock->lights;
1964 while (lightChain && lightChain->glIndex != -1) {
1965 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1966 checkGLcall("glLightfv posn");
1967 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1968 checkGLcall("glLightfv dirn");
1969 lightChain = lightChain->next;
1972 /* Reset Clipping Planes if clipping is enabled */
1973 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1974 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1975 checkGLcall("glClipPlane");
1979 } else { /* What was requested!?? */
1980 WARN("invalid matrix specified: %i\n", d3dts);
1983 /* Release lock, all done */
1988 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1989 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1990 TRACE("(%p) : for Transform State %d\n", This, State);
1991 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1995 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1996 D3DMATRIX *mat = NULL;
1999 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2000 * below means it will be recorded in a state block change, but it
2001 * works regardless where it is recorded.
2002 * If this is found to be wrong, change to StateBlock.
2004 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2005 TRACE("(%p) : For state %u\n", This, State);
2007 if (State < HIGHEST_TRANSFORMSTATE)
2009 mat = &This->updateStateBlock->transforms[State];
2011 FIXME("Unhandled transform state!!\n");
2014 /* Copied from ddraw code: */
2015 temp.u.s._11 = (mat->u.s._11 * pMatrix->u.s._11) + (mat->u.s._21 * pMatrix->u.s._12) +
2016 (mat->u.s._31 * pMatrix->u.s._13) + (mat->u.s._41 * pMatrix->u.s._14);
2017 temp.u.s._21 = (mat->u.s._11 * pMatrix->u.s._21) + (mat->u.s._21 * pMatrix->u.s._22) +
2018 (mat->u.s._31 * pMatrix->u.s._23) + (mat->u.s._41 * pMatrix->u.s._24);
2019 temp.u.s._31 = (mat->u.s._11 * pMatrix->u.s._31) + (mat->u.s._21 * pMatrix->u.s._32) +
2020 (mat->u.s._31 * pMatrix->u.s._33) + (mat->u.s._41 * pMatrix->u.s._34);
2021 temp.u.s._41 = (mat->u.s._11 * pMatrix->u.s._41) + (mat->u.s._21 * pMatrix->u.s._42) +
2022 (mat->u.s._31 * pMatrix->u.s._43) + (mat->u.s._41 * pMatrix->u.s._44);
2024 temp.u.s._12 = (mat->u.s._12 * pMatrix->u.s._11) + (mat->u.s._22 * pMatrix->u.s._12) +
2025 (mat->u.s._32 * pMatrix->u.s._13) + (mat->u.s._42 * pMatrix->u.s._14);
2026 temp.u.s._22 = (mat->u.s._12 * pMatrix->u.s._21) + (mat->u.s._22 * pMatrix->u.s._22) +
2027 (mat->u.s._32 * pMatrix->u.s._23) + (mat->u.s._42 * pMatrix->u.s._24);
2028 temp.u.s._32 = (mat->u.s._12 * pMatrix->u.s._31) + (mat->u.s._22 * pMatrix->u.s._32) +
2029 (mat->u.s._32 * pMatrix->u.s._33) + (mat->u.s._42 * pMatrix->u.s._34);
2030 temp.u.s._42 = (mat->u.s._12 * pMatrix->u.s._41) + (mat->u.s._22 * pMatrix->u.s._42) +
2031 (mat->u.s._32 * pMatrix->u.s._43) + (mat->u.s._42 * pMatrix->u.s._44);
2033 temp.u.s._13 = (mat->u.s._13 * pMatrix->u.s._11) + (mat->u.s._23 * pMatrix->u.s._12) +
2034 (mat->u.s._33 * pMatrix->u.s._13) + (mat->u.s._43 * pMatrix->u.s._14);
2035 temp.u.s._23 = (mat->u.s._13 * pMatrix->u.s._21) + (mat->u.s._23 * pMatrix->u.s._22) +
2036 (mat->u.s._33 * pMatrix->u.s._23) + (mat->u.s._43 * pMatrix->u.s._24);
2037 temp.u.s._33 = (mat->u.s._13 * pMatrix->u.s._31) + (mat->u.s._23 * pMatrix->u.s._32) +
2038 (mat->u.s._33 * pMatrix->u.s._33) + (mat->u.s._43 * pMatrix->u.s._34);
2039 temp.u.s._43 = (mat->u.s._13 * pMatrix->u.s._41) + (mat->u.s._23 * pMatrix->u.s._42) +
2040 (mat->u.s._33 * pMatrix->u.s._43) + (mat->u.s._43 * pMatrix->u.s._44);
2042 temp.u.s._14 = (mat->u.s._14 * pMatrix->u.s._11) + (mat->u.s._24 * pMatrix->u.s._12) +
2043 (mat->u.s._34 * pMatrix->u.s._13) + (mat->u.s._44 * pMatrix->u.s._14);
2044 temp.u.s._24 = (mat->u.s._14 * pMatrix->u.s._21) + (mat->u.s._24 * pMatrix->u.s._22) +
2045 (mat->u.s._34 * pMatrix->u.s._23) + (mat->u.s._44 * pMatrix->u.s._24);
2046 temp.u.s._34 = (mat->u.s._14 * pMatrix->u.s._31) + (mat->u.s._24 * pMatrix->u.s._32) +
2047 (mat->u.s._34 * pMatrix->u.s._33) + (mat->u.s._44 * pMatrix->u.s._34);
2048 temp.u.s._44 = (mat->u.s._14 * pMatrix->u.s._41) + (mat->u.s._24 * pMatrix->u.s._42) +
2049 (mat->u.s._34 * pMatrix->u.s._43) + (mat->u.s._44 * pMatrix->u.s._44);
2051 /* Apply change via set transform - will reapply to eg. lights this way */
2052 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2057 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
2059 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2060 you can reference any indexes you want as long as that number max are enabled at any
2061 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2062 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2063 but when recording, just build a chain pretty much of commands to be replayed. */
2065 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2067 PLIGHTINFOEL *object, *temp;
2069 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2070 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2072 /* If recording state block, just add to end of lights chain */
2073 if (This->isRecordingState) {
2074 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2075 if (NULL == object) {
2076 return WINED3DERR_OUTOFVIDEOMEMORY;
2078 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2079 object->OriginalIndex = Index;
2080 object->glIndex = -1;
2081 object->changed = TRUE;
2083 /* Add to the END of the chain of lights changes to be replayed */
2084 if (This->updateStateBlock->lights == NULL) {
2085 This->updateStateBlock->lights = object;
2087 temp = This->updateStateBlock->lights;
2088 while (temp->next != NULL) temp=temp->next;
2089 temp->next = object;
2091 TRACE("Recording... not performing anything more\n");
2095 /* Ok, not recording any longer so do real work */
2096 object = This->stateBlock->lights;
2097 while (object != NULL && object->OriginalIndex != Index) object = object->next;
2099 /* If we didn't find it in the list of lights, time to add it */
2100 if (object == NULL) {
2101 PLIGHTINFOEL *insertAt,*prevPos;
2103 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2104 if (NULL == object) {
2105 return WINED3DERR_OUTOFVIDEOMEMORY;
2107 object->OriginalIndex = Index;
2108 object->glIndex = -1;
2110 /* Add it to the front of list with the idea that lights will be changed as needed
2111 BUT after any lights currently assigned GL indexes */
2112 insertAt = This->stateBlock->lights;
2114 while (insertAt != NULL && insertAt->glIndex != -1) {
2116 insertAt = insertAt->next;
2119 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2120 This->stateBlock->lights = object;
2121 } else if (insertAt == NULL) { /* End of list */
2122 prevPos->next = object;
2123 object->prev = prevPos;
2124 } else { /* Middle of chain */
2125 if (prevPos == NULL) {
2126 This->stateBlock->lights = object;
2128 prevPos->next = object;
2130 object->prev = prevPos;
2131 object->next = insertAt;
2132 insertAt->prev = object;
2136 /* Initialize the object */
2137 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,
2138 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2139 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2140 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2141 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2142 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2143 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2145 /* Save away the information */
2146 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2148 switch (pLight->Type) {
2149 case D3DLIGHT_POINT:
2151 object->lightPosn[0] = pLight->Position.x;
2152 object->lightPosn[1] = pLight->Position.y;
2153 object->lightPosn[2] = pLight->Position.z;
2154 object->lightPosn[3] = 1.0f;
2155 object->cutoff = 180.0f;
2159 case D3DLIGHT_DIRECTIONAL:
2161 object->lightPosn[0] = -pLight->Direction.x;
2162 object->lightPosn[1] = -pLight->Direction.y;
2163 object->lightPosn[2] = -pLight->Direction.z;
2164 object->lightPosn[3] = 0.0;
2165 object->exponent = 0.0f;
2166 object->cutoff = 180.0f;
2171 object->lightPosn[0] = pLight->Position.x;
2172 object->lightPosn[1] = pLight->Position.y;
2173 object->lightPosn[2] = pLight->Position.z;
2174 object->lightPosn[3] = 1.0;
2177 object->lightDirn[0] = pLight->Direction.x;
2178 object->lightDirn[1] = pLight->Direction.y;
2179 object->lightDirn[2] = pLight->Direction.z;
2180 object->lightDirn[3] = 1.0;
2183 * opengl-ish and d3d-ish spot lights use too different models for the
2184 * light "intensity" as a function of the angle towards the main light direction,
2185 * so we only can approximate very roughly.
2186 * however spot lights are rather rarely used in games (if ever used at all).
2187 * furthermore if still used, probably nobody pays attention to such details.
2189 if (pLight->Falloff == 0) {
2192 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2194 if (rho < 0.0001) rho = 0.0001f;
2195 object->exponent = -0.3/log(cos(rho/2));
2196 object->cutoff = pLight->Phi*90/M_PI;
2202 FIXME("Unrecognized light type %d\n", pLight->Type);
2205 /* Update the live definitions if the light is currently assigned a glIndex */
2206 if (object->glIndex != -1) {
2207 setup_light(iface, object->glIndex, object);
2212 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2213 PLIGHTINFOEL *lightInfo = NULL;
2214 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2215 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2217 /* Locate the light in the live lights */
2218 lightInfo = This->stateBlock->lights;
2219 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2221 if (lightInfo == NULL) {
2222 TRACE("Light information requested but light not defined\n");
2223 return WINED3DERR_INVALIDCALL;
2226 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
2231 * Get / Set Light Enable
2232 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2234 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2235 PLIGHTINFOEL *lightInfo = NULL;
2236 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2237 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2239 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2240 if (This->isRecordingState) {
2241 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2242 if (NULL == lightInfo) {
2243 return WINED3DERR_OUTOFVIDEOMEMORY;
2245 lightInfo->OriginalIndex = Index;
2246 lightInfo->glIndex = -1;
2247 lightInfo->enabledChanged = TRUE;
2249 /* Add to the END of the chain of lights changes to be replayed */
2250 if (This->updateStateBlock->lights == NULL) {
2251 This->updateStateBlock->lights = lightInfo;
2253 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2254 while (temp->next != NULL) temp=temp->next;
2255 temp->next = lightInfo;
2257 TRACE("Recording... not performing anything more\n");
2261 /* Not recording... So, locate the light in the live lights */
2262 lightInfo = This->stateBlock->lights;
2263 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2265 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2266 if (lightInfo == NULL) {
2267 D3DLIGHT9 lightParms;
2268 /* Warning - untested code :-) Prob safe to change fixme to a trace but
2269 wait until someone confirms it seems to work! */
2270 TRACE("Light enabled requested but light not defined, so defining one!\n");
2271 lightParms.Type = D3DLIGHT_DIRECTIONAL;
2272 lightParms.Diffuse.r = 1.0;
2273 lightParms.Diffuse.g = 1.0;
2274 lightParms.Diffuse.b = 1.0;
2275 lightParms.Diffuse.a = 0.0;
2276 lightParms.Specular.r = 0.0;
2277 lightParms.Specular.g = 0.0;
2278 lightParms.Specular.b = 0.0;
2279 lightParms.Specular.a = 0.0;
2280 lightParms.Ambient.r = 0.0;
2281 lightParms.Ambient.g = 0.0;
2282 lightParms.Ambient.b = 0.0;
2283 lightParms.Ambient.a = 0.0;
2284 lightParms.Position.x = 0.0;
2285 lightParms.Position.y = 0.0;
2286 lightParms.Position.z = 0.0;
2287 lightParms.Direction.x = 0.0;
2288 lightParms.Direction.y = 0.0;
2289 lightParms.Direction.z = 1.0;
2290 lightParms.Range = 0.0;
2291 lightParms.Falloff = 0.0;
2292 lightParms.Attenuation0 = 0.0;
2293 lightParms.Attenuation1 = 0.0;
2294 lightParms.Attenuation2 = 0.0;
2295 lightParms.Theta = 0.0;
2296 lightParms.Phi = 0.0;
2297 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
2299 /* Search for it again! Should be fairly quick as near head of list */
2300 lightInfo = This->stateBlock->lights;
2301 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2302 if (lightInfo == NULL) {
2303 FIXME("Adding default lights has failed dismally\n");
2304 return WINED3DERR_INVALIDCALL;
2308 /* OK, we now have a light... */
2309 if (Enable == FALSE) {
2311 /* If we are disabling it, check it was enabled, and
2312 still only do something if it has assigned a glIndex (which it should have!) */
2313 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2314 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2316 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2317 checkGLcall("glDisable GL_LIGHT0+Index");
2320 TRACE("Nothing to do as light was not enabled\n");
2322 lightInfo->lightEnabled = FALSE;
2325 /* We are enabling it. If it is enabled, it's really simple */
2326 if (lightInfo->lightEnabled) {
2328 TRACE("Nothing to do as light was enabled\n");
2330 /* If it already has a glIndex, it's still simple */
2331 } else if (lightInfo->glIndex != -1) {
2332 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2333 lightInfo->lightEnabled = TRUE;
2335 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2336 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2339 /* Otherwise got to find space - lights are ordered gl indexes first */
2341 PLIGHTINFOEL *bsf = NULL;
2342 PLIGHTINFOEL *pos = This->stateBlock->lights;
2343 PLIGHTINFOEL *prev = NULL;
2347 /* Try to minimize changes as much as possible */
2348 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2350 /* Try to remember which index can be replaced if necessary */
2351 if (bsf==NULL && pos->lightEnabled == FALSE) {
2352 /* Found a light we can replace, save as best replacement */
2356 /* Step to next space */
2362 /* If we have too many active lights, fail the call */
2363 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2364 FIXME("Program requests too many concurrent lights\n");
2365 return WINED3DERR_INVALIDCALL;
2367 /* If we have allocated all lights, but not all are enabled,
2368 reuse one which is not enabled */
2369 } else if (Index == This->maxConcurrentLights) {
2370 /* use bsf - Simply swap the new light and the BSF one */
2371 PLIGHTINFOEL *bsfNext = bsf->next;
2372 PLIGHTINFOEL *bsfPrev = bsf->prev;
2375 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2376 if (bsf->prev != NULL) {
2377 bsf->prev->next = lightInfo;
2379 This->stateBlock->lights = lightInfo;
2382 /* If not side by side, lots of chains to update */
2383 if (bsf->next != lightInfo) {
2384 lightInfo->prev->next = bsf;
2385 bsf->next->prev = lightInfo;
2386 bsf->next = lightInfo->next;
2387 bsf->prev = lightInfo->prev;
2388 lightInfo->next = bsfNext;
2389 lightInfo->prev = bsfPrev;
2393 bsf->prev = lightInfo;
2394 bsf->next = lightInfo->next;
2395 lightInfo->next = bsf;
2396 lightInfo->prev = bsfPrev;
2401 glIndex = bsf->glIndex;
2403 lightInfo->glIndex = glIndex;
2404 lightInfo->lightEnabled = TRUE;
2406 /* Finally set up the light in gl itself */
2407 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2409 setup_light(iface, glIndex, lightInfo);
2410 glEnable(GL_LIGHT0 + glIndex);
2411 checkGLcall("glEnable GL_LIGHT0 new setup");
2414 /* If we reached the end of the allocated lights, with space in the
2415 gl lights, setup a new light */
2416 } else if (pos->glIndex == -1) {
2418 /* We reached the end of the allocated gl lights, so already
2419 know the index of the next one! */
2421 lightInfo->glIndex = glIndex;
2422 lightInfo->lightEnabled = TRUE;
2424 /* In an ideal world, it's already in the right place */
2425 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2426 /* No need to move it */
2428 /* Remove this light from the list */
2429 lightInfo->prev->next = lightInfo->next;
2430 if (lightInfo->next != NULL) {
2431 lightInfo->next->prev = lightInfo->prev;
2434 /* Add in at appropriate place (inbetween prev and pos) */
2435 lightInfo->prev = prev;
2436 lightInfo->next = pos;
2438 This->stateBlock->lights = lightInfo;
2440 prev->next = lightInfo;
2443 pos->prev = lightInfo;
2447 /* Finally set up the light in gl itself */
2448 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2450 setup_light(iface, glIndex, lightInfo);
2451 glEnable(GL_LIGHT0 + glIndex);
2452 checkGLcall("glEnable GL_LIGHT0 new setup");
2461 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2463 PLIGHTINFOEL *lightInfo = NULL;
2464 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2465 TRACE("(%p) : for idx(%ld)\n", This, Index);
2467 /* Locate the light in the live lights */
2468 lightInfo = This->stateBlock->lights;
2469 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2471 if (lightInfo == NULL) {
2472 TRACE("Light enabled state requested but light not defined\n");
2473 return WINED3DERR_INVALIDCALL;
2475 *pEnable = lightInfo->lightEnabled;
2480 * Get / Set Clip Planes
2482 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2483 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2484 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2486 /* Validate Index */
2487 if (Index >= GL_LIMITS(clipplanes)) {
2488 TRACE("Application has requested clipplane this device doesn't support\n");
2489 return WINED3DERR_INVALIDCALL;
2492 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2493 This->updateStateBlock->set.clipplane[Index] = TRUE;
2494 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2495 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2496 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2497 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2499 /* Handle recording of state blocks */
2500 if (This->isRecordingState) {
2501 TRACE("Recording... not performing anything\n");
2509 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2510 glMatrixMode(GL_MODELVIEW);
2512 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2514 TRACE("Clipplane [%f,%f,%f,%f]\n",
2515 This->updateStateBlock->clipplane[Index][0],
2516 This->updateStateBlock->clipplane[Index][1],
2517 This->updateStateBlock->clipplane[Index][2],
2518 This->updateStateBlock->clipplane[Index][3]);
2519 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2520 checkGLcall("glClipPlane");
2528 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2529 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2530 TRACE("(%p) : for idx %ld\n", This, Index);
2532 /* Validate Index */
2533 if (Index >= GL_LIMITS(clipplanes)) {
2534 TRACE("Application has requested clipplane this device doesn't support\n");
2535 return WINED3DERR_INVALIDCALL;
2538 pPlane[0] = This->stateBlock->clipplane[Index][0];
2539 pPlane[1] = This->stateBlock->clipplane[Index][1];
2540 pPlane[2] = This->stateBlock->clipplane[Index][2];
2541 pPlane[3] = This->stateBlock->clipplane[Index][3];
2546 * Get / Set Clip Plane Status
2547 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2549 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2550 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2551 FIXME("(%p) : stub\n", This);
2552 if (NULL == pClipStatus) {
2553 return WINED3DERR_INVALIDCALL;
2555 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2556 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2560 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2561 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2562 FIXME("(%p) : stub\n", This);
2563 if (NULL == pClipStatus) {
2564 return WINED3DERR_INVALIDCALL;
2566 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2567 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2572 * Get / Set Material
2573 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2575 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2576 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2578 This->updateStateBlock->changed.material = TRUE;
2579 This->updateStateBlock->set.material = TRUE;
2580 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2582 /* Handle recording of state blocks */
2583 if (This->isRecordingState) {
2584 TRACE("Recording... not performing anything\n");
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);
2599 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2600 checkGLcall("glMaterialfv(GL_AMBIENT)");
2601 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2602 checkGLcall("glMaterialfv(GL_DIFFUSE)");
2604 /* Only change material color if specular is enabled, otherwise it is set to black */
2605 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2606 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2607 checkGLcall("glMaterialfv(GL_SPECULAR");
2609 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2610 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2611 checkGLcall("glMaterialfv(GL_SPECULAR");
2613 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2614 checkGLcall("glMaterialfv(GL_EMISSION)");
2615 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2616 checkGLcall("glMaterialf(GL_SHININESS");
2622 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2623 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2624 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2625 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2626 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2627 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2628 pMaterial->Ambient.b, pMaterial->Ambient.a);
2629 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2630 pMaterial->Specular.b, pMaterial->Specular.a);
2631 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2632 pMaterial->Emissive.b, pMaterial->Emissive.a);
2633 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2641 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2642 UINT BaseVertexIndex) {
2643 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2644 IWineD3DIndexBuffer *oldIdxs;
2646 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2647 oldIdxs = This->updateStateBlock->pIndexData;
2649 This->updateStateBlock->changed.indices = TRUE;
2650 This->updateStateBlock->set.indices = TRUE;
2651 This->updateStateBlock->pIndexData = pIndexData;
2652 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2654 /* Handle recording of state blocks */
2655 if (This->isRecordingState) {
2656 TRACE("Recording... not performing anything\n");
2660 if (NULL != pIndexData) {
2661 IWineD3DIndexBuffer_AddRef(pIndexData);
2663 if (NULL != oldIdxs) {
2664 IWineD3DIndexBuffer_Release(oldIdxs);
2669 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2670 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2672 *ppIndexData = This->stateBlock->pIndexData;
2674 /* up ref count on ppindexdata */
2676 IWineD3DIndexBuffer_AddRef(*ppIndexData);
2677 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2678 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
2680 TRACE("(%p) No index data set\n", This);
2682 TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
2688 * Get / Set Viewports
2690 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2691 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2693 TRACE("(%p)\n", This);
2694 This->updateStateBlock->changed.viewport = TRUE;
2695 This->updateStateBlock->set.viewport = TRUE;
2696 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2698 /* Handle recording of state blocks */
2699 if (This->isRecordingState) {
2700 TRACE("Recording... not performing anything\n");
2703 This->viewport_changed = TRUE;
2707 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2708 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2710 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2711 checkGLcall("glDepthRange");
2712 /* Note: GL requires lower left, DirectX supplies upper left */
2713 /* TODO: replace usage of renderTarget with context management */
2714 glViewport(pViewport->X,
2715 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2716 pViewport->Width, pViewport->Height);
2718 checkGLcall("glViewport");
2726 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2727 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2728 TRACE("(%p)\n", This);
2729 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2734 * Get / Set Render States
2735 * TODO: Verify against dx9 definitions
2737 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2739 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2740 DWORD OldValue = This->stateBlock->renderState[State];
2742 /* Simple way of referring to either a DWORD or a 4 byte float */
2748 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2749 This->updateStateBlock->changed.renderState[State] = TRUE;
2750 This->updateStateBlock->set.renderState[State] = TRUE;
2751 This->updateStateBlock->renderState[State] = Value;
2753 /* Handle recording of state blocks */
2754 if (This->isRecordingState) {
2755 TRACE("Recording... not performing anything\n");
2762 case WINED3DRS_FILLMODE :
2763 switch ((D3DFILLMODE) Value) {
2764 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2765 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2766 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2768 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
2770 checkGLcall("glPolygonMode (fillmode)");
2773 case WINED3DRS_LIGHTING :
2775 glEnable(GL_LIGHTING);
2776 checkGLcall("glEnable GL_LIGHTING");
2778 glDisable(GL_LIGHTING);
2779 checkGLcall("glDisable GL_LIGHTING");
2783 case WINED3DRS_ZENABLE :
2784 switch ((D3DZBUFFERTYPE) Value) {
2786 glDisable(GL_DEPTH_TEST);
2787 checkGLcall("glDisable GL_DEPTH_TEST");
2790 glEnable(GL_DEPTH_TEST);
2791 checkGLcall("glEnable GL_DEPTH_TEST");
2794 glEnable(GL_DEPTH_TEST);
2795 checkGLcall("glEnable GL_DEPTH_TEST");
2796 FIXME("W buffer is not well handled\n");
2799 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2803 case WINED3DRS_CULLMODE :
2805 /* If we are culling "back faces with clockwise vertices" then
2806 set front faces to be counter clockwise and enable culling
2808 switch ((D3DCULL) Value) {
2810 glDisable(GL_CULL_FACE);
2811 checkGLcall("glDisable GL_CULL_FACE");
2814 glEnable(GL_CULL_FACE);
2815 checkGLcall("glEnable GL_CULL_FACE");
2816 if (This->renderUpsideDown) {
2818 checkGLcall("glFrontFace GL_CW");
2820 glFrontFace(GL_CCW);
2821 checkGLcall("glFrontFace GL_CCW");
2823 glCullFace(GL_BACK);
2826 glEnable(GL_CULL_FACE);
2827 checkGLcall("glEnable GL_CULL_FACE");
2828 if (This->renderUpsideDown) {
2829 glFrontFace(GL_CCW);
2830 checkGLcall("glFrontFace GL_CCW");
2833 checkGLcall("glFrontFace GL_CW");
2835 glCullFace(GL_BACK);
2838 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2842 case WINED3DRS_SHADEMODE :
2843 switch ((D3DSHADEMODE) Value) {
2845 glShadeModel(GL_FLAT);
2846 checkGLcall("glShadeModel");
2848 case D3DSHADE_GOURAUD:
2849 glShadeModel(GL_SMOOTH);
2850 checkGLcall("glShadeModel");
2852 case D3DSHADE_PHONG:
2853 FIXME("D3DSHADE_PHONG isn't supported?\n");
2856 return WINED3DERR_INVALIDCALL;
2858 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2862 case WINED3DRS_DITHERENABLE :
2864 glEnable(GL_DITHER);
2865 checkGLcall("glEnable GL_DITHER");
2867 glDisable(GL_DITHER);
2868 checkGLcall("glDisable GL_DITHER");
2872 case WINED3DRS_ZWRITEENABLE :
2875 checkGLcall("glDepthMask");
2878 checkGLcall("glDepthMask");
2882 case WINED3DRS_ZFUNC :
2884 int glParm = GL_LESS;
2886 switch ((D3DCMPFUNC) Value) {
2887 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2888 case D3DCMP_LESS: glParm=GL_LESS; break;
2889 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2890 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2891 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2892 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2893 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2894 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2896 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2898 glDepthFunc(glParm);
2899 checkGLcall("glDepthFunc");
2903 case WINED3DRS_AMBIENT :
2906 D3DCOLORTOGLFLOAT4(Value, col);
2907 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2908 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2909 checkGLcall("glLightModel for MODEL_AMBIENT");
2914 case WINED3DRS_ALPHABLENDENABLE :
2917 checkGLcall("glEnable GL_BLEND");
2919 glDisable(GL_BLEND);
2920 checkGLcall("glDisable GL_BLEND");
2924 case WINED3DRS_SRCBLEND :
2925 case WINED3DRS_DESTBLEND :
2927 int newVal = GL_ZERO;
2929 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2930 case D3DBLEND_ONE : newVal = GL_ONE; break;
2931 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2932 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2933 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2934 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2935 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2936 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2937 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2938 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2939 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2941 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2942 This->srcBlend = newVal;
2943 This->dstBlend = newVal;
2946 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2947 This->srcBlend = newVal;
2948 This->dstBlend = newVal;
2951 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2954 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2955 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2956 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2957 glBlendFunc(This->srcBlend, This->dstBlend);
2959 checkGLcall("glBlendFunc");
2963 case WINED3DRS_ALPHATESTENABLE :
2965 glEnable(GL_ALPHA_TEST);
2966 checkGLcall("glEnable GL_ALPHA_TEST");
2968 glDisable(GL_ALPHA_TEST);
2969 checkGLcall("glDisable GL_ALPHA_TEST");
2973 case WINED3DRS_ALPHAFUNC :
2975 int glParm = GL_LESS;
2976 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2978 switch ((D3DCMPFUNC) Value) {
2979 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2980 case D3DCMP_LESS: glParm = GL_LESS; break;
2981 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2982 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2983 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2984 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2985 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2986 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2988 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2990 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2991 glAlphaFunc(glParm, ref);
2992 This->alphafunc = glParm;
2993 checkGLcall("glAlphaFunc");
2997 case WINED3DRS_ALPHAREF :
2999 int glParm = This->alphafunc;
3002 ref = ((float) Value) / 255.0f;
3003 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
3004 glAlphaFunc(glParm, ref);
3005 checkGLcall("glAlphaFunc");
3009 case WINED3DRS_CLIPPLANEENABLE :
3010 case WINED3DRS_CLIPPING :
3012 /* Ensure we only do the changed clip planes */
3013 DWORD enable = 0xFFFFFFFF;
3014 DWORD disable = 0x00000000;
3016 /* If enabling / disabling all */
3017 if (State == WINED3DRS_CLIPPING) {
3019 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3022 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3026 enable = Value & ~OldValue;
3027 disable = ~Value & OldValue;
3030 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
3031 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
3032 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
3033 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
3034 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
3035 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
3037 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
3038 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
3039 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
3040 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
3041 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
3042 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
3044 /** update clipping status */
3046 This->stateBlock->clip_status.ClipUnion = 0;
3047 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
3049 This->stateBlock->clip_status.ClipUnion = 0;
3050 This->stateBlock->clip_status.ClipIntersection = 0;
3055 case WINED3DRS_BLENDOP :
3057 int glParm = GL_FUNC_ADD;
3059 switch ((D3DBLENDOP) Value) {
3060 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
3061 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
3062 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3063 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
3064 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
3066 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
3068 TRACE("glBlendEquation(%x)\n", glParm);
3069 glBlendEquation(glParm);
3070 checkGLcall("glBlendEquation");
3074 case WINED3DRS_TEXTUREFACTOR :
3078 /* Note the texture color applies to all textures whereas
3079 GL_TEXTURE_ENV_COLOR applies to active only */
3081 D3DCOLORTOGLFLOAT4(Value, col);
3082 /* Set the default alpha blend color */
3083 glBlendColor(col[0], col[1], col[2], col[3]);
3084 checkGLcall("glBlendColor");
3086 /* And now the default texture color as well */
3087 for (i = 0; i < GL_LIMITS(textures); i++) {
3089 /* Note the D3DRS value applies to all textures, but GL has one
3090 per texture, so apply it now ready to be used! */
3091 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3094 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3097 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3098 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3103 case WINED3DRS_SPECULARENABLE :
3105 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3106 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3107 specular color. This is wrong:
3108 Separate specular color means the specular colour is maintained separately, whereas
3109 single color means it is merged in. However in both cases they are being used to
3111 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3112 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3116 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3117 checkGLcall("glMaterialfv");
3118 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3119 glEnable(GL_COLOR_SUM_EXT);
3121 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3123 checkGLcall("glEnable(GL_COLOR_SUM)");
3125 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3127 /* for the case of enabled lighting: */
3128 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3129 checkGLcall("glMaterialfv");
3131 /* for the case of disabled lighting: */
3132 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3133 glDisable(GL_COLOR_SUM_EXT);
3135 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3137 checkGLcall("glDisable(GL_COLOR_SUM)");
3142 case WINED3DRS_STENCILENABLE :
3144 glEnable(GL_STENCIL_TEST);
3145 checkGLcall("glEnable GL_STENCIL_TEST");
3147 glDisable(GL_STENCIL_TEST);
3148 checkGLcall("glDisable GL_STENCIL_TEST");
3152 case WINED3DRS_STENCILFUNC :
3155 GLint ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3156 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3159 switch ((D3DCMPFUNC)Value) {
3160 case D3DCMP_NEVER: func = GL_NEVER; break;
3161 case D3DCMP_LESS: func = GL_LESS; break;
3162 case D3DCMP_EQUAL: func = GL_EQUAL; break;
3163 case D3DCMP_LESSEQUAL: func = GL_LEQUAL; break;
3164 case D3DCMP_GREATER: func = GL_GREATER; break;
3165 case D3DCMP_NOTEQUAL: func = GL_NOTEQUAL; break;
3166 case D3DCMP_GREATEREQUAL: func = GL_GEQUAL; break;
3167 case D3DCMP_ALWAYS: func = GL_ALWAYS; break;
3169 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3171 This->stencilfunc = func;
3172 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3173 #if 0 /* Don't use OpenGL 2.0 calls for now */
3174 if(GL_EXTCALL(glStencilFuncSeparate)) {
3175 GL_EXTCALL(glStencilFuncSeparate(GL_FRONT, func, ref, mask));
3176 checkGLcall("glStencilFuncSeparate(GL_FRONT,...)");
3180 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3181 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3182 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3183 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
3184 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
3185 glStencilFunc(func, ref, mask);
3186 checkGLcall("glStencilFunc(...)");
3188 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3189 GL_EXTCALL(glStencilFuncSeparateATI(GL_FRONT, func, ref, mask));
3190 checkGLcall("glStencilFuncSeparateATI(GL_FRONT,...)");
3192 TRACE("Separate stencil function not supported on this version of opengl");
3193 glStencilFunc(func, ref, mask);
3194 checkGLcall("glStencilFunc(...)");
3197 glStencilFunc(func, ref, mask);
3198 checkGLcall("glStencilFunc(...)");
3202 case WINED3DRS_STENCILREF :
3204 int glParm = This->stencilfunc;
3206 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3209 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3210 glStencilFunc(glParm, ref, mask);
3211 checkGLcall("glStencilFunc");
3215 case WINED3DRS_STENCILMASK :
3217 int glParm = This->stencilfunc;
3218 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3219 GLuint mask = Value;
3221 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3222 glStencilFunc(glParm, ref, mask);
3223 checkGLcall("glStencilFunc");
3227 case WINED3DRS_STENCILFAIL :
3228 case WINED3DRS_STENCILZFAIL :
3229 case WINED3DRS_STENCILPASS :
3235 GLint action = StencilOp(Value);
3237 glGetIntegerv(GL_STENCIL_FAIL, &stencilFail);
3238 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &depthFail);
3239 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &stencilPass);
3241 if(WINED3DRS_STENCILFAIL == State) {
3242 stencilFail = action;
3244 else if(WINED3DRS_STENCILZFAIL == State) {
3247 else if(WINED3DRS_STENCILPASS == State) {
3248 stencilPass = action;
3251 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3252 #if 0 /* Don't use OpenGL 2.0 calls for now */
3253 if(GL_EXTCALL(glStencilOpSeparate)) {
3254 GL_EXTCALL(glStencilOpSeparate(GL_FRONT, stencilFail, depthFail, stencilPass));
3255 checkGLcall("glStencilOpSeparate(GL_FRONT,...)");
3259 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3260 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3261 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3262 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
3263 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
3264 glStencilOp(stencilFail, depthFail, stencilPass);
3265 checkGLcall("glStencilOp(...)");
3267 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3268 GL_EXTCALL(glStencilOpSeparateATI(GL_FRONT, stencilFail, depthFail, stencilPass));
3269 checkGLcall("glStencilOpSeparateATI(GL_FRONT,...)");
3271 TRACE("Separate stencil operation not supported on this version of opengl");
3272 glStencilOp(stencilFail, depthFail, stencilPass);
3273 checkGLcall("glStencilOp(...)");
3276 glStencilOp(stencilFail, depthFail, stencilPass);
3277 checkGLcall("glStencilOp(...)");
3281 case WINED3DRS_STENCILWRITEMASK :
3283 glStencilMask(Value);
3284 TRACE("glStencilMask(%lu)\n", Value);
3285 checkGLcall("glStencilMask");
3289 case WINED3DRS_FOGENABLE :
3291 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
3293 checkGLcall("glEnable GL_FOG");
3296 checkGLcall("glDisable GL_FOG");
3301 case WINED3DRS_RANGEFOGENABLE :
3304 TRACE("Enabled RANGEFOG");
3306 TRACE("Disabled RANGEFOG");
3311 case WINED3DRS_FOGCOLOR :
3314 D3DCOLORTOGLFLOAT4(Value, col);
3315 /* Set the default alpha blend color */
3316 glFogfv(GL_FOG_COLOR, &col[0]);
3317 checkGLcall("glFog GL_FOG_COLOR");
3321 case WINED3DRS_FOGTABLEMODE :
3323 glHint(GL_FOG_HINT, GL_NICEST);
3325 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3326 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3327 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3328 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3330 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3332 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3333 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3338 case WINED3DRS_FOGVERTEXMODE :
3340 glHint(GL_FOG_HINT, GL_FASTEST);
3342 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3343 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3344 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3345 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3347 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3349 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3350 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
3355 case WINED3DRS_FOGSTART :
3358 glFogfv(GL_FOG_START, &tmpvalue.f);
3359 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3360 TRACE("Fog Start == %f\n", tmpvalue.f);
3364 case WINED3DRS_FOGEND :
3367 glFogfv(GL_FOG_END, &tmpvalue.f);
3368 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3369 TRACE("Fog End == %f\n", tmpvalue.f);
3373 case WINED3DRS_FOGDENSITY :
3376 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3377 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3381 case WINED3DRS_VERTEXBLEND :
3383 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3384 TRACE("Vertex Blending state to %ld\n", Value);
3388 case WINED3DRS_TWEENFACTOR :
3391 This->updateStateBlock->tween_factor = tmpvalue.f;
3392 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3396 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
3398 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3402 case WINED3DRS_COLORVERTEX :
3403 case WINED3DRS_DIFFUSEMATERIALSOURCE :
3404 case WINED3DRS_SPECULARMATERIALSOURCE :
3405 case WINED3DRS_AMBIENTMATERIALSOURCE :
3406 case WINED3DRS_EMISSIVEMATERIALSOURCE :
3408 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3410 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3411 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3412 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3413 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3414 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3415 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3417 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3418 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3419 Parm = GL_AMBIENT_AND_DIFFUSE;
3423 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3425 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3427 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3434 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3436 This->tracking_color = NEEDS_TRACKING;
3437 This->tracking_parm = Parm;
3441 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3446 case WINED3DRS_LINEPATTERN :
3452 tmppattern.d = Value;
3454 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3456 if (tmppattern.lp.wRepeatFactor) {
3457 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3458 checkGLcall("glLineStipple(repeat, linepattern)");
3459 glEnable(GL_LINE_STIPPLE);
3460 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3462 glDisable(GL_LINE_STIPPLE);
3463 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3468 case WINED3DRS_ZBIAS : /* D3D8 only */
3472 TRACE("ZBias value %f\n", tmpvalue.f);
3473 glPolygonOffset(0, -tmpvalue.f);
3474 checkGLcall("glPolygonOffset(0, -Value)");
3475 glEnable(GL_POLYGON_OFFSET_FILL);
3476 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3477 glEnable(GL_POLYGON_OFFSET_LINE);
3478 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3479 glEnable(GL_POLYGON_OFFSET_POINT);
3480 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3482 glDisable(GL_POLYGON_OFFSET_FILL);
3483 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3484 glDisable(GL_POLYGON_OFFSET_LINE);
3485 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3486 glDisable(GL_POLYGON_OFFSET_POINT);
3487 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3492 case WINED3DRS_NORMALIZENORMALS :
3494 glEnable(GL_NORMALIZE);
3495 checkGLcall("glEnable(GL_NORMALIZE);");
3497 glDisable(GL_NORMALIZE);
3498 checkGLcall("glDisable(GL_NORMALIZE);");
3502 case WINED3DRS_POINTSIZE :
3503 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
3505 TRACE("Set point size to %f\n", tmpvalue.f);
3506 glPointSize(tmpvalue.f);
3507 checkGLcall("glPointSize(...);");
3510 case WINED3DRS_POINTSIZE_MIN :
3511 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3513 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3514 checkGLcall("glPointParameterfEXT(...);");
3516 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3520 case WINED3DRS_POINTSIZE_MAX :
3521 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3523 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3524 checkGLcall("glPointParameterfEXT(...);");
3526 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3530 case WINED3DRS_POINTSCALE_A :
3531 case WINED3DRS_POINTSCALE_B :
3532 case WINED3DRS_POINTSCALE_C :
3533 case WINED3DRS_POINTSCALEENABLE :
3536 * POINTSCALEENABLE controls how point size value is treated. If set to
3537 * true, the point size is scaled with respect to height of viewport.
3538 * When set to false point size is in pixels.
3540 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
3543 /* Default values */
3544 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3547 * Minimum valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
3548 * This means that OpenGL will clamp really small point sizes to 1.0f.
3549 * To correct for this we need to multiply by the scale factor when sizes
3550 * are less than 1.0f. scale_factor = 1.0f / point_size.
3552 GLfloat pointSize = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSIZE]);
3553 if(pointSize > 0.0f) {
3554 GLfloat scaleFactor;
3556 if(pointSize < 1.0f) {
3557 scaleFactor = pointSize * pointSize;
3562 if(This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3563 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]) /
3564 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3565 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]) /
3566 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3567 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) /
3568 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3572 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
3573 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
3574 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
3576 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3577 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3578 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
3580 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
3584 case WINED3DRS_COLORWRITEENABLE :
3586 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3587 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3588 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3589 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3590 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3591 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3592 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3593 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3594 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3595 checkGLcall("glColorMask(...)");
3599 case WINED3DRS_LOCALVIEWER :
3601 GLint state = (Value) ? 1 : 0;
3602 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3603 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3607 case WINED3DRS_LASTPIXEL :
3610 TRACE("Last Pixel Drawing Enabled\n");
3612 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3617 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3620 TRACE("Software Processing Enabled\n");
3622 TRACE("Software Processing Disabled\n");
3627 /** not supported */
3628 case WINED3DRS_ZVISIBLE :
3631 return WINED3DERR_INVALIDCALL;
3633 case WINED3DRS_POINTSPRITEENABLE :
3635 /* TODO: NV_POINT_SPRITE */
3636 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
3637 TRACE("Point sprites not supported\n");
3642 * Point sprites are always enabled. Value controls texture coordinate
3643 * replacement mode. Must be set true for point sprites to use
3646 glEnable(GL_POINT_SPRITE_ARB);
3647 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
3650 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
3651 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, TRUE)");
3653 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, FALSE);
3654 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, FALSE)");
3658 case WINED3DRS_EDGEANTIALIAS :
3661 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3663 checkGLcall("glEnable(GL_BLEND)");
3664 glEnable(GL_LINE_SMOOTH);
3665 checkGLcall("glEnable(GL_LINE_SMOOTH)");
3667 glDisable(GL_BLEND);
3668 checkGLcall("glDisable(GL_BLEND)");
3669 glDisable(GL_LINE_SMOOTH);
3670 checkGLcall("glDisable(GL_LINE_SMOOTH)");
3674 case WINED3DRS_WRAP0 :
3675 case WINED3DRS_WRAP1 :
3676 case WINED3DRS_WRAP2 :
3677 case WINED3DRS_WRAP3 :
3678 case WINED3DRS_WRAP4 :
3679 case WINED3DRS_WRAP5 :
3680 case WINED3DRS_WRAP6 :
3681 case WINED3DRS_WRAP7 :
3682 case WINED3DRS_WRAP8 :
3683 case WINED3DRS_WRAP9 :
3684 case WINED3DRS_WRAP10 :
3685 case WINED3DRS_WRAP11 :
3686 case WINED3DRS_WRAP12 :
3687 case WINED3DRS_WRAP13 :
3688 case WINED3DRS_WRAP14 :
3689 case WINED3DRS_WRAP15 :
3691 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
3692 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
3693 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
3694 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
3695 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
3697 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
3699 TRACE("(%p)->(%s,%ld) Texture wraping not yet supported\n",This, debug_d3drenderstate(State), Value);
3701 case WINED3DRS_MULTISAMPLEANTIALIAS :
3703 if (!GL_SUPPORT(ARB_MULTISAMPLE)) {
3704 TRACE("Multisample antialiasing not supported\n");
3709 glEnable(GL_MULTISAMPLE_ARB);
3710 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
3712 glDisable(GL_MULTISAMPLE_ARB);
3713 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
3717 case WINED3DRS_SCISSORTESTENABLE :
3720 glEnable(GL_SCISSOR_TEST);
3721 checkGLcall("glEnable(GL_SCISSOR_TEST)");
3723 glDisable(GL_SCISSOR_TEST);
3724 checkGLcall("glDisable(GL_SCISSOR_TEST)");
3728 case WINED3DRS_SLOPESCALEDEPTHBIAS :
3732 glEnable(GL_POLYGON_OFFSET_FILL);
3733 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
3734 glPolygonOffset(tmpvalue.f, *((float*)&This->stateBlock->renderState[WINED3DRS_DEPTHBIAS]));
3735 checkGLcall("glPolygonOffset(...)");
3737 glDisable(GL_POLYGON_OFFSET_FILL);
3738 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
3742 case WINED3DRS_ANTIALIASEDLINEENABLE :
3745 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3747 checkGLcall("glEnable(GL_BLEND)");
3748 glEnable(GL_LINE_SMOOTH);
3749 checkGLcall("glEnable(GL_LINE_SMOOTH)");
3751 glDisable(GL_BLEND);
3752 checkGLcall("glDisable(GL_BLEND)");
3753 glDisable(GL_LINE_SMOOTH);
3754 checkGLcall("glDisable(GL_LINE_SMOOTH)");
3758 case WINED3DRS_TWOSIDEDSTENCILMODE :
3761 TRACE("Two-sided stencil mode enabled\n");
3763 TRACE("Two-sided stencil mode disabled\n");
3767 case WINED3DRS_CCW_STENCILFAIL :
3768 case WINED3DRS_CCW_STENCILZFAIL :
3769 case WINED3DRS_CCW_STENCILPASS :
3775 GLint action = StencilOp(Value);
3777 glGetIntegerv(GL_STENCIL_BACK_FAIL, &stencilFail);
3778 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &depthFail);
3779 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS, &stencilPass);
3781 if(WINED3DRS_CCW_STENCILFAIL == State) {
3782 stencilFail = action;
3784 else if(WINED3DRS_CCW_STENCILZFAIL == State) {
3787 else if(WINED3DRS_CCW_STENCILPASS == State) {
3788 stencilPass = action;
3791 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3792 #if 0 /* Don't use OpenGL 2.0 calls for now */
3793 if(GL_EXTCALL(glStencilOpSeparate)) {
3794 GL_EXTCALL(glStencilOpSeparate(GL_BACK, stencilFail, depthFail, stencilPass));
3795 checkGLcall("glStencilOpSeparate(GL_BACK,...)");
3799 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3800 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3801 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3802 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
3803 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
3804 glStencilOp(stencilFail, depthFail, stencilPass);
3805 checkGLcall("glStencilOp(...)");
3807 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3808 GL_EXTCALL(glStencilOpSeparateATI(GL_BACK, stencilFail, depthFail, stencilPass));
3809 checkGLcall("glStencilOpSeparateATI(GL_BACK,...)");
3811 TRACE("Separate stencil operation not supported on this version of opengl");
3812 glStencilOp(stencilFail, depthFail, stencilPass);
3813 checkGLcall("glStencilOp(...)");
3816 glStencilOp(stencilFail, depthFail, stencilPass);
3817 checkGLcall("glStencilOp(...)");
3821 case WINED3DRS_CCW_STENCILFUNC :
3824 GLint ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3825 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3828 switch ((D3DCMPFUNC)Value) {
3829 case D3DCMP_NEVER: func = GL_NEVER; break;
3830 case D3DCMP_LESS: func = GL_LESS; break;
3831 case D3DCMP_EQUAL: func = GL_EQUAL; break;
3832 case D3DCMP_LESSEQUAL: func = GL_LEQUAL; break;
3833 case D3DCMP_GREATER: func = GL_GREATER; break;
3834 case D3DCMP_NOTEQUAL: func = GL_NOTEQUAL; break;
3835 case D3DCMP_GREATEREQUAL: func = GL_GEQUAL; break;
3836 case D3DCMP_ALWAYS: func = GL_ALWAYS; break;
3838 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3840 This->stencilfunc = func;
3841 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3842 #if 0 /* Don't use OpenGL 2.0 calls for now */
3843 if(GL_EXTCALL(glStencilFuncSeparate)) {
3844 GL_EXTCALL(glStencilFuncSeparate(GL_BACK, func, ref, mask));
3845 checkGLcall("glStencilFuncSeparate(GL_BACK,...)");
3849 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3850 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3851 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3852 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
3853 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
3854 glStencilFunc(func, ref, mask);
3855 checkGLcall("glStencilFunc(...)");
3857 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3858 GL_EXTCALL(glStencilFuncSeparateATI(GL_BACK, func, ref, mask));
3859 checkGLcall("glStencilFuncSeparateATI(GL_BACK,...)");
3861 TRACE("Separate stencil function not supported on this version of opengl");
3862 glStencilFunc(func, ref, mask);
3863 checkGLcall("glStencilFunc(...)");
3866 glStencilFunc(func, ref, mask);
3867 checkGLcall("glStencilFunc(...)");
3871 case WINED3DRS_DEPTHBIAS :
3875 glEnable(GL_POLYGON_OFFSET_FILL);
3876 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
3877 glPolygonOffset(*((float*)&This->stateBlock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS]), tmpvalue.f);
3878 checkGLcall("glPolygonOffset(...)");
3880 glDisable(GL_POLYGON_OFFSET_FILL);
3881 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
3885 case WINED3DRS_SEPARATEALPHABLENDENABLE :
3886 case WINED3DRS_SRCBLENDALPHA :
3887 case WINED3DRS_DESTBLENDALPHA :
3888 case WINED3DRS_BLENDOPALPHA :
3889 case WINED3DRS_MULTISAMPLEMASK :
3890 case WINED3DRS_PATCHEDGESTYLE :
3891 case WINED3DRS_PATCHSEGMENTS :
3892 case WINED3DRS_DEBUGMONITORTOKEN :
3893 case WINED3DRS_POSITIONORDER :
3894 case WINED3DRS_NORMALORDER :
3895 case WINED3DRS_MINTESSELLATIONLEVEL :
3896 case WINED3DRS_MAXTESSELLATIONLEVEL :
3897 case WINED3DRS_ADAPTIVETESS_X :
3898 case WINED3DRS_ADAPTIVETESS_Y :
3899 case WINED3DRS_ADAPTIVETESS_Z :
3900 case WINED3DRS_ADAPTIVETESS_W :
3901 case WINED3DRS_ENABLEADAPTIVETESSELLATION :
3902 case WINED3DRS_COLORWRITEENABLE1 :
3903 case WINED3DRS_COLORWRITEENABLE2 :
3904 case WINED3DRS_COLORWRITEENABLE3 :
3905 case WINED3DRS_BLENDFACTOR :
3906 case WINED3DRS_SRGBWRITEENABLE :
3907 FIXME("(%p)->(%s,%ld) not handled yet\n", This, debug_d3drenderstate(State), Value);
3910 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3918 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3919 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3920 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3921 *pValue = This->stateBlock->renderState[State];
3926 * Get / Set Sampler States
3927 * TODO: Verify against dx9 definitions
3930 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3931 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3933 * SetSampler is designed to allow for more than the standard up to 8 textures
3934 * and Geforce has stopped supporting more than 6 standard textures in openGL.
3935 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3937 * http://developer.nvidia.com/object/General_FAQ.html#t6
3939 * There are two new settings for GForce
3941 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3942 * and the texture one:
3943 * GL_MAX_TEXTURE_COORDS_ARB.
3944 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3946 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
3947 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
3949 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
3950 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE, Sampler, Type);
3951 return WINED3DERR_INVALIDCALL;
3953 TRACE("Setting sampler %ld %d to %ld\n", Sampler, Type, Value);
3954 This->updateStateBlock->samplerState[Sampler][Type] = Value;
3955 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
3956 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
3958 /* Handle recording of state blocks */
3959 if (This->isRecordingState) {
3960 TRACE("Recording... not performing anything\n");
3967 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3968 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3969 /** TODO: check that sampler is in range **/
3970 *Value = This->updateStateBlock->samplerState[Sampler][Type];
3971 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
3976 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3977 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3980 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3981 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3982 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3988 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3989 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3990 GLint scissorBox[4];
3993 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3994 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
3995 pRect->left = scissorBox[1];
3996 pRect->top = scissorBox[2];
3997 pRect->right = scissorBox[1] + scissorBox[3];
3998 pRect->bottom = scissorBox[2] + scissorBox[4];
3999 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4004 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
4005 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4006 IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
4008 TRACE("(%p) : pDecl=%p\n", This, pDecl);
4010 This->updateStateBlock->vertexDecl = pDecl;
4011 This->updateStateBlock->changed.vertexDecl = TRUE;
4012 This->updateStateBlock->set.vertexDecl = TRUE;
4014 if (This->isRecordingState) {
4015 TRACE("Recording... not performing anything\n");
4018 if (NULL != pDecl) {
4019 IWineD3DVertexDeclaration_AddRef(pDecl);
4021 if (NULL != oldDecl) {
4022 IWineD3DVertexDeclaration_Release(oldDecl);
4027 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
4028 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4030 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
4032 *ppDecl = This->stateBlock->vertexDecl;
4033 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
4037 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
4038 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4039 IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
4041 This->updateStateBlock->vertexShader = pShader;
4042 This->updateStateBlock->changed.vertexShader = TRUE;
4043 This->updateStateBlock->set.vertexShader = TRUE;
4045 if (This->isRecordingState) {
4046 TRACE("Recording... not performing anything\n");
4049 if (NULL != pShader) {
4050 IWineD3DVertexShader_AddRef(pShader);
4052 if (NULL != oldShader) {
4053 IWineD3DVertexShader_Release(oldShader);
4056 if (pShader != NULL && ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration != NULL) {
4057 TRACE("(%p) : setting vertexDeclaration(%p)\n", This, ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration);
4058 IWineD3DDevice_SetVertexDeclaration(iface, ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration);
4061 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4063 * TODO: merge HAL shaders context switching from prototype
4068 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
4069 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4071 if (NULL == ppShader) {
4072 return WINED3DERR_INVALIDCALL;
4074 *ppShader = This->stateBlock->vertexShader;
4075 if( NULL != *ppShader)
4076 IWineD3DVertexShader_AddRef(*ppShader);
4078 TRACE("(%p) : returning %p\n", This, *ppShader);
4082 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4083 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4086 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4088 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4089 iface, dstData, srcData, type, start, count, registersize);
4091 if (type != WINESHADERCNST_NONE) {
4092 if (srcData == NULL || cnt < 0) {
4093 return WINED3DERR_INVALIDCALL;
4096 CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
4099 for (i = start; i < cnt + start; ++i) {
4100 This->updateStateBlock->changed.vertexShaderConstants[i] = TRUE;
4101 This->updateStateBlock->set.vertexShaderConstants[i] = TRUE;
4102 This->updateStateBlock->vertexShaderConstantT[i] = type;
4108 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4109 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4112 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4114 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4115 iface, dstData, srcData, type, start, count, registersize);
4117 /* Verify that the requested shader constant was populated with the correct type */
4118 for (i = start; i < cnt + start; ++i) {
4119 if (This->updateStateBlock->vertexShaderConstantT[i] != type) {
4120 TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning WINED3DERR_INVALIDCALL\n",
4121 This, type, This->updateStateBlock->vertexShaderConstantT[i]);
4122 return WINED3DERR_INVALIDCALL;
4126 if (dstData == NULL || cnt < 0) {
4127 return WINED3DERR_INVALIDCALL;
4130 CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
4135 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
4136 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4138 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4139 This->updateStateBlock->vertexShaderConstantB,
4141 WINESHADERCNST_BOOL,
4144 sizeof(*pConstantData));
4147 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
4148 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4150 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4152 This->updateStateBlock->vertexShaderConstantB,
4153 WINESHADERCNST_BOOL,
4156 sizeof(*pConstantData));
4159 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
4160 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4162 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4163 This->updateStateBlock->vertexShaderConstantI,
4165 WINESHADERCNST_INTEGER,
4168 4 * sizeof(*pConstantData));
4171 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
4172 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4174 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4176 This->updateStateBlock->vertexShaderConstantI,
4177 WINESHADERCNST_INTEGER,
4180 4 * sizeof(*pConstantData));
4184 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
4185 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4187 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4188 This->updateStateBlock->vertexShaderConstantF,
4190 WINESHADERCNST_FLOAT,
4193 4 * sizeof(*pConstantData));
4196 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
4197 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4199 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4201 This->updateStateBlock->vertexShaderConstantF,
4202 WINESHADERCNST_FLOAT,
4205 4 * sizeof(*pConstantData));
4208 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
4209 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4212 WINESHADERCNST_NONE,
4218 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
4219 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4220 IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader;
4221 This->updateStateBlock->pixelShader = pShader;
4222 This->updateStateBlock->changed.pixelShader = TRUE;
4223 This->updateStateBlock->set.pixelShader = TRUE;
4225 /* Handle recording of state blocks */
4226 if (This->isRecordingState) {
4227 TRACE("Recording... not performing anything\n");
4230 if (NULL != pShader) {
4231 IWineD3DPixelShader_AddRef(pShader);
4233 if (NULL != oldShader) {
4234 IWineD3DPixelShader_Release(oldShader);
4237 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4239 * TODO: merge HAL shaders context switching from prototype
4244 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
4245 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4247 if (NULL == ppShader) {
4248 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
4249 return WINED3DERR_INVALIDCALL;
4252 *ppShader = This->stateBlock->pixelShader;
4253 if (NULL != ppShader) {
4254 IWineD3DPixelShader_AddRef(*ppShader);
4256 TRACE("(%p) : returning %p\n", This, *ppShader);
4260 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4261 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4264 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4266 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4267 iface, dstData, srcData, type, start, count, registersize);
4269 if (type != WINESHADERCNST_NONE) {
4270 if (srcData == NULL || cnt < 0) {
4271 return WINED3DERR_INVALIDCALL;
4274 CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
4277 for (i = start; i < cnt + start; ++i) {
4278 This->updateStateBlock->changed.pixelShaderConstants[i] = TRUE;
4279 This->updateStateBlock->set.pixelShaderConstants[i] = TRUE;
4280 This->updateStateBlock->pixelShaderConstantT[i] = type;
4286 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4287 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4290 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4292 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4293 iface, dstData, srcData, type, start, count, registersize);
4295 /* Verify that the requested shader constant was populated with the correct type */
4296 for (i = start; i < cnt + start; ++i) {
4297 if (This->updateStateBlock->pixelShaderConstantT[i] != type) {
4298 TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning WINED3DERR_INVALIDCALL\n",
4299 This, type, This->updateStateBlock->pixelShaderConstantT[i]);
4300 return WINED3DERR_INVALIDCALL;
4304 if (dstData == NULL || cnt < 0) {
4305 return WINED3DERR_INVALIDCALL;
4308 CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
4313 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
4314 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4316 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4317 This->updateStateBlock->pixelShaderConstantB,
4319 WINESHADERCNST_BOOL,
4322 sizeof(*pConstantData));
4325 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
4326 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4328 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4330 This->updateStateBlock->pixelShaderConstantB,
4331 WINESHADERCNST_BOOL,
4334 sizeof(*pConstantData));
4337 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
4338 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4340 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4341 This->updateStateBlock->pixelShaderConstantI,
4343 WINESHADERCNST_INTEGER,
4346 4 * sizeof(*pConstantData));
4349 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
4350 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4352 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4354 This->updateStateBlock->pixelShaderConstantI,
4355 WINESHADERCNST_INTEGER,
4358 4 * sizeof(*pConstantData));
4361 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
4362 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4364 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4365 This->updateStateBlock->pixelShaderConstantF,
4367 WINESHADERCNST_FLOAT,
4370 4 * sizeof(*pConstantData));
4373 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
4374 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4376 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4378 This->updateStateBlock->pixelShaderConstantF,
4379 WINESHADERCNST_FLOAT,
4382 4 * sizeof(*pConstantData));
4385 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
4386 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4389 WINESHADERCNST_NONE,
4395 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
4396 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4397 FIXME("(%p) : stub\n", This);
4402 * Apply / Get / Set Texture Stage States
4403 * TODO: Verify against dx9 definitions
4406 /* NOTE: It's expected that this function is going to be called lots of times with the same stage active, so make it the callers responsibility to GLACTIVETEXTURE(Stage) for better state management. Set the correct Texture unit active before calling ApplyTextureStageState */
4407 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
4408 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4409 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
4410 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4412 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4414 /* Check that the stage is within limits */
4415 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4416 TRACE("Attempt to access invalid texture rejected\n");
4423 case WINED3DTSS_ALPHAOP :
4424 case WINED3DTSS_COLOROP :
4425 /* nothing to do as moved to drawprim for now */
4427 case WINED3DTSS_ADDRESSW :
4428 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
4429 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
4430 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
4433 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
4434 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
4435 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
4436 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
4439 case WINED3DTSS_TEXCOORDINDEX :
4441 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
4443 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
4444 one flag, you can still specify an index value, which the system uses to
4445 determine the texture wrapping mode.
4446 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
4447 means use the vertex position (camera-space) as the input texture coordinates
4448 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
4449 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
4450 to the TEXCOORDINDEX value */
4453 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
4455 switch (Value & 0xFFFF0000) {
4456 case D3DTSS_TCI_PASSTHRU:
4457 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
4458 glDisable(GL_TEXTURE_GEN_S);
4459 glDisable(GL_TEXTURE_GEN_T);
4460 glDisable(GL_TEXTURE_GEN_R);
4461 glDisable(GL_TEXTURE_GEN_Q);
4462 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
4465 case D3DTSS_TCI_CAMERASPACEPOSITION:
4466 /* CameraSpacePosition means use the vertex position, transformed to camera space,
4467 as the input texture coordinates for this stage's texture transformation. This
4468 equates roughly to EYE_LINEAR */
4470 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4471 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4472 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4473 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4474 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4476 glMatrixMode(GL_MODELVIEW);
4479 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4480 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4481 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4482 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4485 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
4486 glEnable(GL_TEXTURE_GEN_S);
4487 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4488 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4489 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4490 glEnable(GL_TEXTURE_GEN_T);
4491 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4492 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4493 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4494 glEnable(GL_TEXTURE_GEN_R);
4495 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4496 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4497 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4501 case D3DTSS_TCI_CAMERASPACENORMAL:
4503 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4504 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4505 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4506 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4507 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4508 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
4510 glMatrixMode(GL_MODELVIEW);
4513 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4514 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4515 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4516 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4519 glEnable(GL_TEXTURE_GEN_S);
4520 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4521 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4522 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4523 glEnable(GL_TEXTURE_GEN_T);
4524 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4525 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4526 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4527 glEnable(GL_TEXTURE_GEN_R);
4528 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4529 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4530 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4535 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
4537 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4538 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4539 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4540 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4541 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4542 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
4544 glMatrixMode(GL_MODELVIEW);
4547 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4548 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4549 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4550 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4553 glEnable(GL_TEXTURE_GEN_S);
4554 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4555 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4556 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4557 glEnable(GL_TEXTURE_GEN_T);
4558 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4559 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4560 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4561 glEnable(GL_TEXTURE_GEN_R);
4562 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4563 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4564 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4569 /* Unhandled types: */
4572 /* ? disable GL_TEXTURE_GEN_n ? */
4573 glDisable(GL_TEXTURE_GEN_S);
4574 glDisable(GL_TEXTURE_GEN_T);
4575 glDisable(GL_TEXTURE_GEN_R);
4576 glDisable(GL_TEXTURE_GEN_Q);
4577 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
4584 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
4585 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);
4588 case WINED3DTSS_BUMPENVMAT00 :
4589 case WINED3DTSS_BUMPENVMAT01 :
4590 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
4592 case WINED3DTSS_BUMPENVMAT10 :
4593 case WINED3DTSS_BUMPENVMAT11 :
4594 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
4597 case WINED3DTSS_BUMPENVLSCALE :
4598 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4601 case WINED3DTSS_BUMPENVLOFFSET :
4602 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4605 case WINED3DTSS_RESULTARG :
4606 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4610 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
4611 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4620 * Get / Set Texture Stage States
4621 * TODO: Verify against dx9 definitions
4623 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
4624 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4626 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4628 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4630 /* Reject invalid texture units */
4631 if (Stage >= GL_LIMITS(textures)) {
4632 TRACE("Attempt to access invalid texture rejected\n");
4633 return WINED3DERR_INVALIDCALL;
4636 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
4637 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
4638 This->updateStateBlock->textureState[Stage][Type] = Value;
4643 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4644 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4645 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4646 *pValue = This->updateStateBlock->textureState[Stage][Type];
4653 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4655 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4656 IWineD3DBaseTexture *oldTexture;
4658 oldTexture = This->updateStateBlock->textures[Stage];
4659 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
4661 #if 0 /* TODO: check so vertex textures */
4662 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
4663 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
4668 /* Reject invalid texture units */
4669 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4670 WARN("Attempt to access invalid texture rejected\n");
4671 return WINED3DERR_INVALIDCALL;
4674 if(pTexture != NULL) {
4675 /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH; The same is
4676 * the case for WINED3DPOOL_SYSTEMMEM textures unless WINED3DDEVCAPS_TEXTURESYSTEMMORY is set.
4677 * We don't check the caps as GetDeviceCaps is inefficient and we don't set the cap anyway.
4679 if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH || ((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SYSTEMMEM) {
4680 WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
4681 return WINED3DERR_INVALIDCALL;
4685 oldTexture = This->updateStateBlock->textures[Stage];
4686 TRACE("GL_LIMITS %d\n",GL_LIMITS(textures));
4687 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
4689 This->updateStateBlock->set.textures[Stage] = TRUE;
4690 This->updateStateBlock->changed.textures[Stage] = TRUE;
4691 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
4692 This->updateStateBlock->textures[Stage] = pTexture;
4694 /* Handle recording of state blocks */
4695 if (This->isRecordingState) {
4696 TRACE("Recording... not performing anything\n");
4700 /** NOTE: MSDN says that setTexture increases the reference count,
4701 * and the the application nust set the texture back to null (or have a leaky application),
4702 * This means we should pass the refcount up to the parent
4703 *******************************/
4704 if (NULL != This->updateStateBlock->textures[Stage]) {
4705 IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
4708 if (NULL != oldTexture) {
4709 IWineD3DBaseTexture_Release(oldTexture);
4715 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4716 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4717 TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
4719 /* Reject invalid texture units */
4720 if (Stage >= GL_LIMITS(textures)) {
4721 TRACE("Attempt to access invalid texture rejected\n");
4722 return WINED3DERR_INVALIDCALL;
4724 *ppTexture=This->updateStateBlock->textures[Stage];
4726 IWineD3DBaseTexture_AddRef(*ppTexture);
4728 return WINED3DERR_INVALIDCALL;
4735 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
4736 IWineD3DSurface **ppBackBuffer) {
4737 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4738 IWineD3DSwapChain *swapChain;
4741 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4743 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4744 if (hr == WINED3D_OK) {
4745 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4746 IWineD3DSwapChain_Release(swapChain);
4748 *ppBackBuffer = NULL;
4753 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4754 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4755 WARN("(%p) : stub, calling idirect3d for now\n", This);
4756 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4759 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
4760 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4761 IWineD3DSwapChain *swapChain;
4764 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4765 if (hr == WINED3D_OK) {
4766 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4767 IWineD3DSwapChain_Release(swapChain);
4769 FIXME("(%p) Error getting display mode\n", This);
4774 * Stateblock related functions
4777 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4778 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4779 IWineD3DStateBlockImpl *object;
4780 TRACE("(%p)", This);
4782 if (This->isRecordingState) {
4783 return WINED3DERR_INVALIDCALL;
4786 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4787 if (NULL == object ) {
4788 FIXME("(%p)Error allocating memory for stateblock\n", This);
4789 return E_OUTOFMEMORY;
4791 TRACE("(%p) creted object %p\n", This, object);
4792 object->wineD3DDevice= This;
4793 /** FIXME: object->parent = parent; **/
4794 object->parent = NULL;
4795 object->blockType = WINED3DSBT_ALL;
4797 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
4799 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4800 This->updateStateBlock = object;
4801 This->isRecordingState = TRUE;
4803 TRACE("(%p) recording stateblock %p\n",This , object);
4807 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4808 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4810 if (!This->isRecordingState) {
4811 FIXME("(%p) not recording! returning error\n", This);
4812 *ppStateBlock = NULL;
4813 return WINED3DERR_INVALIDCALL;
4816 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4817 This->isRecordingState = FALSE;
4818 This->updateStateBlock = This->stateBlock;
4819 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4820 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4821 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4826 * Scene related functions
4828 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4829 /* At the moment we have no need for any functionality at the beginning
4831 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4832 TRACE("(%p) : stub\n", This);
4836 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4837 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4838 TRACE("(%p)\n", This);
4840 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4842 checkGLcall("glFlush");
4844 TRACE("End Scene\n");
4845 if(This->renderTarget != NULL) {
4847 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4848 IUnknown *targetContainer = NULL;
4849 if (WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
4850 || WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
4851 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
4852 /** always dirtify for now. we must find a better way to see that surface have been modified
4853 (Modifications should will only occur via draw-primitive, but we do need better locking
4854 switching to render-to-texture should remove the overhead though.
4856 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4857 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
4858 IWineD3DSurface_PreLoad(This->renderTarget);
4859 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4860 IUnknown_Release(targetContainer);
4863 This->sceneEnded = TRUE;
4868 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4869 CONST RECT* pSourceRect, CONST RECT* pDestRect,
4870 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4871 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4872 IWineD3DSwapChain *swapChain = NULL;
4874 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4876 TRACE("(%p) Presenting the frame\n", This);
4878 for(i = 0 ; i < swapchains ; i ++) {
4880 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4881 TRACE("presentinng chain %d, %p\n", i, swapChain);
4882 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4883 IWineD3DSwapChain_Release(swapChain);
4889 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4890 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4891 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4893 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4894 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4895 when the depth-buffer format does not contain stencil buffer information, this method fails. */
4896 GLbitfield glMask = 0;
4897 GLboolean old_ztest;
4898 GLfloat old_z_clear_value;
4899 GLint old_stencil_clear_value;
4900 GLfloat old_color_clear_value[4];
4902 CONST D3DRECT* curRect;
4904 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4905 Count, pRects, Flags, Z, Stencil);
4909 glEnable(GL_SCISSOR_TEST);
4910 checkGLcall("glEnable GL_SCISSOR_TEST");
4912 if (Count > 0 && pRects) {
4918 /* Only set the values up once, as they are not changing */
4919 if (Flags & D3DCLEAR_STENCIL) {
4920 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4921 glClearStencil(Stencil);
4922 checkGLcall("glClearStencil");
4923 glMask = glMask | GL_STENCIL_BUFFER_BIT;
4924 glStencilMask(0xFFFFFFFF);
4927 if (Flags & D3DCLEAR_ZBUFFER) {
4928 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4929 glDepthMask(GL_TRUE);
4930 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4932 checkGLcall("glClearDepth");
4933 glMask = glMask | GL_DEPTH_BUFFER_BIT;
4936 if (Flags & D3DCLEAR_TARGET) {
4937 TRACE("Clearing screen with glClear to color %lx\n", Color);
4938 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4939 glClearColor(D3DCOLOR_R(Color),
4943 checkGLcall("glClearColor");
4945 /* Clear ALL colors! */
4946 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4947 glMask = glMask | GL_COLOR_BUFFER_BIT;
4950 /* Now process each rect in turn */
4951 for (i = 0; i < Count || i == 0; i++) {
4954 /* Note gl uses lower left, width/height */
4955 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4956 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4957 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4958 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4959 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4960 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4961 checkGLcall("glScissor");
4963 glScissor(This->stateBlock->viewport.X,
4964 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
4965 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4966 This->stateBlock->viewport.Width,
4967 This->stateBlock->viewport.Height);
4968 checkGLcall("glScissor");
4971 /* Clear the selected rectangle (or full screen) */
4973 checkGLcall("glClear");
4975 /* Step to the next rectangle */
4976 if (curRect) curRect = curRect + sizeof(D3DRECT);
4979 /* Restore the old values (why..?) */
4980 if (Flags & D3DCLEAR_STENCIL) {
4981 glClearStencil(old_stencil_clear_value);
4982 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4984 if (Flags & D3DCLEAR_ZBUFFER) {
4985 glDepthMask(old_ztest);
4986 glClearDepth(old_z_clear_value);
4988 if (Flags & D3DCLEAR_TARGET) {
4989 glClearColor(old_color_clear_value[0],
4990 old_color_clear_value[1],
4991 old_color_clear_value[2],
4992 old_color_clear_value[3]);
4993 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4994 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4995 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4996 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4999 glDisable(GL_SCISSOR_TEST);
5000 checkGLcall("glDisable");
5009 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
5010 UINT PrimitiveCount) {
5012 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5013 This->stateBlock->streamIsUP = FALSE;
5015 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
5016 debug_d3dprimitivetype(PrimitiveType),
5017 StartVertex, PrimitiveCount);
5018 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
5019 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
5025 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
5026 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
5027 D3DPRIMITIVETYPE PrimitiveType,
5028 INT baseVIndex, UINT minIndex,
5029 UINT NumVertices, UINT startIndex, UINT primCount) {
5031 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5033 IWineD3DIndexBuffer *pIB;
5034 WINED3DINDEXBUFFER_DESC IdxBufDsc;
5036 pIB = This->stateBlock->pIndexData;
5037 This->stateBlock->streamIsUP = FALSE;
5039 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
5040 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5041 minIndex, NumVertices, startIndex, baseVIndex, primCount);
5043 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
5044 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
5050 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
5051 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
5056 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
5057 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
5058 UINT VertexStreamZeroStride) {
5059 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5061 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
5062 debug_d3dprimitivetype(PrimitiveType),
5063 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
5065 /* release the stream source */
5066 if (This->stateBlock->streamSource[0] != NULL) {
5067 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5070 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5071 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5072 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5073 This->stateBlock->streamIsUP = TRUE;
5075 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
5076 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
5077 /* stream zero settings set to null at end, as per the msdn
5078 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
5080 This->stateBlock->streamStride[0] = 0;
5081 This->stateBlock->streamSource[0] = NULL;
5083 /*stream zero settings set to null at end, as per the msdn */
5087 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
5088 UINT MinVertexIndex, UINT NumVertices,
5089 UINT PrimitiveCount, CONST void* pIndexData,
5090 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
5091 UINT VertexStreamZeroStride) {
5093 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5095 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
5096 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5097 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
5098 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
5100 if (IndexDataFormat == WINED3DFMT_INDEX16) {
5106 /* release the stream and index data */
5107 if (This->stateBlock->streamSource[0] != NULL) {
5108 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5110 if (This->stateBlock->pIndexData) {
5111 IWineD3DIndexBuffer_Release(This->stateBlock->pIndexData);
5114 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5115 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5116 This->stateBlock->streamIsUP = TRUE;
5117 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5119 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
5120 /* stream zero settings set to null at end as per the msdn
5121 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
5124 /* stream zero settings set to null at end as per the msdn */
5125 This->stateBlock->streamSource[0] = NULL;
5126 This->stateBlock->streamStride[0] = 0;
5131 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
5132 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
5133 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5134 HRESULT hr = WINED3D_OK;
5135 WINED3DRESOURCETYPE sourceType;
5136 WINED3DRESOURCETYPE destinationType;
5139 /* TODO: think about moving the code into IWineD3DBaseTexture */
5141 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
5143 /* verify that the source and destination textures aren't NULL */
5144 if (NULL == pSourceTexture || NULL == pDestinationTexture) {
5145 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
5146 This, pSourceTexture, pDestinationTexture);
5147 hr = WINED3DERR_INVALIDCALL;
5150 if (pSourceTexture == pDestinationTexture) {
5151 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
5152 This, pSourceTexture, pDestinationTexture);
5153 hr = WINED3DERR_INVALIDCALL;
5155 /* Verify that the source and destination textures are the same type */
5156 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
5157 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
5159 if (sourceType != destinationType) {
5160 WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
5162 hr = WINED3DERR_INVALIDCALL;
5165 /* check that both textures have the identical numbers of levels */
5166 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
5167 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
5168 hr = WINED3DERR_INVALIDCALL;
5171 if (WINED3D_OK == hr) {
5173 /* Make sure that the destination texture is loaded */
5174 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
5176 /* Update every surface level of the texture */
5177 levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
5179 switch (sourceType) {
5180 case WINED3DRTYPE_TEXTURE:
5182 IWineD3DSurface *srcSurface;
5183 IWineD3DSurface *destSurface;
5185 for (i = 0 ; i < levels ; ++i) {
5186 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture, i, &srcSurface);
5187 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
5188 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5189 IWineD3DSurface_Release(srcSurface);
5190 IWineD3DSurface_Release(destSurface);
5191 if (WINED3D_OK != hr) {
5192 WARN("(%p) : Call to update surface failed\n", This);
5198 case WINED3DRTYPE_CUBETEXTURE:
5200 IWineD3DSurface *srcSurface;
5201 IWineD3DSurface *destSurface;
5202 WINED3DCUBEMAP_FACES faceType;
5204 for (i = 0 ; i < levels ; ++i) {
5205 /* Update each cube face */
5206 for (faceType = D3DCUBEMAP_FACE_POSITIVE_X; faceType <= D3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
5207 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture, faceType, i, &srcSurface);
5208 if (WINED3D_OK != hr) {
5209 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5211 TRACE("Got srcSurface %p\n", srcSurface);
5213 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
5214 if (WINED3D_OK != hr) {
5215 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5217 TRACE("Got desrSurface %p\n", destSurface);
5219 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5220 IWineD3DSurface_Release(srcSurface);
5221 IWineD3DSurface_Release(destSurface);
5222 if (WINED3D_OK != hr) {
5223 WARN("(%p) : Call to update surface failed\n", This);
5230 #if 0 /* TODO: Add support for volume textures */
5231 case WINED3DRTYPE_VOLUMETEXTURE:
5233 IWineD3DVolume srcVolume = NULL;
5234 IWineD3DSurface destVolume = NULL;
5236 for (i = 0 ; i < levels ; ++i) {
5237 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture, i, &srcVolume);
5238 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
5239 hr = IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
5240 IWineD3DVolume_Release(srcSurface);
5241 IWineD3DVolume_Release(destSurface);
5242 if (WINED3D_OK != hr) {
5243 WARN("(%p) : Call to update volume failed\n", This);
5251 FIXME("(%p) : Unsupported source and destination type\n", This);
5252 hr = WINED3DERR_INVALIDCALL;
5259 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
5260 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
5261 CONST RECT* pDestRect, WINED3DTEXTUREFILTERTYPE Filter) {
5262 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5264 TRACE("(%p) : stub\n", This);
5267 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
5268 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5269 /** TODO: remove remove casts to IWineD3DSurfaceImpl *
5270 * NOTE It may be best to move the code into surface to occomplish this
5271 ****************************************/
5273 WINED3DSURFACE_DESC surfaceDesc;
5274 unsigned int surfaceWidth, surfaceHeight;
5275 glDescriptor *targetGlDescription = NULL;
5276 glDescriptor *surfaceGlDescription = NULL;
5277 IWineD3DSwapChainImpl *container = NULL;
5279 IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
5280 IWineD3DSurface_GetGlDesc(pSurface, &surfaceGlDescription);
5281 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5283 surfaceDesc.Width = &surfaceWidth;
5284 surfaceDesc.Height = &surfaceHeight;
5285 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5286 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
5288 /* Ok, I may need to setup some kind of active swapchain reference on the device */
5289 IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
5291 /* TODO: opengl Context switching for swapchains etc... */
5292 if (NULL != container || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
5293 if (NULL != container && (pRenderTarget == container->backBuffer)) {
5294 glReadBuffer(GL_BACK);
5295 vcheckGLcall("glReadBuffer(GL_BACK)");
5296 } else if ((NULL != container && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
5297 glReadBuffer(GL_FRONT);
5298 vcheckGLcall("glReadBuffer(GL_FRONT)");
5299 } else if (pRenderTarget == This->depthStencilBuffer) {
5300 FIXME("Reading of depthstencil not yet supported\n");
5303 glReadPixels(surfaceGlDescription->target,
5304 surfaceGlDescription->level,
5307 surfaceGlDescription->glFormat,
5308 surfaceGlDescription->glType,
5309 (void *)IWineD3DSurface_GetData(pSurface));
5310 vcheckGLcall("glReadPixels(...)");
5311 if(NULL != container ){
5312 IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
5315 IWineD3DBaseTexture *container;
5316 GLenum textureDimensions = GL_TEXTURE_2D;
5318 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
5319 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
5320 IWineD3DBaseTexture_Release(container);
5322 /* TODO: 2D -> Cube surface coppies etc.. */
5323 if (surfaceGlDescription->target != textureDimensions) {
5324 FIXME("(%p) : Texture dimension mismatch\n", This);
5326 glEnable(textureDimensions);
5327 vcheckGLcall("glEnable(GL_TEXTURE_...)");
5328 /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
5329 glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
5330 vcheckGLcall("glBindTexture");
5331 glGetTexImage(surfaceGlDescription->target,
5332 surfaceGlDescription->level,
5333 surfaceGlDescription->glFormat,
5334 surfaceGlDescription->glType,
5335 (void *)IWineD3DSurface_GetData(pSurface));
5336 glDisable(textureDimensions);
5337 vcheckGLcall("glDisable(GL_TEXTURE_...)");
5344 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
5345 IWineD3DSwapChain *swapChain;
5347 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5348 if(hr == WINED3D_OK) {
5349 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
5350 IWineD3DSwapChain_Release(swapChain);
5355 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5356 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5357 /* return a sensible default */
5359 /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
5360 FIXME("(%p) : stub\n", This);
5364 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5365 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5367 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5368 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5369 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5370 return WINED3DERR_INVALIDCALL;
5372 for (j = 0; j < 256; ++j) {
5373 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
5374 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5375 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
5376 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5378 TRACE("(%p) : returning\n", This);
5382 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5383 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5385 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5386 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5387 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5388 return WINED3DERR_INVALIDCALL;
5390 for (j = 0; j < 256; ++j) {
5391 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
5392 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5393 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
5394 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5396 TRACE("(%p) : returning\n", This);
5400 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5401 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5402 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5403 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5404 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5405 return WINED3DERR_INVALIDCALL;
5407 /*TODO: stateblocks */
5408 This->currentPalette = PaletteNumber;
5409 TRACE("(%p) : returning\n", This);
5413 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
5414 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5415 if (PaletteNumber == NULL) {
5416 WARN("(%p) : returning Invalid Call\n", This);
5417 return WINED3DERR_INVALIDCALL;
5419 /*TODO: stateblocks */
5420 *PaletteNumber = This->currentPalette;
5421 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
5425 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
5426 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5427 static BOOL showFixmes = TRUE;
5429 FIXME("(%p) : stub\n", This);
5433 This->softwareVertexProcessing = bSoftware;
5438 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
5439 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5440 static BOOL showFixmes = TRUE;
5442 FIXME("(%p) : stub\n", This);
5445 return This->softwareVertexProcessing;
5449 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
5450 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5451 IWineD3DSwapChain *swapChain;
5454 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
5456 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5457 if(hr == WINED3D_OK){
5458 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
5459 IWineD3DSwapChain_Release(swapChain);
5461 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
5467 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
5468 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5469 static BOOL showfixmes = TRUE;
5470 if(nSegments != 0.0f) {
5472 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
5479 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
5480 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5481 static BOOL showfixmes = TRUE;
5483 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
5489 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
5490 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5491 /** TODO: remove casts to IWineD3DSurfaceImpl
5492 * NOTE: move code to surface to accomplish this
5493 ****************************************/
5494 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
5495 int srcWidth, srcHeight;
5496 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
5497 WINED3DFORMAT destFormat, srcFormat;
5499 int destLeft, destTop;
5500 WINED3DPOOL srcPool, destPool;
5502 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
5503 glDescriptor *glDescription = NULL;
5504 GLenum textureDimensions = GL_TEXTURE_2D;
5505 IWineD3DBaseTexture *baseTexture;
5507 WINED3DSURFACE_DESC winedesc;
5509 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
5510 memset(&winedesc, 0, sizeof(winedesc));
5511 winedesc.Width = &srcSurfaceWidth;
5512 winedesc.Height = &srcSurfaceHeight;
5513 winedesc.Pool = &srcPool;
5514 winedesc.Format = &srcFormat;
5516 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5518 winedesc.Width = &destSurfaceWidth;
5519 winedesc.Height = &destSurfaceHeight;
5520 winedesc.Pool = &destPool;
5521 winedesc.Format = &destFormat;
5522 winedesc.Size = &destSize;
5524 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5526 if(srcPool != WINED3DPOOL_SYSTEMMEM || destPool != WINED3DPOOL_DEFAULT){
5527 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
5528 return WINED3DERR_INVALIDCALL;
5531 if (destFormat == WINED3DFMT_UNKNOWN) {
5532 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5533 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5535 /* Get the update surface description */
5536 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5539 /* Make sure the surface is loaded and up to date */
5540 IWineD3DSurface_PreLoad(pDestinationSurface);
5542 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
5546 /* this needs to be done in lines if the sourceRect != the sourceWidth */
5547 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
5548 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
5549 destLeft = pDestPoint ? pDestPoint->x : 0;
5550 destTop = pDestPoint ? pDestPoint->y : 0;
5553 /* This function doesn't support compressed textures
5554 the pitch is just bytesPerPixel * width */
5555 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
5556 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
5557 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
5558 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
5560 /* TODO DXT formats */
5562 if(pSourceRect != NULL && pSourceRect->top != 0){
5563 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
5565 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
5567 ,glDescription->level
5572 ,glDescription->glFormat
5573 ,glDescription->glType
5574 ,IWineD3DSurface_GetData(pSourceSurface)
5578 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
5580 /* need to lock the surface to get the data */
5581 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5584 /* TODO: Cube and volume support */
5586 /* not a whole row so we have to do it a line at a time */
5589 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
5590 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5592 for(j = destTop ; j < (srcHeight + destTop) ; j++){
5594 glTexSubImage2D(glDescription->target
5595 ,glDescription->level
5600 ,glDescription->glFormat
5601 ,glDescription->glType
5602 ,data /* could be quicker using */
5607 } else { /* Full width, so just write out the whole texture */
5609 if (WINED3DFMT_DXT1 == destFormat ||
5610 WINED3DFMT_DXT2 == destFormat ||
5611 WINED3DFMT_DXT3 == destFormat ||
5612 WINED3DFMT_DXT4 == destFormat ||
5613 WINED3DFMT_DXT5 == destFormat) {
5614 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
5615 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
5616 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
5617 FIXME("Updating part of a compressed texture is not supported at the moment\n");
5618 } if (destFormat != srcFormat) {
5619 FIXME("Updating mixed format compressed texture is not curretly support\n");
5621 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
5622 glDescription->level,
5623 glDescription->glFormatInternal,
5628 IWineD3DSurface_GetData(pSourceSurface));
5631 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
5636 if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
5638 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
5639 to repack the data from pow2Width/Height to expected Width,Height, this makes the
5640 data returned by GetData non-power2 width/height with hardware non-power2
5641 pow2Width/height are set to surface width height, repacking isn't needed so it
5642 doesn't matter which function gets called. */
5643 glTexSubImage2D(glDescription->target
5644 ,glDescription->level
5649 ,glDescription->glFormat
5650 ,glDescription->glType
5651 ,IWineD3DSurface_GetData(pSourceSurface)
5655 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
5656 glTexSubImage2D(glDescription->target
5657 ,glDescription->level
5660 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
5661 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
5662 ,glDescription->glFormat
5663 ,glDescription->glType
5664 ,IWineD3DSurface_GetData(pSourceSurface)
5670 checkGLcall("glTexSubImage2D");
5672 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
5673 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
5674 * surface bigger than it needs to be hmm.. */
5675 if (WINED3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
5676 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
5677 IWineD3DBaseTexture_Release(baseTexture);
5680 glDisable(textureDimensions); /* This needs to be managed better.... */
5686 /* Used by DirectX 8 */
5687 HRESULT WINAPI IWineD3DDeviceImpl_CopyRects(IWineD3DDevice *iface,
5688 IWineD3DSurface* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
5689 IWineD3DSurface* pDestinationSurface, CONST POINT* pDestPointsArray) {
5691 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5692 HRESULT hr = WINED3D_OK;
5693 WINED3DFORMAT srcFormat, destFormat;
5694 UINT srcWidth, destWidth;
5695 UINT srcHeight, destHeight;
5697 WINED3DSURFACE_DESC winedesc;
5699 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
5700 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
5703 /* Check that the source texture is in WINED3DPOOL_SYSTEMMEM and the destination texture is in WINED3DPOOL_DEFAULT */
5704 memset(&winedesc, 0, sizeof(winedesc));
5706 winedesc.Format = &srcFormat;
5707 winedesc.Width = &srcWidth;
5708 winedesc.Height = &srcHeight;
5709 winedesc.Size = &srcSize;
5710 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5712 winedesc.Format = &destFormat;
5713 winedesc.Width = &destWidth;
5714 winedesc.Height = &destHeight;
5715 winedesc.Size = NULL;
5716 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5718 /* Check that the source and destination formats match */
5719 if (srcFormat != destFormat && WINED3DFMT_UNKNOWN != destFormat) {
5720 WARN("(%p) source %p format must match the dest %p format, returning WINED3DERR_INVALIDCALL\n", This, pSourceSurface, pDestinationSurface);
5721 return WINED3DERR_INVALIDCALL;
5722 } else if (WINED3DFMT_UNKNOWN == destFormat) {
5723 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5724 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5725 destFormat = srcFormat;
5728 /* Quick if complete copy ... */
5729 if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
5731 if (srcWidth == destWidth && srcHeight == destHeight) {
5732 WINED3DLOCKED_RECT lrSrc;
5733 WINED3DLOCKED_RECT lrDst;
5734 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, NULL, WINED3DLOCK_READONLY);
5735 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, NULL, 0L);
5736 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", srcWidth, srcHeight);
5738 memcpy(lrDst.pBits, lrSrc.pBits, srcSize);
5740 IWineD3DSurface_UnlockRect(pSourceSurface);
5741 IWineD3DSurface_UnlockRect(pDestinationSurface);
5742 TRACE("Unlocked src and dst\n");
5746 FIXME("Wanted to copy all surfaces but size not compatible, returning WINED3DERR_INVALIDCALL\n");
5747 hr = WINED3DERR_INVALIDCALL;
5752 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
5754 int bytesPerPixel = ((IWineD3DSurfaceImpl *) pSourceSurface)->bytesPerPixel;
5757 /* Copy rect by rect */
5758 for (i = 0; i < cRects; ++i) {
5759 CONST RECT* r = &pSourceRectsArray[i];
5760 CONST POINT* p = &pDestPointsArray[i];
5763 WINED3DLOCKED_RECT lrSrc;
5764 WINED3DLOCKED_RECT lrDst;
5767 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
5768 if (srcFormat == WINED3DFMT_DXT1) {
5769 copyperline = ((r->right - r->left) * bytesPerPixel) / 2; /* DXT1 is half byte per pixel */
5771 copyperline = ((r->right - r->left) * bytesPerPixel);
5774 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, r, WINED3DLOCK_READONLY);
5775 dest_rect.left = p->x;
5776 dest_rect.top = p->y;
5777 dest_rect.right = p->x + (r->right - r->left);
5778 dest_rect.bottom= p->y + (r->bottom - r->top);
5779 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, &dest_rect, 0L);
5780 TRACE("Locked src and dst\n");
5782 /* Find where to start */
5783 for (j = 0; j < (r->bottom - r->top - 1); ++j) {
5784 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
5786 IWineD3DSurface_UnlockRect(pSourceSurface);
5787 IWineD3DSurface_UnlockRect(pDestinationSurface);
5788 TRACE("Unlocked src and dst\n");
5791 FIXME("Wanted to copy partial surfaces not implemented, returning WINED3DERR_INVALIDCALL\n");
5792 hr = WINED3DERR_INVALIDCALL;
5799 /* Implementation details at http://developer.nvidia.com/attach/6494
5801 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
5802 hmm.. no longer supported use
5803 OpenGL evaluators or tessellate surfaces within your application.
5806 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
5807 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
5808 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5809 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
5810 FIXME("(%p) : Stub\n", This);
5815 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
5816 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
5817 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5818 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
5819 FIXME("(%p) : Stub\n", This);
5823 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5824 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5825 TRACE("(%p) Handle(%d)\n", This, Handle);
5826 FIXME("(%p) : Stub\n", This);
5830 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
5831 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
5832 fill a surface with a block of color! */
5833 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5834 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
5835 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
5836 IWineD3DSwapChainImpl *container = NULL;
5837 BOOL isRenderTarget = FALSE;
5838 unsigned int width, height;
5839 unsigned int top, left;
5842 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
5844 if (surface->resource.pool != WINED3DPOOL_DEFAULT) {
5845 FIXME("call to colorfill with non WINED3DPOOL_DEFAULT surface\n");
5846 return WINED3DERR_INVALIDCALL;
5849 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
5850 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
5851 if (WINED3DUSAGE_RENDERTARGET & surface->resource.usage) {
5852 /* TODO: make sure we set everything back to the way it was, and context management!
5853 glGetIntegerv(GL_READ_BUFFER, &prev_read);
5854 vcheckGLcall("glIntegerv");
5855 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
5856 vcheckGLcall("glIntegerv");
5858 TRACE("Color fill to render targets may cause some graphics issues\n");
5859 if (pSurface == container->frontBuffer) {
5860 glDrawBuffer(GL_FRONT);
5862 glDrawBuffer(GL_BACK);
5865 if (WINED3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
5866 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld\n", surface, surface->resource.usage);
5868 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
5870 if (container != NULL) {
5871 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5873 /* we can use GL_STENCIL_INDEX etc...*/
5876 if (container != NULL) {
5877 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5879 isRenderTarget = TRUE;
5881 /* TODO: drawing to GL_FRONT and GL_BACK */
5882 /* TODO: see if things can be speeded up by using the correct
5883 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
5884 if (pRect == NULL) {
5887 width = surface->currentDesc.Width;
5888 height = surface->currentDesc.Height;
5892 width = pRect->x2 - left;
5893 height = pRect->y2 - top;
5896 data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
5897 /* Create a 'line' of color color, in the correct format for the surface */
5898 for (u = 0 ; u < width ; u ++) {
5903 if (isRenderTarget == FALSE) {
5904 glDescriptor *glDesc;
5905 IWineD3DSurface_PreLoad(pSurface);
5907 /* draw a block of the coloured line on the sufrace */
5908 IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
5909 for (v = 0 ; v< height;v++) {
5910 glTexSubImage2D(glDesc->target
5911 ,glDesc->level /* level */
5921 checkGLcall("glTexSubImage2D");
5923 glDisable(glDesc->target);
5925 /** FIXME: Using GLClear may be faster **/
5926 glRasterPos2i(left, top);
5927 glPixelZoom((float)width ,(float)height);
5928 glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
5929 checkGLcall("glDrawPixels");
5931 HeapFree(GetProcessHeap(), 0, data);
5937 /* rendertarget and deptth stencil functions */
5938 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
5939 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5941 /* FIXME: Implelent RenderTargetIndex >0 */
5942 if(RenderTargetIndex > 0)
5943 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
5945 *ppRenderTarget = This->renderTarget;
5946 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
5947 /* Note inc ref on returned surface */
5948 if(*ppRenderTarget != NULL)
5949 IWineD3DSurface_AddRef(*ppRenderTarget);
5953 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5954 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5955 *ppZStencilSurface = This->depthStencilBuffer;
5956 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
5958 if(*ppZStencilSurface != NULL) {
5959 /* Note inc ref on returned surface */
5960 IWineD3DSurface_AddRef(*ppZStencilSurface);
5965 /* internal static helper functions */
5966 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5967 IWineD3DSurface *RenderSurface);
5969 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5970 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5971 HRESULT hr = WINED3D_OK;
5972 WINED3DVIEWPORT viewport;
5974 TRACE("(%p) Swapping rendertarget\n",This);
5975 if (RenderTargetIndex > 0) {
5976 FIXME("(%p) Render targets other than the first are not supported\n",This);
5977 RenderTargetIndex = 0;
5980 /* MSDN says that null disables the render target
5981 but a device must always be associated with a render target
5982 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5984 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5987 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5988 FIXME("Trying to set render target 0 to NULL\n");
5989 return WINED3DERR_INVALIDCALL;
5991 /* TODO: replace Impl* usage with interface usage */
5992 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
5993 FIXME("(%p)Trying to set the render target to a surface(%p) that wasn't created with a usage of WINED3DUSAGE_RENDERTARGET\n",This ,pRenderTarget);
5994 return WINED3DERR_INVALIDCALL;
5996 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
5997 * builds, but I think wine counts as a 'debug' build for now.
5998 ******************************/
5999 /* If we are trying to set what we already have, don't bother */
6000 if (pRenderTarget == This->renderTarget) {
6001 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6003 /* Otherwise, set the render target up */
6005 if (FALSE == This->sceneEnded) {
6006 IWineD3DDevice_EndScene(iface);
6008 TRACE("clearing renderer\n");
6009 /* IWineD3DDeviceImpl_CleanRender(iface); */
6010 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6011 depending on the renter target implementation being used.
6012 A shared context implementation will share all buffers between all rendertargets (including swapchains),
6013 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6014 stencil buffer and incure an extra memory overhead */
6015 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
6018 if (SUCCEEDED(hr)) {
6019 /* Finally, reset the viewport as the MSDN states. */
6020 /* TODO: Replace impl usage */
6021 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
6022 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
6025 viewport.MaxZ = 1.0f;
6026 viewport.MinZ = 0.0f;
6027 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
6029 FIXME("Unknown error setting the render target\n");
6031 This->sceneEnded = FALSE;
6035 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
6036 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6037 HRESULT hr = WINED3D_OK;
6038 IWineD3DSurface *tmp;
6040 TRACE("(%p) Swapping z-buffer\n",This);
6042 if (pNewZStencil == This->stencilBufferTarget) {
6043 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6045 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6046 * depending on the renter target implementation being used.
6047 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
6048 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6049 * stencil buffer and incure an extra memory overhead
6050 ******************************************************/
6053 tmp = This->stencilBufferTarget;
6054 This->stencilBufferTarget = pNewZStencil;
6055 /* should we be calling the parent or the wined3d surface? */
6056 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
6057 if (NULL != tmp) IWineD3DSurface_Release(tmp);
6059 /** TODO: glEnable/glDisable on depth/stencil depending on
6060 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
6061 **********************************************************/
6068 #ifdef GL_VERSION_1_3
6069 /* Internal functions not in DirectX */
6070 /** TODO: move this off to the opengl context manager
6071 *(the swapchain doesn't need to know anything about offscreen rendering!)
6072 ****************************************************/
6074 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
6076 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6078 TRACE("(%p), %p\n", This, swapchain);
6080 if (swapchain->win != swapchain->drawable) {
6081 /* Set everything back the way it ws */
6082 swapchain->render_ctx = swapchain->glCtx;
6083 swapchain->drawable = swapchain->win;
6088 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
6089 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
6090 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6093 unsigned int height;
6094 WINED3DFORMAT format;
6095 WINED3DSURFACE_DESC surfaceDesc;
6096 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
6097 surfaceDesc.Width = &width;
6098 surfaceDesc.Height = &height;
6099 surfaceDesc.Format = &format;
6100 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
6102 /* I need a get width/height function (and should do something with the format) */
6103 for (i = 0; i < CONTEXT_CACHE; ++i) {
6104 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
6105 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
6106 the pSurface can be set to 0 allowing it to be reused from cache **/
6107 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
6108 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
6109 *context = &This->contextCache[i];
6112 if (This->contextCache[i].Width == 0) {
6113 This->contextCache[i].pSurface = pSurface;
6114 This->contextCache[i].Width = width;
6115 This->contextCache[i].Height = height;
6116 *context = &This->contextCache[i];
6120 if (i == CONTEXT_CACHE) {
6121 int minUsage = 0x7FFFFFFF; /* MAX_INT */
6122 glContext *dropContext = 0;
6123 for (i = 0; i < CONTEXT_CACHE; i++) {
6124 if (This->contextCache[i].usedcount < minUsage) {
6125 dropContext = &This->contextCache[i];
6126 minUsage = This->contextCache[i].usedcount;
6129 /* clean up the context (this doesn't work for ATI at the moment */
6131 glXDestroyContext(swapchain->display, dropContext->context);
6132 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
6135 dropContext->Width = 0;
6136 dropContext->pSurface = pSurface;
6137 *context = dropContext;
6139 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
6140 for (i = 0; i < CONTEXT_CACHE; i++) {
6141 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
6145 if (*context != NULL)
6148 return E_OUTOFMEMORY;
6152 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
6153 * the functionality needs splitting up so that we don't do more than we should do.
6154 * this only seems to impact performance a little.
6155 ******************************/
6156 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
6157 IWineD3DSurface *RenderSurface) {
6158 HRESULT ret = WINED3DERR_INVALIDCALL;
6161 * Currently only active for GLX >= 1.3
6162 * for others versions we'll have to use GLXPixmaps
6164 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
6165 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
6166 * so only check OpenGL version
6167 * ..........................
6168 * I don't believe that it is a problem with NVidia headers,
6169 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
6170 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
6172 * Your application will report GLX version 1.2 on glXQueryVersion.
6173 * However, it is safe to call the GLX 1.3 functions as described below.
6175 #if defined(GL_VERSION_1_3)
6177 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6178 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
6179 IWineD3DSurface *tmp;
6180 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
6181 GLXFBConfig* cfgs = NULL;
6185 IWineD3DSwapChain *currentSwapchain;
6186 IWineD3DSwapChainImpl *swapchain;
6187 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
6188 * but switch them off if the StencilSurface is set to NULL
6189 ** *********************************************************/
6190 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
6191 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
6194 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
6195 it StencilSurface != NULL && zBufferTarget == NULL switch it on
6198 #define PUSH1(att) attribs[nAttribs++] = (att);
6199 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
6201 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
6203 /** TODO: remove the reff to Impl (context manager should fix this!) **/
6204 IWineD3DSwapChainImpl *impSwapChain;
6205 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
6206 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
6207 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
6212 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
6213 PUSH2(GLX_X_RENDERABLE, TRUE);
6214 PUSH2(GLX_DOUBLEBUFFER, TRUE);
6215 TRACE("calling makeglcfg\n");
6216 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
6219 TRACE("calling chooseFGConfig\n");
6220 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
6223 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
6224 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
6225 why we failed and only show this message once! */
6226 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"); /**/
6228 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
6229 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
6230 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
6231 PUSH2(GLX_DOUBLEBUFFER, FALSE);
6232 TRACE("calling makeglcfg\n");
6233 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
6235 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
6242 for (i = 0; i < nCfgs; ++i) {
6243 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
6244 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
6245 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
6248 if (NULL != This->renderTarget) {
6250 vcheckGLcall("glFlush");
6251 /** This is only useful if the old render target was a swapchain,
6252 * we need to supercede this with a function that displays
6253 * the current buffer on the screen. This is easy to do in glx1.3 but
6254 * we need to do copy-write pixels in glx 1.2.
6255 ************************************************/
6256 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
6258 printf("Hit Enter to get next frame ...\n");
6264 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain) != WINED3D_OK) {
6265 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
6266 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
6270 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
6271 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
6272 **********************************************************************/
6273 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == WINED3D_OK) {
6274 /* We also need to make sure that the lights &co are also in the context of the swapchains */
6275 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
6276 TRACE("making swapchain active\n");
6277 if (RenderSurface != This->renderTarget) {
6278 if (RenderSurface == swapchain->backBuffer) {
6280 /* This could be flagged so that some operations work directly with the front buffer */
6281 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
6283 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
6285 TRACE("Error in setting current context: context %p drawable %ld !\n",
6286 impSwapChain->glCtx, impSwapChain->win);
6289 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
6291 checkGLcall("glXMakeContextCurrent");
6293 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
6295 else if (pbuffer_support == TRUE && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
6297 /** ********************************************************************
6298 * This is a quickly hacked out implementation of offscreen textures.
6299 * It will work in most cases but there may be problems if the client
6300 * modifies the texture directly, or expects the contents of the rendertarget
6303 * There are some real speed vs compatibility issues here:
6304 * we should really use a new context for every texture, but that eats ram.
6305 * we should also be restoring the texture to the pbuffer but that eats CPU
6306 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
6307 * but if this means reusing the display backbuffer then we need to make sure that
6308 * states are correctly preserved.
6309 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
6310 * and gain a good performance increase at the cost of compatibility.
6311 * I would suggest that, when this is the case, a user configurable flag be made
6312 * available, allowing the user to choose the best emulated experience for them.
6313 *********************************************************************/
6315 XVisualInfo *visinfo;
6316 glContext *newContext;
6318 /* Here were using a shared context model */
6319 if (WINED3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
6320 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6323 /* If the context doesn't exist then create a new one */
6324 /* TODO: This should really be part of findGlContext */
6325 if (NULL == newContext->context) {
6327 TRACE("making new buffer\n");
6329 PUSH2(GLX_PBUFFER_WIDTH, newContext->Width);
6330 PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
6333 newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
6335 /** ****************************************
6336 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
6338 * In future releases, we may provide the calls glXCreateNewContext,
6339 * glXQueryDrawable and glXMakeContextCurrent.
6340 * so until then we have to use glXGetVisualFromFBConfig &co..
6341 ********************************************/
6344 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
6346 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
6348 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
6352 if (NULL == newContext || NULL == newContext->context) {
6353 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6355 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
6356 if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
6357 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
6360 /* Clean up the old context */
6361 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
6362 /* Set the current context of the swapchain to the new context */
6363 impSwapChain->drawable = newContext->drawable;
6364 impSwapChain->render_ctx = newContext->context;
6368 #if 1 /* Apply the stateblock to the new context
6369 FIXME: This is a bit of a hack, each context should know it's own state,
6370 the directX current directX state should then be applied to the context */
6373 IWineD3DStateBlockImpl *oldUpdateStateBlock;
6374 oldUpdateStateBlock = This->updateStateBlock;
6375 oldRecording= This->isRecordingState;
6376 This->isRecordingState = FALSE;
6377 This->updateStateBlock = This->stateBlock;
6378 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
6380 This->isRecordingState = oldRecording;
6381 This->updateStateBlock = oldUpdateStateBlock;
6386 /* clean up the current rendertargets swapchain (if it belonged to one) */
6387 if (currentSwapchain != NULL) {
6388 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
6391 /* Were done with the opengl context management, setup the rendertargets */
6393 tmp = This->renderTarget;
6394 This->renderTarget = RenderSurface;
6395 IWineD3DSurface_AddRef(This->renderTarget);
6396 IWineD3DSurface_Release(tmp);
6402 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
6403 /* Check that the container is not a swapchain member */
6405 IWineD3DSwapChain *tmpSwapChain;
6406 if (WINED3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
6407 This->renderUpsideDown = TRUE;
6409 This->renderUpsideDown = FALSE;
6410 IWineD3DSwapChain_Release(tmpSwapChain);
6412 /* Force updating the cull mode */
6413 TRACE("setting render state\n");
6414 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
6415 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
6417 /* Force updating projection matrix */
6418 This->last_was_rhw = FALSE;
6419 This->proj_valid = FALSE;
6427 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
6428 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
6433 if ( NULL != impSwapChain) {
6434 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
6442 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
6443 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
6444 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6445 /* TODO: the use of Impl is deprecated. */
6446 /* some basic validation checks */
6447 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
6449 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
6451 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
6452 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
6453 return WINED3DERR_INVALIDCALL;
6455 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
6456 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
6457 return WINED3DERR_INVALIDCALL;
6459 /* TODO: make the cursor 'real' */
6461 This->xHotSpot = XHotSpot;
6462 This->yHotSpot = YHotSpot;
6467 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
6468 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6469 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
6471 This->xScreenSpace = XScreenSpace;
6472 This->yScreenSpace = YScreenSpace;
6478 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
6479 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6480 TRACE("(%p) : visible(%d)\n", This, bShow);
6482 This->bCursorVisible = bShow;
6487 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
6488 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6489 TRACE("(%p) : state (%lu)\n", This, This->state);
6490 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
6491 switch (This->state) {
6494 case WINED3DERR_DEVICELOST:
6496 ResourceList *resourceList = This->resources;
6497 while (NULL != resourceList) {
6498 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
6499 return WINED3DERR_DEVICENOTRESET;
6500 resourceList = resourceList->next;
6502 return WINED3DERR_DEVICELOST;
6504 case WINED3DERR_DRIVERINTERNALERROR:
6505 return WINED3DERR_DRIVERINTERNALERROR;
6509 return WINED3DERR_DRIVERINTERNALERROR;
6513 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
6514 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6515 /** FIXME: Resource tracking needs to be done,
6516 * The closes we can do to this is set the priorities of all managed textures low
6517 * and then reset them.
6518 ***********************************************************/
6519 FIXME("(%p) : stub\n", This);
6523 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
6524 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6525 /** FIXME: Resource trascking needs to be done.
6526 * in effect this pulls all non only default
6527 * textures out of video memory and deletes all glTextures (glDeleteTextures)
6528 * and should clear down the context and set it up according to pPresentationParameters
6529 ***********************************************************/
6530 FIXME("(%p) : stub\n", This);
6534 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
6535 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6536 /** FIXME: always true at the moment **/
6537 if(bEnableDialogs == FALSE) {
6538 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
6544 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
6545 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6546 TRACE("(%p) : pParameters %p\n", This, pParameters);
6548 *pParameters = This->createParms;
6552 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
6553 IWineD3DSwapChain *swapchain;
6554 HRESULT hrc = WINED3D_OK;
6556 TRACE("Relaying to swapchain\n");
6558 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
6559 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
6560 IWineD3DSwapChain_Release(swapchain);
6565 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
6566 IWineD3DSwapChain *swapchain;
6567 HRESULT hrc = WINED3D_OK;
6569 TRACE("Relaying to swapchain\n");
6571 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
6572 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
6573 IWineD3DSwapChain_Release(swapchain);
6579 /** ********************************************************
6580 * Notification functions
6581 ** ********************************************************/
6582 /** This function must be called in the release of a resource when ref == 0,
6583 * the contents of resource must still be correct,
6584 * any handels to other resource held by the caller must be closed
6585 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
6586 *****************************************************/
6587 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6588 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6589 ResourceList* resourceList;
6591 TRACE("(%p) : resource %p\n", This, resource);
6593 EnterCriticalSection(&resourceStoreCriticalSection);
6595 /* add a new texture to the frot of the linked list */
6596 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
6597 resourceList->resource = resource;
6599 /* Get the old head */
6600 resourceList->next = This->resources;
6602 This->resources = resourceList;
6603 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
6606 LeaveCriticalSection(&resourceStoreCriticalSection);
6611 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6612 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6613 ResourceList* resourceList = NULL;
6614 ResourceList* previousResourceList = NULL;
6616 TRACE("(%p) : resource %p\n", This, resource);
6619 EnterCriticalSection(&resourceStoreCriticalSection);
6621 resourceList = This->resources;
6623 while (resourceList != NULL) {
6624 if(resourceList->resource == resource) break;
6625 previousResourceList = resourceList;
6626 resourceList = resourceList->next;
6629 if (resourceList == NULL) {
6630 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
6632 LeaveCriticalSection(&resourceStoreCriticalSection);
6636 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
6638 /* make sure we don't leave a hole in the list */
6639 if (previousResourceList != NULL) {
6640 previousResourceList->next = resourceList->next;
6642 This->resources = resourceList->next;
6646 LeaveCriticalSection(&resourceStoreCriticalSection);
6652 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
6653 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6656 TRACE("(%p) : resource %p\n", This, resource);
6657 switch(IWineD3DResource_GetType(resource)){
6658 case WINED3DRTYPE_SURFACE:
6659 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
6661 case WINED3DRTYPE_TEXTURE:
6662 case WINED3DRTYPE_CUBETEXTURE:
6663 case WINED3DRTYPE_VOLUMETEXTURE:
6664 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
6665 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6666 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6667 This->stateBlock->textures[counter] = NULL;
6669 if (This->updateStateBlock != This->stateBlock ){
6670 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6671 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6672 This->updateStateBlock->textures[counter] = NULL;
6677 case WINED3DRTYPE_VOLUME:
6678 /* TODO: nothing really? */
6680 case WINED3DRTYPE_VERTEXBUFFER:
6681 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
6684 TRACE("Cleaning up stream pointers\n");
6686 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
6687 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
6688 FINDOUT: should changes.streamSource[StreamNumber] be set ?
6690 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6691 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
6692 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
6693 This->updateStateBlock->streamSource[streamNumber] = 0;
6694 /* Set changed flag? */
6697 if (This->stateBlock != NULL ) { /* only happens if there is an error in the application, or on reset/release (because we don't manage internal tracking properly) */
6698 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
6699 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
6700 This->stateBlock->streamSource[streamNumber] = 0;
6703 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
6704 else { /* This shouldn't happen */
6705 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
6712 case WINED3DRTYPE_INDEXBUFFER:
6713 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
6714 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6715 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6716 This->updateStateBlock->pIndexData = NULL;
6719 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
6720 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6721 This->stateBlock->pIndexData = NULL;
6727 FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
6732 /* Remove the resoruce from the resourceStore */
6733 IWineD3DDeviceImpl_RemoveResource(iface, resource);
6735 TRACE("Resource released\n");
6740 /** This function is to be called by the swapchain when it is released and it's ref = 0
6741 *****************************************************/
6742 void WINAPI IWineD3DDeviceImpl_SwapChainReleased(IWineD3DDevice *iface, IWineD3DSwapChain *swapChain){
6743 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6744 SwapChainList **nextSwapchain;
6745 nextSwapchain = &This->swapchains;
6747 /* Check to see if the swapchian is being used as the render target */
6748 if (This->renderTarget != NULL) {
6749 IWineD3DSurface *swapchainBackBuffer;
6751 IWineD3DSwapChain_GetBackBuffer(swapChain, 0 ,( D3DBACKBUFFER_TYPE) 0, &swapchainBackBuffer);
6752 if (This->renderTarget == swapchainBackBuffer) {
6753 /* Don't know what to do, so warn and carry on as usual (which in this case leaves the renderterget in limbo) */
6754 FIXME("Atempting to release a swapchain that is currently beuing used as a render target, behaviour is undefined\n");
6758 /* Go through the swapchain list and try to find the swapchain being released */
6759 while(*nextSwapchain != NULL && (*nextSwapchain)->swapchain != swapChain) {
6760 nextSwapchain = &(*nextSwapchain)->next;
6763 /* Check to see if we found the swapchain */
6764 if (NULL != *nextSwapchain) {
6765 /* We found the swapchain so remove it from the list */
6766 TRACE("(%p) releasing swapchain(%p)\n", iface, swapChain);
6767 HeapFree(GetProcessHeap(), 0 , *nextSwapchain);
6768 *nextSwapchain = (*nextSwapchain)->next;
6770 /* We didn't find the swapchain on the list, this can only heppen because of a programming error in wined3d */
6771 FIXME("(%p) Attempting to release a swapchain (%p) that hasn't been stored\n", iface, swapChain);
6774 TRACE("swapchain (%p) released\n", swapChain);
6778 /**********************************************************
6779 * IWineD3DDevice VTbl follows
6780 **********************************************************/
6782 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
6784 /*** IUnknown methods ***/
6785 IWineD3DDeviceImpl_QueryInterface,
6786 IWineD3DDeviceImpl_AddRef,
6787 IWineD3DDeviceImpl_Release,
6788 /*** IWineD3DDevice methods ***/
6789 IWineD3DDeviceImpl_GetParent,
6790 /*** Creation methods**/
6791 IWineD3DDeviceImpl_CreateVertexBuffer,
6792 IWineD3DDeviceImpl_CreateIndexBuffer,
6793 IWineD3DDeviceImpl_CreateStateBlock,
6794 IWineD3DDeviceImpl_CreateSurface,
6795 IWineD3DDeviceImpl_CreateTexture,
6796 IWineD3DDeviceImpl_CreateVolumeTexture,
6797 IWineD3DDeviceImpl_CreateVolume,
6798 IWineD3DDeviceImpl_CreateCubeTexture,
6799 IWineD3DDeviceImpl_CreateQuery,
6800 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
6801 IWineD3DDeviceImpl_CreateVertexDeclaration,
6802 IWineD3DDeviceImpl_CreateVertexShader,
6803 IWineD3DDeviceImpl_CreatePixelShader,
6804 /*** Odd functions **/
6805 IWineD3DDeviceImpl_Init3D,
6806 IWineD3DDeviceImpl_Uninit3D,
6807 IWineD3DDeviceImpl_EvictManagedResources,
6808 IWineD3DDeviceImpl_GetAvailableTextureMem,
6809 IWineD3DDeviceImpl_GetBackBuffer,
6810 IWineD3DDeviceImpl_GetCreationParameters,
6811 IWineD3DDeviceImpl_GetDeviceCaps,
6812 IWineD3DDeviceImpl_GetDirect3D,
6813 IWineD3DDeviceImpl_GetDisplayMode,
6814 IWineD3DDeviceImpl_GetNumberOfSwapChains,
6815 IWineD3DDeviceImpl_GetRasterStatus,
6816 IWineD3DDeviceImpl_GetSwapChain,
6817 IWineD3DDeviceImpl_Reset,
6818 IWineD3DDeviceImpl_SetDialogBoxMode,
6819 IWineD3DDeviceImpl_SetCursorProperties,
6820 IWineD3DDeviceImpl_SetCursorPosition,
6821 IWineD3DDeviceImpl_ShowCursor,
6822 IWineD3DDeviceImpl_TestCooperativeLevel,
6823 /*** Getters and setters **/
6824 IWineD3DDeviceImpl_SetClipPlane,
6825 IWineD3DDeviceImpl_GetClipPlane,
6826 IWineD3DDeviceImpl_SetClipStatus,
6827 IWineD3DDeviceImpl_GetClipStatus,
6828 IWineD3DDeviceImpl_SetCurrentTexturePalette,
6829 IWineD3DDeviceImpl_GetCurrentTexturePalette,
6830 IWineD3DDeviceImpl_SetDepthStencilSurface,
6831 IWineD3DDeviceImpl_GetDepthStencilSurface,
6832 IWineD3DDeviceImpl_SetFVF,
6833 IWineD3DDeviceImpl_GetFVF,
6834 IWineD3DDeviceImpl_SetGammaRamp,
6835 IWineD3DDeviceImpl_GetGammaRamp,
6836 IWineD3DDeviceImpl_SetIndices,
6837 IWineD3DDeviceImpl_GetIndices,
6838 IWineD3DDeviceImpl_SetLight,
6839 IWineD3DDeviceImpl_GetLight,
6840 IWineD3DDeviceImpl_SetLightEnable,
6841 IWineD3DDeviceImpl_GetLightEnable,
6842 IWineD3DDeviceImpl_SetMaterial,
6843 IWineD3DDeviceImpl_GetMaterial,
6844 IWineD3DDeviceImpl_SetNPatchMode,
6845 IWineD3DDeviceImpl_GetNPatchMode,
6846 IWineD3DDeviceImpl_SetPaletteEntries,
6847 IWineD3DDeviceImpl_GetPaletteEntries,
6848 IWineD3DDeviceImpl_SetPixelShader,
6849 IWineD3DDeviceImpl_GetPixelShader,
6850 IWineD3DDeviceImpl_SetPixelShaderConstant,
6851 IWineD3DDeviceImpl_GetPixelShaderConstant,
6852 IWineD3DDeviceImpl_SetPixelShaderConstantB,
6853 IWineD3DDeviceImpl_GetPixelShaderConstantB,
6854 IWineD3DDeviceImpl_SetPixelShaderConstantI,
6855 IWineD3DDeviceImpl_GetPixelShaderConstantI,
6856 IWineD3DDeviceImpl_SetPixelShaderConstantF,
6857 IWineD3DDeviceImpl_GetPixelShaderConstantF,
6858 IWineD3DDeviceImpl_SetPixelShaderConstantN,
6859 IWineD3DDeviceImpl_SetRenderState,
6860 IWineD3DDeviceImpl_GetRenderState,
6861 IWineD3DDeviceImpl_SetRenderTarget,
6862 IWineD3DDeviceImpl_GetRenderTarget,
6863 IWineD3DDeviceImpl_SetSamplerState,
6864 IWineD3DDeviceImpl_GetSamplerState,
6865 IWineD3DDeviceImpl_SetScissorRect,
6866 IWineD3DDeviceImpl_GetScissorRect,
6867 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
6868 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
6869 IWineD3DDeviceImpl_SetStreamSource,
6870 IWineD3DDeviceImpl_GetStreamSource,
6871 IWineD3DDeviceImpl_SetStreamSourceFreq,
6872 IWineD3DDeviceImpl_GetStreamSourceFreq,
6873 IWineD3DDeviceImpl_SetTexture,
6874 IWineD3DDeviceImpl_GetTexture,
6875 IWineD3DDeviceImpl_SetTextureStageState,
6876 IWineD3DDeviceImpl_GetTextureStageState,
6877 IWineD3DDeviceImpl_SetTransform,
6878 IWineD3DDeviceImpl_GetTransform,
6879 IWineD3DDeviceImpl_SetVertexDeclaration,
6880 IWineD3DDeviceImpl_GetVertexDeclaration,
6881 IWineD3DDeviceImpl_SetVertexShader,
6882 IWineD3DDeviceImpl_GetVertexShader,
6883 IWineD3DDeviceImpl_SetVertexShaderConstant,
6884 IWineD3DDeviceImpl_GetVertexShaderConstant,
6885 IWineD3DDeviceImpl_SetVertexShaderConstantB,
6886 IWineD3DDeviceImpl_GetVertexShaderConstantB,
6887 IWineD3DDeviceImpl_SetVertexShaderConstantI,
6888 IWineD3DDeviceImpl_GetVertexShaderConstantI,
6889 IWineD3DDeviceImpl_SetVertexShaderConstantF,
6890 IWineD3DDeviceImpl_GetVertexShaderConstantF,
6891 IWineD3DDeviceImpl_SetVertexShaderConstantN,
6892 IWineD3DDeviceImpl_SetViewport,
6893 IWineD3DDeviceImpl_GetViewport,
6894 IWineD3DDeviceImpl_MultiplyTransform,
6895 IWineD3DDeviceImpl_ValidateDevice,
6896 IWineD3DDeviceImpl_ProcessVertices,
6897 /*** State block ***/
6898 IWineD3DDeviceImpl_BeginStateBlock,
6899 IWineD3DDeviceImpl_EndStateBlock,
6900 /*** Scene management ***/
6901 IWineD3DDeviceImpl_BeginScene,
6902 IWineD3DDeviceImpl_EndScene,
6903 IWineD3DDeviceImpl_Present,
6904 IWineD3DDeviceImpl_Clear,
6906 IWineD3DDeviceImpl_DrawPrimitive,
6907 IWineD3DDeviceImpl_DrawIndexedPrimitive,
6908 IWineD3DDeviceImpl_DrawPrimitiveUP,
6909 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
6910 IWineD3DDeviceImpl_DrawRectPatch,
6911 IWineD3DDeviceImpl_DrawTriPatch,
6912 IWineD3DDeviceImpl_DeletePatch,
6913 IWineD3DDeviceImpl_ColorFill,
6914 IWineD3DDeviceImpl_UpdateTexture,
6915 IWineD3DDeviceImpl_UpdateSurface,
6916 IWineD3DDeviceImpl_CopyRects,
6917 IWineD3DDeviceImpl_StretchRect,
6918 IWineD3DDeviceImpl_GetRenderTargetData,
6919 IWineD3DDeviceImpl_GetFrontBufferData,
6920 /*** Internal use IWineD3DDevice methods ***/
6921 IWineD3DDeviceImpl_SetupTextureStates,
6922 /*** object tracking ***/
6923 IWineD3DDeviceImpl_SwapChainReleased,
6924 IWineD3DDeviceImpl_ResourceReleased
6928 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
6929 WINED3DRS_ALPHABLENDENABLE ,
6930 WINED3DRS_ALPHAFUNC ,
6931 WINED3DRS_ALPHAREF ,
6932 WINED3DRS_ALPHATESTENABLE ,
6934 WINED3DRS_COLORWRITEENABLE ,
6935 WINED3DRS_DESTBLEND ,
6936 WINED3DRS_DITHERENABLE ,
6937 WINED3DRS_FILLMODE ,
6938 WINED3DRS_FOGDENSITY ,
6940 WINED3DRS_FOGSTART ,
6941 WINED3DRS_LASTPIXEL ,
6942 WINED3DRS_SHADEMODE ,
6943 WINED3DRS_SRCBLEND ,
6944 WINED3DRS_STENCILENABLE ,
6945 WINED3DRS_STENCILFAIL ,
6946 WINED3DRS_STENCILFUNC ,
6947 WINED3DRS_STENCILMASK ,
6948 WINED3DRS_STENCILPASS ,
6949 WINED3DRS_STENCILREF ,
6950 WINED3DRS_STENCILWRITEMASK ,
6951 WINED3DRS_STENCILZFAIL ,
6952 WINED3DRS_TEXTUREFACTOR ,
6963 WINED3DRS_ZWRITEENABLE
6966 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
6967 WINED3DTSS_ADDRESSW ,
6968 WINED3DTSS_ALPHAARG0 ,
6969 WINED3DTSS_ALPHAARG1 ,
6970 WINED3DTSS_ALPHAARG2 ,
6971 WINED3DTSS_ALPHAOP ,
6972 WINED3DTSS_BUMPENVLOFFSET ,
6973 WINED3DTSS_BUMPENVLSCALE ,
6974 WINED3DTSS_BUMPENVMAT00 ,
6975 WINED3DTSS_BUMPENVMAT01 ,
6976 WINED3DTSS_BUMPENVMAT10 ,
6977 WINED3DTSS_BUMPENVMAT11 ,
6978 WINED3DTSS_COLORARG0 ,
6979 WINED3DTSS_COLORARG1 ,
6980 WINED3DTSS_COLORARG2 ,
6981 WINED3DTSS_COLOROP ,
6982 WINED3DTSS_RESULTARG ,
6983 WINED3DTSS_TEXCOORDINDEX ,
6984 WINED3DTSS_TEXTURETRANSFORMFLAGS
6987 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
6988 WINED3DSAMP_ADDRESSU ,
6989 WINED3DSAMP_ADDRESSV ,
6990 WINED3DSAMP_ADDRESSW ,
6991 WINED3DSAMP_BORDERCOLOR ,
6992 WINED3DSAMP_MAGFILTER ,
6993 WINED3DSAMP_MINFILTER ,
6994 WINED3DSAMP_MIPFILTER ,
6995 WINED3DSAMP_MIPMAPLODBIAS ,
6996 WINED3DSAMP_MAXMIPLEVEL ,
6997 WINED3DSAMP_MAXANISOTROPY ,
6998 WINED3DSAMP_SRGBTEXTURE ,
6999 WINED3DSAMP_ELEMENTINDEX
7002 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
7004 WINED3DRS_AMBIENTMATERIALSOURCE ,
7005 WINED3DRS_CLIPPING ,
7006 WINED3DRS_CLIPPLANEENABLE ,
7007 WINED3DRS_COLORVERTEX ,
7008 WINED3DRS_DIFFUSEMATERIALSOURCE ,
7009 WINED3DRS_EMISSIVEMATERIALSOURCE ,
7010 WINED3DRS_FOGDENSITY ,
7012 WINED3DRS_FOGSTART ,
7013 WINED3DRS_FOGTABLEMODE ,
7014 WINED3DRS_FOGVERTEXMODE ,
7015 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
7016 WINED3DRS_LIGHTING ,
7017 WINED3DRS_LOCALVIEWER ,
7018 WINED3DRS_MULTISAMPLEANTIALIAS ,
7019 WINED3DRS_MULTISAMPLEMASK ,
7020 WINED3DRS_NORMALIZENORMALS ,
7021 WINED3DRS_PATCHEDGESTYLE ,
7022 WINED3DRS_POINTSCALE_A ,
7023 WINED3DRS_POINTSCALE_B ,
7024 WINED3DRS_POINTSCALE_C ,
7025 WINED3DRS_POINTSCALEENABLE ,
7026 WINED3DRS_POINTSIZE ,
7027 WINED3DRS_POINTSIZE_MAX ,
7028 WINED3DRS_POINTSIZE_MIN ,
7029 WINED3DRS_POINTSPRITEENABLE ,
7030 WINED3DRS_RANGEFOGENABLE ,
7031 WINED3DRS_SPECULARMATERIALSOURCE ,
7032 WINED3DRS_TWEENFACTOR ,
7033 WINED3DRS_VERTEXBLEND
7036 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
7037 WINED3DTSS_TEXCOORDINDEX ,
7038 WINED3DTSS_TEXTURETRANSFORMFLAGS
7041 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
7042 WINED3DSAMP_DMAPOFFSET