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