wined3d: Add a resource dumper.
[wine/multimedia.git] / dlls / wined3d / device.c
blob71147f880b287b09bf81b7ca85db6f64d0349716
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 #ifdef HAVE_FLOAT_H
26 # include <float.h>
27 #endif
28 #include "wined3d_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
31 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
33 /* x11drv GDI escapes */
34 #define X11DRV_ESCAPE 6789
35 enum x11drv_escape_codes
37 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
38 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
39 X11DRV_GET_FONT, /* get current X font for a DC */
42 /* retrieve the X display to use on a given DC */
43 inline static Display *get_display( HDC hdc )
45 Display *display;
46 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
48 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
49 sizeof(display), (LPSTR)&display )) display = NULL;
50 return display;
53 /* Memory tracking and object counting */
54 static unsigned int emulated_textureram = 64*1024*1024;
56 /* TODO: setup some flags in the regestry to enable, disable pbuffer support */
57 /* enable pbuffer support for offscreen textures */
58 BOOL pbuffer_support = FALSE;
59 /* allocate one pbuffer per surface */
60 BOOL pbuffer_per_surface = FALSE;
62 /* static function declarations */
63 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
65 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type);
67 /* helper macros */
68 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return WINED3DERR_OUTOFVIDEOMEMORY;}
70 #define D3DCREATEOBJECTINSTANCE(object, type) { \
71 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
72 D3DMEMCHECK(object, pp##type); \
73 object->lpVtbl = &IWineD3D##type##_Vtbl; \
74 object->wineD3DDevice = This; \
75 object->parent = parent; \
76 object->ref = 1; \
77 *pp##type = (IWineD3D##type *) object; \
80 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
81 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
82 D3DMEMCHECK(object, pp##type); \
83 object->lpVtbl = &IWineD3D##type##_Vtbl; \
84 object->resource.wineD3DDevice = This; \
85 object->resource.parent = parent; \
86 object->resource.resourceType = d3dtype; \
87 object->resource.ref = 1; \
88 object->resource.pool = Pool; \
89 object->resource.format = Format; \
90 object->resource.usage = Usage; \
91 object->resource.size = _size; \
92 /* Check that we have enough video ram left */ \
93 if (Pool == WINED3DPOOL_DEFAULT) { \
94 if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
95 WARN("Out of 'bogus' video memory\n"); \
96 HeapFree(GetProcessHeap(), 0, object); \
97 *pp##type = NULL; \
98 return WINED3DERR_OUTOFVIDEOMEMORY; \
99 } \
100 globalChangeGlRam(_size); \
102 object->resource.allocatedMemory = (0 == _size ? NULL : Pool == WINED3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
103 if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != WINED3DPOOL_DEFAULT) { \
104 FIXME("Out of memory!\n"); \
105 HeapFree(GetProcessHeap(), 0, object); \
106 *pp##type = NULL; \
107 return WINED3DERR_OUTOFVIDEOMEMORY; \
109 *pp##type = (IWineD3D##type *) object; \
110 IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
111 TRACE("(%p) : Created resource %p\n", This, object); \
114 #define D3DINITIALIZEBASETEXTURE(_basetexture) { \
115 _basetexture.levels = Levels; \
116 _basetexture.filterType = (Usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE; \
117 _basetexture.LOD = 0; \
118 _basetexture.dirty = TRUE; \
121 /**********************************************************
122 * Global variable / Constants follow
123 **********************************************************/
124 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
126 /**********************************************************
127 * Utility functions follow
128 **********************************************************/
129 /* Convert the D3DLIGHT properties into equivalent gl lights */
130 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
132 float quad_att;
133 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
134 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
136 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
137 glMatrixMode(GL_MODELVIEW);
138 glPushMatrix();
139 glLoadMatrixf((float *)&This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
141 /* Diffuse: */
142 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
143 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
144 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
145 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
146 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
147 checkGLcall("glLightfv");
149 /* Specular */
150 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
151 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
152 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
153 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
154 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
155 checkGLcall("glLightfv");
157 /* Ambient */
158 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
159 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
160 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
161 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
162 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
163 checkGLcall("glLightfv");
165 /* Attenuation - Are these right? guessing... */
166 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
167 checkGLcall("glLightf");
168 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
169 checkGLcall("glLightf");
171 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
172 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
173 } else {
174 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
177 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
178 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
179 checkGLcall("glLightf");
181 switch (lightInfo->OriginalParms.Type) {
182 case D3DLIGHT_POINT:
183 /* Position */
184 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
185 checkGLcall("glLightfv");
186 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
187 checkGLcall("glLightf");
188 /* FIXME: Range */
189 break;
191 case D3DLIGHT_SPOT:
192 /* Position */
193 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
194 checkGLcall("glLightfv");
195 /* Direction */
196 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
197 checkGLcall("glLightfv");
198 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
199 checkGLcall("glLightf");
200 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
201 checkGLcall("glLightf");
202 /* FIXME: Range */
203 break;
205 case D3DLIGHT_DIRECTIONAL:
206 /* Direction */
207 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
208 checkGLcall("glLightfv");
209 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
210 checkGLcall("glLightf");
211 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
212 checkGLcall("glLightf");
213 break;
215 default:
216 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
219 /* Restore the modelview matrix */
220 glPopMatrix();
223 /* Apply the current values to the specified texture stage */
224 void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Sampler, DWORD Flags) {
225 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
226 float col[4];
228 union {
229 float f;
230 DWORD d;
231 } tmpvalue;
233 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
234 clamping, MIPLOD, etc. This will work for up to 16 samplers.
237 if (Sampler >= GL_LIMITS(samplers)) {
238 FIXME("Trying to set the state of more samplers %ld than are supported %d by this openGL implementation\n", Sampler, GL_LIMITS(samplers));
239 return;
241 VTRACE(("Activating appropriate texture state %ld\n", Sampler));
242 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
243 ENTER_GL();
244 GLACTIVETEXTURE(Sampler);
245 LEAVE_GL();
246 /* Could we use bindTexture and then apply the states instead of GLACTIVETEXTURE */
247 } else if (Sampler > 0) {
248 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
249 return;
252 /* TODO: change this to a lookup table
253 LOOKUP_TEXTURE_STATES lists all texture states that should be applied.
254 LOOKUP_CONTEXT_SATES list all context applicable states that can be applied
255 etc.... it's a lot cleaner, quicker and possibly easier to maintain than running a switch and setting a skip flag...
256 especially when there are a number of groups of states. */
258 TRACE("-----------------------> Updating the texture at Sampler %ld to have new texture state information\n", Sampler);
260 /* The list of states not to apply is a big as the list of states to apply, so it makes sense to produce an inclusive list */
261 #define APPLY_STATE(_state) IWineD3DDeviceImpl_ApplyTextureUnitState(iface, Sampler, _state)
262 /* these are the only two supported states that need to be applied */
263 APPLY_STATE(WINED3DTSS_TEXCOORDINDEX);
264 APPLY_STATE(WINED3DTSS_TEXTURETRANSFORMFLAGS);
265 #if 0 /* not supported at the moment */
266 APPLY_STATE(WINED3DTSS_BUMPENVMAT00);
267 APPLY_STATE(WINED3DTSS_BUMPENVMAT01);
268 APPLY_STATE(WINED3DTSS_BUMPENVMAT10);
269 APPLY_STATE(WINED3DTSS_BUMPENVMAT11);
270 APPLY_STATE(WINED3DTSS_BUMPENVLSCALE);
271 APPLY_STATE(WINED3DTSS_BUMPENVLOFFSET);
272 APPLY_STATE(WINED3DTSS_RESULTARG);
273 APPLY_STATE(WINED3DTSS_CONSTANT);
274 #endif
275 /* a quick sanity check in case someone forgot to update this function */
276 if (WINED3D_HIGHEST_TEXTURE_STATE > WINED3DTSS_CONSTANT) {
277 FIXME("(%p) : There are more texture states than expected, update device.c to match\n", This);
279 #undef APPLY_STATE
281 /* apply any sampler states that always need applying */
282 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
283 tmpvalue.d = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPMAPLODBIAS];
284 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
285 GL_TEXTURE_LOD_BIAS_EXT,
286 tmpvalue.f);
287 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
290 /* Note the D3DRS value applies to all textures, but GL has one
291 * per texture, so apply it now ready to be used!
293 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
294 /* Set the default alpha blend color */
295 glBlendColor(col[0], col[1], col[2], col[3]);
296 checkGLcall("glBlendColor");
298 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
299 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
300 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
302 /* TODO: NV_POINT_SPRITE */
303 if (GL_SUPPORT(ARB_POINT_SPRITE)) {
304 if (This->stateBlock->renderState[WINED3DRS_POINTSPRITEENABLE] != FALSE) {
305 /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
306 glDisable(GL_POINT_SMOOTH);
308 /* Centre the texture on the vertex */
309 VTRACE("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
310 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
312 VTRACE("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
313 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
314 checkGLcall("glTexEnvf(...)");
315 VTRACE("glEnable( GL_POINT_SPRITE_ARB )\n");
316 glEnable( GL_POINT_SPRITE_ARB );
317 checkGLcall("glEnable(...)");
318 } else {
319 VTRACE("glDisable( GL_POINT_SPRITE_ARB )\n");
320 glDisable( GL_POINT_SPRITE_ARB );
321 checkGLcall("glEnable(...)");
325 TRACE("-----------------------> Updated the texture at Sampler %ld to have new texture state information\n", Sampler);
328 /**********************************************************
329 * IUnknown parts follows
330 **********************************************************/
332 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
334 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
336 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
337 if (IsEqualGUID(riid, &IID_IUnknown)
338 || IsEqualGUID(riid, &IID_IWineD3DBase)
339 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
340 IUnknown_AddRef(iface);
341 *ppobj = This;
342 return WINED3D_OK;
345 return E_NOINTERFACE;
348 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
349 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
350 ULONG refCount = InterlockedIncrement(&This->ref);
352 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
353 return refCount;
356 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
357 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
358 ULONG refCount = InterlockedDecrement(&This->ref);
360 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
362 if (!refCount) {
363 /* TODO: Clean up all the surfaces and textures! */
364 /* FIXME: Create targets and state blocks in d3d8 */
365 if (((IWineD3DImpl *)This->wineD3D)->dxVersion >= 8) { /*We don't create state blocks for d3d7 yet*/
366 /* NOTE: You must release the parent if the object was created via a callback
367 ** ***************************/
368 /* TODO: this is exactly the same as required by _Reset.., so at some point we need to move the code so that is can be called by reset add release... */
369 /* Release all of the swapchains, except the implicit swapchain */
370 IUnknown* stencilBufferParent;
371 IUnknown* swapChainParent;
373 /* NOTE: Don't release swapchain 0 here, it's 'special' */
374 SwapChainList *nextSwapchain = This->swapchains;
375 if (nextSwapchain != NULL) {
376 nextSwapchain = nextSwapchain->next;
377 } else {
378 WARN("Expected to find the implicit swapchain\n");
381 /* release all the other swapchains */
382 while (nextSwapchain != NULL) {
383 SwapChainList *prevSwapchain = nextSwapchain;
384 nextSwapchain = nextSwapchain->next;
385 IWineD3DSwapChain_Release(prevSwapchain->swapchain);
386 /* NOTE: no need to free the list element, it will be done by the release callback
387 HeapFree(GetProcessHeap(), 0, prevSwapchain); */
389 /* Release the buffers (with sanity checks)*/
390 if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
391 if(This->depthStencilBuffer != This->stencilBufferTarget)
392 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
394 This->stencilBufferTarget = NULL;
396 if(IWineD3DSurface_Release(This->renderTarget) >0){
397 /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
399 This->renderTarget = NULL;
401 IWineD3DSurface_GetParent(This->depthStencilBuffer, &stencilBufferParent);
402 IUnknown_Release(stencilBufferParent); /* once for the get parent */
403 if(IUnknown_Release(stencilBufferParent) >0){ /* the second time for when it was created */
404 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
406 This->depthStencilBuffer = NULL;
408 /* Release the update stateblock */
409 if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){
410 if(This->updateStateBlock != This->stateBlock)
411 FIXME("(%p) Something's still holding the Update stateblock\n",This);
413 This->updateStateBlock = NULL;
414 { /* because were not doing proper internal refcounts releasing the primary state block
415 causes recursion with the extra checks in ResourceReleased, to avoid this we have
416 to set this->stateBlock = NULL; first */
417 IWineD3DStateBlock *stateBlock = (IWineD3DStateBlock *)This->stateBlock;
418 This->stateBlock = NULL;
420 /* Release the stateblock */
421 if(IWineD3DStateBlock_Release(stateBlock) > 0){
422 FIXME("(%p) Something's still holding the Update stateblock\n",This);
426 if (This->swapchains != NULL) {
427 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
428 IWineD3DSwapChain_GetParent(This->swapchains->swapchain, &swapChainParent);
429 IUnknown_Release(swapChainParent); /* once for the get parent */
430 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
431 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
435 if (This->resources != NULL ) {
436 FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This);
437 dumpResources(This->resources);
441 IWineD3D_Release(This->wineD3D);
442 This->wineD3D = NULL;
443 HeapFree(GetProcessHeap(), 0, This);
444 TRACE("Freed device %p\n", This);
445 This = NULL;
447 return refCount;
450 /**********************************************************
451 * IWineD3DDevice implementation follows
452 **********************************************************/
453 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
454 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
455 *pParent = This->parent;
456 IUnknown_AddRef(This->parent);
457 return WINED3D_OK;
460 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
461 DWORD FVF, WINED3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
462 IUnknown *parent) {
463 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
464 IWineD3DVertexBufferImpl *object;
465 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
466 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, WINED3DRTYPE_VERTEXBUFFER, Size)
468 /*TODO: use VBO's */
469 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
470 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
472 object->fvf = FVF;
474 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
475 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
477 return WINED3D_OK;
480 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
481 WINED3DFORMAT Format, WINED3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
482 HANDLE *sharedHandle, IUnknown *parent) {
483 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
484 IWineD3DIndexBufferImpl *object;
485 TRACE("(%p) Creating index buffer\n", This);
487 /* Allocate the storage for the device */
488 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,WINED3DRTYPE_INDEXBUFFER, Length)
490 /*TODO: use VBO's */
491 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
492 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
495 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
496 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
497 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
499 return WINED3D_OK;
502 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
504 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
505 IWineD3DStateBlockImpl *object;
506 int i, j;
508 D3DCREATEOBJECTINSTANCE(object, StateBlock)
509 object->blockType = Type;
511 /* Special case - Used during initialization to produce a placeholder stateblock
512 so other functions called can update a state block */
513 if (Type == WINED3DSBT_INIT) {
514 /* Don't bother increasing the reference count otherwise a device will never
515 be freed due to circular dependencies */
516 return WINED3D_OK;
519 /* Otherwise, might as well set the whole state block to the appropriate values */
520 if ( This->stateBlock != NULL) {
521 memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
522 } else {
523 memset(object->streamFreq, 1, sizeof(object->streamFreq));
526 /* Reset the ref and type after kludging it */
527 object->wineD3DDevice = This;
528 object->ref = 1;
529 object->blockType = Type;
531 TRACE("Updating changed flags appropriate for type %d\n", Type);
533 if (Type == WINED3DSBT_ALL) {
535 TRACE("ALL => Pretend everything has changed\n");
536 memset(&object->changed, TRUE, sizeof(This->stateBlock->changed));
537 } else if (Type == WINED3DSBT_PIXELSTATE) {
539 TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
540 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
542 object->changed.pixelShader = TRUE;
544 /* Pixel Shader Constants */
545 for (i = 0; i < MAX_PSHADER_CONSTANTS; ++i) {
546 object->changed.pixelShaderConstants[i] = TRUE;
548 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
549 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
551 for (j = 0; j < GL_LIMITS(textures); j++) {
552 for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
553 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
556 for (j = 0 ; j < 16; j++) {
557 for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
559 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
563 } else if (Type == WINED3DSBT_VERTEXSTATE) {
565 TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
566 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
568 object->changed.vertexShader = TRUE;
570 /* Vertex Shader Constants */
571 for (i = 0; i < MAX_VSHADER_CONSTANTS; ++i) {
572 object->changed.vertexShaderConstants[i] = TRUE;
574 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
575 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
577 for (j = 0; j < GL_LIMITS(textures); j++) {
578 for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
579 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
582 for (j = 0 ; j < 16; j++){
583 for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
584 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
588 /* Duplicate light chain */
590 PLIGHTINFOEL *src = NULL;
591 PLIGHTINFOEL *dst = NULL;
592 PLIGHTINFOEL *newEl = NULL;
593 src = This->stateBlock->lights;
594 object->lights = NULL;
597 while (src) {
598 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
599 if (newEl == NULL) return WINED3DERR_OUTOFVIDEOMEMORY;
600 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
601 newEl->prev = dst;
602 newEl->changed = TRUE;
603 newEl->enabledChanged = TRUE;
604 if (dst == NULL) {
605 object->lights = newEl;
606 } else {
607 dst->next = newEl;
609 dst = newEl;
610 src = src->next;
615 } else {
616 FIXME("Unrecognized state block type %d\n", Type);
619 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
620 return WINED3D_OK;
624 /* ************************************
625 MSDN:
626 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
628 Discard
629 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
631 If this flag is set, the contents of the depth stencil buffer will be invalid after calling either IDirect3DDevice9::Present or IDirect3DDevice9::SetDepthStencilSurface with a different depth surface.
633 ******************************** */
635 HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height, WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **ppSurface,WINED3DRESOURCETYPE Type, DWORD Usage, WINED3DPOOL Pool, WINED3DMULTISAMPLE_TYPE MultiSample ,DWORD MultisampleQuality, HANDLE* pSharedHandle, IUnknown *parent) {
636 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
637 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
638 unsigned int pow2Width, pow2Height;
639 unsigned int Size = 1;
640 TRACE("(%p) Create surface\n",This);
642 /** FIXME: Check ranges on the inputs are valid
643 * MSDN
644 * MultisampleQuality
645 * [in] Quality level. The valid range is between zero and one less than the level
646 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
647 * Passing a larger value returns the error WINED3DERR_INVALIDCALL. The MultisampleQuality
648 * values of paired render targets, depth stencil surfaces, and the MultiSample type
649 * must all match.
650 *******************************/
654 * TODO: Discard MSDN
655 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
657 * If this flag is set, the contents of the depth stencil buffer will be
658 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
659 * with a different depth surface.
661 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
662 ***************************/
664 if(MultisampleQuality < 0) {
665 FIXME("Invalid multisample level %ld\n", MultisampleQuality);
666 return WINED3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
669 if(MultisampleQuality > 0) {
670 FIXME("MultisampleQuality set to %ld, substituting 0\n", MultisampleQuality);
671 MultisampleQuality=0;
674 /** FIXME: Check that the format is supported
675 * by the device.
676 *******************************/
678 /* Non-power2 support */
680 /* Find the nearest pow2 match */
681 pow2Width = pow2Height = 1;
682 while (pow2Width < Width) pow2Width <<= 1;
683 while (pow2Height < Height) pow2Height <<= 1;
685 if (pow2Width > Width || pow2Height > Height) {
686 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
687 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
688 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
689 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
690 This, Width, Height);
691 return WINED3DERR_NOTAVAILABLE;
695 /** Check against the maximum texture sizes supported by the video card **/
696 if (pow2Width > GL_LIMITS(texture_size) || pow2Height > GL_LIMITS(texture_size)) {
697 /* one of three options
698 1: Do the same as we do with nonpow 2 and scale the texture, (any texture ops would require the texture to be scaled which is potentially slow)
699 2: Set the texture to the maxium size (bad idea)
700 3: WARN and return WINED3DERR_NOTAVAILABLE;
702 WARN("(%p) Application requested a surface w %d, h %d, but the graphics card only supports %d\n", This, Width, Height, GL_LIMITS(texture_size));
703 return WINED3DERR_NOTAVAILABLE;
708 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
709 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
710 * space!
711 *********************************/
712 if (WINED3DFMT_UNKNOWN == Format) {
713 Size = 0;
714 } else if (Format == WINED3DFMT_DXT1) {
715 /* DXT1 is half byte per pixel */
716 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4)) >> 1;
718 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
719 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
720 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4));
721 } else {
722 Size = (pow2Width * D3DFmtGetBpp(This, Format)) * pow2Height;
725 /** Create and initialise the surface resource **/
726 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,WINED3DRTYPE_SURFACE, Size)
727 /* "Standalone" surface */
728 IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL);
730 object->currentDesc.Width = Width;
731 object->currentDesc.Height = Height;
732 object->currentDesc.MultiSampleType = MultiSample;
733 object->currentDesc.MultiSampleQuality = MultisampleQuality;
735 /* Setup some glformat defaults */
736 if (WINED3DFMT_UNKNOWN != Format) {
737 object->glDescription.glFormat = D3DFmt2GLFmt(This, object->resource.format);
738 object->glDescription.glFormatInternal = D3DFmt2GLIntFmt(This, object->resource.format);
739 object->glDescription.glType = D3DFmt2GLType(This, object->resource.format);
740 } else {
741 object->glDescription.glFormat = 0;
742 object->glDescription.glFormatInternal = 0;
743 object->glDescription.glType = 0;
746 object->glDescription.textureName = 0;
747 object->glDescription.level = Level;
748 object->glDescription.target = GL_TEXTURE_2D;
750 /* Internal data */
751 object->pow2Width = pow2Width;
752 object->pow2Height = pow2Height;
753 object->nonpow2 = (pow2Width != Width || pow2Height != Height) ? TRUE : FALSE;
754 object->discard = Discard;
755 object->activeLock = FALSE;
757 if (WINED3DFMT_UNKNOWN != Format) {
758 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
759 object->pow2Size = (pow2Width * object->bytesPerPixel) * pow2Height;
760 } else {
761 object->bytesPerPixel = 0;
762 object->pow2Size = 0;
765 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
767 TRACE("Pool %d %d %d %d",Pool, WINED3DPOOL_DEFAULT, WINED3DPOOL_MANAGED, WINED3DPOOL_SYSTEMMEM);
769 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
770 * this function is too deap to need to care about things like this.
771 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
772 * ****************************************/
773 switch(Pool) {
774 case WINED3DPOOL_SCRATCH:
775 if(Lockable == FALSE)
776 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
777 which are mutually exclusive, setting lockable to true\n");
778 Lockable = TRUE;
779 break;
780 case WINED3DPOOL_SYSTEMMEM:
781 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
782 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
783 case WINED3DPOOL_MANAGED:
784 if(Usage == WINED3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
785 Usage of DYNAMIC which are mutually exclusive, not doing \
786 anything just telling you.\n");
787 break;
788 case WINED3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
789 if(!(Usage & WINED3DUSAGE_DYNAMIC) && !(Usage & WINED3DUSAGE_RENDERTARGET)
790 && !(Usage && WINED3DUSAGE_DEPTHSTENCIL ) && Lockable == TRUE)
791 FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
792 break;
793 default:
794 FIXME("(%p) Unknown pool %d\n", This, Pool);
795 break;
798 if (Usage & WINED3DUSAGE_RENDERTARGET && Pool != WINED3DPOOL_DEFAULT) {
799 FIXME("Trying to create a render target that isn't in the default pool\n");
803 object->locked = FALSE;
804 object->lockable = (WINED3DFMT_D16_LOCKABLE == Format) ? TRUE : Lockable;
806 /* mark the texture as dirty so that it get's loaded first time around*/
807 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
808 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
809 This, Width, Height, Format, debug_d3dformat(Format),
810 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
811 return WINED3D_OK;
815 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
816 DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
817 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
818 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
820 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
821 IWineD3DTextureImpl *object;
822 unsigned int i;
823 UINT tmpW;
824 UINT tmpH;
825 HRESULT hr;
826 unsigned int pow2Width = Width;
827 unsigned int pow2Height = Height;
830 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) ....\n", This, Width, Height, Levels, Usage);
832 /* TODO: It should only be possible to create textures for formats
833 that are reported as supported */
834 if (WINED3DFMT_UNKNOWN >= Format) {
835 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
836 return WINED3DERR_INVALIDCALL;
839 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, WINED3DRTYPE_TEXTURE, 0);
840 D3DINITIALIZEBASETEXTURE(object->baseTexture);
841 object->width = Width;
842 object->height = Height;
844 /** Non-power2 support **/
845 /* Find the nearest pow2 match */
846 pow2Width = pow2Height = 1;
847 while (pow2Width < Width) pow2Width <<= 1;
848 while (pow2Height < Height) pow2Height <<= 1;
850 /** FIXME: add support for real non-power-two if it's provided by the video card **/
851 /* Precalculated scaling for 'faked' non power of two texture coords */
852 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
853 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
854 TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
856 /* Calculate levels for mip mapping */
857 if (Levels == 0) {
858 TRACE("calculating levels %d\n", object->baseTexture.levels);
859 object->baseTexture.levels++;
860 tmpW = Width;
861 tmpH = Height;
862 while (tmpW > 1 && tmpH > 1) {
863 tmpW = max(1, tmpW >> 1);
864 tmpH = max(1, tmpH >> 1);
865 object->baseTexture.levels++;
867 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
870 /* Generate all the surfaces */
871 tmpW = Width;
872 tmpH = Height;
873 for (i = 0; i < object->baseTexture.levels; i++)
875 /* use the callback to create the texture surface */
876 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
877 if (hr!= WINED3D_OK) {
878 int j;
879 FIXME("Failed to create surface %p\n", object);
880 /* clean up */
881 for (j = 0 ; j < i ; j++) {
882 IWineD3DSurface_Release(object->surfaces[j]);
884 /* heap free object */
885 HeapFree(GetProcessHeap(), 0, object);
887 *ppTexture = NULL;
888 return hr;
891 IWineD3DSurface_SetContainer(object->surfaces[i], (IWineD3DBase *)object);
892 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
893 /* calculate the next mipmap level */
894 tmpW = max(1, tmpW >> 1);
895 tmpH = max(1, tmpH >> 1);
898 TRACE("(%p) : Created texture %p\n", This, object);
899 return WINED3D_OK;
902 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
903 UINT Width, UINT Height, UINT Depth,
904 UINT Levels, DWORD Usage,
905 WINED3DFORMAT Format, WINED3DPOOL Pool,
906 IWineD3DVolumeTexture **ppVolumeTexture,
907 HANDLE *pSharedHandle, IUnknown *parent,
908 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
910 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
911 IWineD3DVolumeTextureImpl *object;
912 unsigned int i;
913 UINT tmpW;
914 UINT tmpH;
915 UINT tmpD;
917 /* TODO: It should only be possible to create textures for formats
918 that are reported as supported */
919 if (WINED3DFMT_UNKNOWN >= Format) {
920 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
921 return WINED3DERR_INVALIDCALL;
924 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, WINED3DRTYPE_VOLUMETEXTURE, 0);
925 D3DINITIALIZEBASETEXTURE(object->baseTexture);
927 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
928 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
930 object->width = Width;
931 object->height = Height;
932 object->depth = Depth;
934 /* Calculate levels for mip mapping */
935 if (Levels == 0) {
936 object->baseTexture.levels++;
937 tmpW = Width;
938 tmpH = Height;
939 tmpD = Depth;
940 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
941 tmpW = max(1, tmpW >> 1);
942 tmpH = max(1, tmpH >> 1);
943 tmpD = max(1, tmpD >> 1);
944 object->baseTexture.levels++;
946 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
949 /* Generate all the surfaces */
950 tmpW = Width;
951 tmpH = Height;
952 tmpD = Depth;
954 for (i = 0; i < object->baseTexture.levels; i++)
956 /* Create the volume */
957 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
958 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
960 /* Set it's container to this object */
961 IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)object);
963 /* calcualte the next mipmap level */
964 tmpW = max(1, tmpW >> 1);
965 tmpH = max(1, tmpH >> 1);
966 tmpD = max(1, tmpD >> 1);
969 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
970 TRACE("(%p) : Created volume texture %p\n", This, object);
971 return WINED3D_OK;
974 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
975 UINT Width, UINT Height, UINT Depth,
976 DWORD Usage,
977 WINED3DFORMAT Format, WINED3DPOOL Pool,
978 IWineD3DVolume** ppVolume,
979 HANDLE* pSharedHandle, IUnknown *parent) {
981 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
982 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
984 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, WINED3DRTYPE_VOLUME, ((Width * D3DFmtGetBpp(This, Format)) * Height * Depth))
986 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
987 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
989 object->currentDesc.Width = Width;
990 object->currentDesc.Height = Height;
991 object->currentDesc.Depth = Depth;
992 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
994 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
995 object->lockable = TRUE;
996 object->locked = FALSE;
997 memset(&object->lockedBox, 0, sizeof(WINED3DBOX));
998 object->dirty = TRUE;
1000 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
1003 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
1004 UINT Levels, DWORD Usage,
1005 WINED3DFORMAT Format, WINED3DPOOL Pool,
1006 IWineD3DCubeTexture **ppCubeTexture,
1007 HANDLE *pSharedHandle, IUnknown *parent,
1008 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1010 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1011 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1012 unsigned int i, j;
1013 UINT tmpW;
1014 HRESULT hr;
1015 unsigned int pow2EdgeLength = EdgeLength;
1017 /* TODO: It should only be possible to create textures for formats
1018 that are reported as supported */
1019 if (WINED3DFMT_UNKNOWN >= Format) {
1020 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
1021 return WINED3DERR_INVALIDCALL;
1024 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, WINED3DRTYPE_CUBETEXTURE, 0);
1025 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1027 TRACE("(%p) Create Cube Texture\n", This);
1029 /** Non-power2 support **/
1031 /* Find the nearest pow2 match */
1032 pow2EdgeLength = 1;
1033 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
1035 object->edgeLength = EdgeLength;
1036 /* TODO: support for native non-power 2 */
1037 /* Precalculated scaling for 'faked' non power of two texture coords */
1038 object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
1040 /* Calculate levels for mip mapping */
1041 if (Levels == 0) {
1042 object->baseTexture.levels++;
1043 tmpW = EdgeLength;
1044 while (tmpW > 1) {
1045 tmpW = max(1, tmpW >> 1);
1046 object->baseTexture.levels++;
1048 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1051 /* Generate all the surfaces */
1052 tmpW = EdgeLength;
1053 for (i = 0; i < object->baseTexture.levels; i++) {
1055 /* Create the 6 faces */
1056 for (j = 0; j < 6; j++) {
1058 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
1059 i /* Level */, &object->surfaces[j][i],pSharedHandle);
1061 if(hr!= WINED3D_OK) {
1062 /* clean up */
1063 int k;
1064 int l;
1065 for (l = 0; l < j; l++) {
1066 IWineD3DSurface_Release(object->surfaces[j][i]);
1068 for (k = 0; k < i; k++) {
1069 for (l = 0; l < 6; l++) {
1070 IWineD3DSurface_Release(object->surfaces[l][j]);
1074 FIXME("(%p) Failed to create surface\n",object);
1075 HeapFree(GetProcessHeap(),0,object);
1076 *ppCubeTexture = NULL;
1077 return hr;
1079 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IWineD3DBase *)object);
1080 TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1082 tmpW = max(1, tmpW >> 1);
1085 TRACE("(%p) : Created Cube Texture %p\n", This, object);
1086 *ppCubeTexture = (IWineD3DCubeTexture *) object;
1087 return WINED3D_OK;
1090 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1091 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1092 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1094 if (NULL == ppQuery) {
1095 /* Just a check to see if we support this type of query */
1096 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1097 switch(Type) {
1098 case WINED3DQUERYTYPE_OCCLUSION:
1099 TRACE("(%p) occlusion query\n", This);
1100 if (GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY))
1101 hr = WINED3D_OK;
1102 else
1103 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1104 break;
1105 case WINED3DQUERYTYPE_VCACHE:
1106 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1107 case WINED3DQUERYTYPE_VERTEXSTATS:
1108 case WINED3DQUERYTYPE_EVENT:
1109 case WINED3DQUERYTYPE_TIMESTAMP:
1110 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1111 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1112 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1113 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1114 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1115 case WINED3DQUERYTYPE_PIXELTIMINGS:
1116 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1117 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1118 default:
1119 FIXME("(%p) Unhandled query type %d\n", This, Type);
1121 return hr;
1124 D3DCREATEOBJECTINSTANCE(object, Query)
1125 object->type = Type;
1126 /* allocated the 'extended' data based on the type of query requested */
1127 switch(Type){
1128 case D3DQUERYTYPE_OCCLUSION:
1129 if(GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY)) {
1130 TRACE("(%p) Allocating data for an occlusion query\n", This);
1131 object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1132 break;
1134 case D3DQUERYTYPE_VCACHE:
1135 case D3DQUERYTYPE_RESOURCEMANAGER:
1136 case D3DQUERYTYPE_VERTEXSTATS:
1137 case D3DQUERYTYPE_EVENT:
1138 case D3DQUERYTYPE_TIMESTAMP:
1139 case D3DQUERYTYPE_TIMESTAMPDISJOINT:
1140 case D3DQUERYTYPE_TIMESTAMPFREQ:
1141 case D3DQUERYTYPE_PIPELINETIMINGS:
1142 case D3DQUERYTYPE_INTERFACETIMINGS:
1143 case D3DQUERYTYPE_VERTEXTIMINGS:
1144 case D3DQUERYTYPE_PIXELTIMINGS:
1145 case D3DQUERYTYPE_BANDWIDTHTIMINGS:
1146 case D3DQUERYTYPE_CACHEUTILIZATION:
1147 default:
1148 object->extendedData = 0;
1149 FIXME("(%p) Unhandled query type %d\n",This , Type);
1151 TRACE("(%p) : Created Query %p\n", This, object);
1152 return WINED3D_OK;
1155 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1156 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1157 IUnknown* parent,
1158 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1159 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1160 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1162 HDC hDc;
1163 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1164 int num;
1165 XVisualInfo template;
1166 GLXContext oldContext;
1167 Drawable oldDrawable;
1168 HRESULT hr = WINED3D_OK;
1170 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1172 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1173 * does a device hold a reference to a swap chain giving them a lifetime of the device
1174 * or does the swap chain notify the device of its destruction.
1175 *******************************/
1177 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1179 /* Initialize other useful values */
1180 object->presentParms.BackBufferCount = 1; /* TODO:? support for gl_aux buffers */
1182 /*********************
1183 * Lookup the window Handle and the relating X window handle
1184 ********************/
1186 /* Setup hwnd we are using, plus which display this equates to */
1187 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1188 if (!object->win_handle) {
1189 object->win_handle = This->createParms.hFocusWindow;
1192 object->win_handle = GetAncestor(object->win_handle, GA_ROOT);
1193 if ( !( object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window") ) ) {
1194 ERR("Can't get drawable (window), HWND:%p doesn't have the property __wine_x11_whole_window\n", object->win_handle);
1195 return WINED3DERR_NOTAVAILABLE;
1197 hDc = GetDC(object->win_handle);
1198 object->display = get_display(hDc);
1199 ReleaseDC(object->win_handle, hDc);
1200 TRACE("Using a display of %p %p\n", object->display, hDc);
1202 if (NULL == object->display || NULL == hDc) {
1203 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1204 return WINED3DERR_NOTAVAILABLE;
1207 if (object->win == 0) {
1208 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1209 return WINED3DERR_NOTAVAILABLE;
1212 * Create an opengl context for the display visual
1213 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1214 * use different properties after that point in time. FIXME: How to handle when requested format
1215 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1216 * it chooses is identical to the one already being used!
1217 **********************************/
1219 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1220 ENTER_GL();
1222 /* Create a new context for this swapchain */
1223 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1224 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1225 (or the best possible if none is requested) */
1226 TRACE("Found x visual ID : %ld\n", template.visualid);
1228 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1229 if (NULL == object->visInfo) {
1230 ERR("cannot really get XVisual\n");
1231 LEAVE_GL();
1232 return WINED3DERR_NOTAVAILABLE;
1233 } else {
1234 int n, value;
1235 /* Write out some debug info about the visual/s */
1236 TRACE("Using x visual ID : %ld\n", template.visualid);
1237 TRACE(" visual info: %p\n", object->visInfo);
1238 TRACE(" num items : %d\n", num);
1239 for (n = 0;n < num; n++) {
1240 TRACE("=====item=====: %d\n", n + 1);
1241 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1242 TRACE(" screen : %d\n", object->visInfo[n].screen);
1243 TRACE(" depth : %u\n", object->visInfo[n].depth);
1244 TRACE(" class : %d\n", object->visInfo[n].class);
1245 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1246 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1247 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1248 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1249 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1250 /* log some extra glx info */
1251 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1252 TRACE(" gl_aux_buffers : %d\n", value);
1253 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1254 TRACE(" gl_buffer_size : %d\n", value);
1255 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1256 TRACE(" gl_red_size : %d\n", value);
1257 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1258 TRACE(" gl_green_size : %d\n", value);
1259 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1260 TRACE(" gl_blue_size : %d\n", value);
1261 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1262 TRACE(" gl_alpha_size : %d\n", value);
1263 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1264 TRACE(" gl_depth_size : %d\n", value);
1265 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1266 TRACE(" gl_stencil_size : %d\n", value);
1268 /* Now choose a simila visual ID*/
1270 #ifdef USE_CONTEXT_MANAGER
1272 /** TODO: use a context mamager **/
1273 #endif
1276 IWineD3DSwapChain *implSwapChain;
1277 if (WINED3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1278 /* The first time around we create the context that is shared with all other swapchains and render targets */
1279 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1280 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1281 } else {
1283 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1284 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1285 /* and create a new context with the implicit swapchains context as the shared context */
1286 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1287 IWineD3DSwapChain_Release(implSwapChain);
1291 /* Cleanup */
1292 XFree(object->visInfo);
1293 object->visInfo = NULL;
1295 if (NULL == object->glCtx) {
1296 ERR("cannot create glxContext\n");
1297 LEAVE_GL();
1298 return WINED3DERR_NOTAVAILABLE;
1301 LEAVE_GL();
1302 if (object->glCtx == NULL) {
1303 ERR("Error in context creation !\n");
1304 return WINED3DERR_INVALIDCALL;
1305 } else {
1306 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1307 object->win_handle, object->glCtx, object->win, object->visInfo);
1310 /*********************
1311 * Windowed / Fullscreen
1312 *******************/
1315 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1316 * so we should really check to see if there is a fullscreen swapchain already
1317 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1318 **************************************/
1320 if (!*(pPresentationParameters->Windowed)) {
1322 DEVMODEW devmode;
1323 HDC hdc;
1324 int bpp = 0;
1326 /* Get info on the current display setup */
1327 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1328 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1329 DeleteDC(hdc);
1331 /* Change the display settings */
1332 memset(&devmode, 0, sizeof(DEVMODEW));
1333 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1334 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1335 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1336 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1337 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1338 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1340 /* Make popup window */
1341 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1342 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1343 *(pPresentationParameters->BackBufferWidth),
1344 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1350 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1351 * then the corresponding dimension of the client area of the hDeviceWindow
1352 * (or the focus window, if hDeviceWindow is NULL) is taken.
1353 **********************/
1355 if (*(pPresentationParameters->Windowed) &&
1356 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1357 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1359 RECT Rect;
1360 GetClientRect(object->win_handle, &Rect);
1362 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1363 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1364 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1366 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1367 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1368 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1372 /*********************
1373 * finish off parameter initialization
1374 *******************/
1376 /* Put the correct figures in the presentation parameters */
1377 TRACE("Coppying accross presentaion paraneters\n");
1378 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1379 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1380 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1381 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1382 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1383 object->presentParms.MultiSampleQuality = NULL == pPresentationParameters->MultiSampleQuality ? 0 : *(pPresentationParameters->MultiSampleQuality);
1384 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1385 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1386 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1387 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1388 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1389 object->presentParms.Flags = *(pPresentationParameters->Flags);
1390 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1391 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1394 /*********************
1395 * Create the back, front and stencil buffers
1396 *******************/
1397 TRACE("calling rendertarget CB\n");
1398 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1399 object->presentParms.BackBufferWidth,
1400 object->presentParms.BackBufferHeight,
1401 object->presentParms.BackBufferFormat,
1402 object->presentParms.MultiSampleType,
1403 object->presentParms.MultiSampleQuality,
1404 TRUE /* Lockable */,
1405 &object->frontBuffer,
1406 NULL /* pShared (always null)*/);
1407 if (object->frontBuffer != NULL)
1408 IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
1409 TRACE("calling rendertarget CB\n");
1410 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1411 object->presentParms.BackBufferWidth,
1412 object->presentParms.BackBufferHeight,
1413 object->presentParms.BackBufferFormat,
1414 object->presentParms.MultiSampleType,
1415 object->presentParms.MultiSampleQuality,
1416 TRUE /* Lockable */,
1417 &object->backBuffer,
1418 NULL /* pShared (always null)*/);
1419 if (object->backBuffer != NULL)
1420 IWineD3DSurface_SetContainer(object->backBuffer, (IWineD3DBase *)object);
1422 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1423 if (pPresentationParameters->EnableAutoDepthStencil) {
1424 TRACE("Creating depth stencil buffer\n");
1425 if (This->depthStencilBuffer == NULL ) {
1426 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1427 object->presentParms.BackBufferWidth,
1428 object->presentParms.BackBufferHeight,
1429 object->presentParms.AutoDepthStencilFormat,
1430 object->presentParms.MultiSampleType,
1431 object->presentParms.MultiSampleQuality,
1432 FALSE /* FIXME: Discard */,
1433 &This->depthStencilBuffer,
1434 NULL /* pShared (always null)*/ );
1435 if (This->depthStencilBuffer != NULL)
1436 IWineD3DSurface_SetContainer(This->depthStencilBuffer, 0);
1439 /** TODO: A check on width, height and multisample types
1440 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1441 ****************************/
1442 object->wantsDepthStencilBuffer = TRUE;
1443 } else {
1444 object->wantsDepthStencilBuffer = FALSE;
1447 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1450 /*********************
1451 * init the default renderTarget management
1452 *******************/
1453 object->drawable = object->win;
1454 object->render_ctx = object->glCtx;
1456 if (hr == WINED3D_OK) {
1457 /*********************
1458 * Setup some defaults and clear down the buffers
1459 *******************/
1460 ENTER_GL();
1461 /** save current context and drawable **/
1462 oldContext = glXGetCurrentContext();
1463 oldDrawable = glXGetCurrentDrawable();
1465 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1466 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1467 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1469 checkGLcall("glXMakeCurrent");
1471 TRACE("Setting up the screen\n");
1472 /* Clear the screen */
1473 glClearColor(1.0, 0.0, 0.0, 0.0);
1474 checkGLcall("glClearColor");
1475 glClearIndex(0);
1476 glClearDepth(1);
1477 glClearStencil(0xffff);
1479 checkGLcall("glClear");
1481 glColor3f(1.0, 1.0, 1.0);
1482 checkGLcall("glColor3f");
1484 glEnable(GL_LIGHTING);
1485 checkGLcall("glEnable");
1487 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1488 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1490 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1491 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1493 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1494 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1496 /* switch back to the original context (if there was one)*/
1497 if (This->swapchains != NULL) {
1498 /** TODO: restore the context and drawable **/
1499 glXMakeCurrent(object->display, oldDrawable, oldContext);
1502 LEAVE_GL();
1504 { /* Finally add the swapchain to the end of the devices' swapchain list */
1505 SwapChainList **nextSwapchain;
1506 nextSwapchain = &This->swapchains;
1507 while (*nextSwapchain != NULL) {
1508 nextSwapchain = &((*nextSwapchain)->next);
1510 (*nextSwapchain) = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->swapchains));
1511 (*nextSwapchain)->swapchain = (IWineD3DSwapChain *)object;
1513 TRACE("Set swapchain to %p\n", object);
1514 } else { /* something went wrong so clean up */
1515 IUnknown* bufferParent;
1516 if (object->frontBuffer) {
1518 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1519 IUnknown_Release(bufferParent); /* once for the get parent */
1520 if (IUnknown_Release(bufferParent) > 0) {
1521 FIXME("(%p) Something's still holding the front buffer\n",This);
1524 if (object->backBuffer) {
1525 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1526 IUnknown_Release(bufferParent); /* once for the get parent */
1527 if (IUnknown_Release(bufferParent) > 0) {
1528 FIXME("(%p) Something's still holding the back buffer\n",This);
1531 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1532 /* Clean up the context */
1533 /* check that we are the current context first (we shouldn't be though!) */
1534 if (object->glCtx != 0) {
1535 if(glXGetCurrentContext() == object->glCtx) {
1536 glXMakeCurrent(object->display, None, NULL);
1538 glXDestroyContext(object->display, object->glCtx);
1540 HeapFree(GetProcessHeap(), 0, object);
1544 return hr;
1547 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1548 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1549 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1550 unsigned int numberOfSwapChains = 0;
1551 SwapChainList *swapchain;
1553 swapchain = This->swapchains;
1554 /* itterate through the list to get a count */
1555 while (swapchain != NULL) {
1556 swapchain = swapchain->next;
1557 numberOfSwapChains++;
1560 TRACE("(%p) returning %d\n", This, numberOfSwapChains);
1561 return numberOfSwapChains;
1564 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1565 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1566 SwapChainList *swapchain;
1567 int i = iSwapChain;
1568 HRESULT hr = WINED3DERR_INVALIDCALL;
1569 swapchain = This->swapchains;
1570 TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1573 TRACE("(%p) Finding swapchain %d\n", This, iSwapChain);
1574 while (i > 0 && swapchain != NULL) {
1575 swapchain = swapchain->next;
1576 --i;
1579 if (i > 0) {
1580 FIXME("(%p) Unable to find swapchain %d\n", This, iSwapChain);
1581 *pSwapChain = NULL;
1582 } else if (swapchain != NULL) {
1583 /** TODO: move off to a linkesList implementation **/
1584 *pSwapChain = swapchain->swapchain;
1585 IWineD3DSwapChain_AddRef(*pSwapChain);
1586 hr = WINED3D_OK;
1589 TRACE("(%p) returning %p\n", This, *pSwapChain);
1590 return hr;
1593 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
1594 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1596 FIXME("(%p) : Stub\n",This);
1597 return WINED3D_OK;
1601 /*****
1602 * Vertex Declaration
1603 *****/
1604 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1605 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1606 IWineD3DVertexDeclarationImpl *object = NULL;
1607 HRESULT hr = WINED3D_OK;
1608 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1609 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1610 object->allFVF = 0;
1612 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1614 return hr;
1617 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1618 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pDeclaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1619 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1620 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1621 HRESULT hr = WINED3D_OK;
1622 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1623 object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins;
1625 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1627 /* If a vertex declaration has been passed, save it to the vertex shader, this affects d3d8 only. */
1628 /* Further it needs to be set before calling SetFunction as SetFunction needs the declaration. */
1629 if (pDeclaration != NULL) {
1630 IWineD3DVertexDeclaration *vertexDeclaration;
1631 hr = IWineD3DDevice_CreateVertexDeclaration(iface, pDeclaration, &vertexDeclaration ,NULL);
1632 if (WINED3D_OK == hr) {
1633 TRACE("(%p) : Setting vertex declaration to %p\n", This, vertexDeclaration);
1634 object->vertexDeclaration = vertexDeclaration;
1635 } else {
1636 FIXME("(%p) : Failed to set the declaration, returning WINED3DERR_INVALIDCALL\n", iface);
1637 IWineD3DVertexShader_Release(*ppVertexShader);
1638 return WINED3DERR_INVALIDCALL;
1642 hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1644 if (WINED3D_OK != hr) {
1645 FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface);
1646 IWineD3DVertexShader_Release(*ppVertexShader);
1647 return WINED3DERR_INVALIDCALL;
1650 #if 0 /* TODO: In D3D* SVP is atatched to the shader, in D3D9 it's attached to the device and isn't stored in the stateblock. */
1651 if(Usage == WINED3DUSAGE_SOFTWAREVERTEXPROCESSING) {
1652 /* Foo */
1653 } else {
1654 /* Bar */
1657 #endif
1659 return WINED3D_OK;
1662 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
1663 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1664 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1665 HRESULT hr = WINED3D_OK;
1667 D3DCREATEOBJECTINSTANCE(object, PixelShader)
1668 object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins;
1669 hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
1670 if (WINED3D_OK == hr) {
1671 TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
1672 } else {
1673 WARN("(%p) : Failed to create pixel shader\n", This);
1676 return hr;
1679 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
1680 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1681 *ppD3D= This->wineD3D;
1682 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1683 IWineD3D_AddRef(*ppD3D);
1684 return WINED3D_OK;
1687 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1688 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1689 * Into the video ram as possible and seeing how many fit
1690 * you can also get the correct initial value from via X and ATI's driver
1691 *******************/
1692 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1693 static BOOL showfixmes = TRUE;
1694 if (showfixmes) {
1695 FIXME("(%p) : stub, emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1696 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1697 showfixmes = FALSE;
1699 TRACE("(%p) : emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1700 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1701 /* videomemory is simulated videomemory + AGP memory left */
1702 return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1707 /*****
1708 * Get / Set FVF
1709 *****/
1710 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1711 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1712 HRESULT hr = WINED3D_OK;
1714 /* Update the current state block */
1715 This->updateStateBlock->fvf = fvf;
1716 This->updateStateBlock->changed.fvf = TRUE;
1717 This->updateStateBlock->set.fvf = TRUE;
1719 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1721 if (0 != fvf) {
1722 /* clear down the vertex declaration
1723 NOTE: Axis and Allies doesn't work properly otherwise
1724 (may be a stateblock problem though!)
1726 hr = IWineD3DDevice_SetVertexDeclaration(iface, NULL);
1729 return hr;
1733 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1734 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1735 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1736 *pfvf = This->stateBlock->fvf;
1737 return WINED3D_OK;
1740 /*****
1741 * Get / Set Stream Source
1742 *****/
1743 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1744 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1745 IWineD3DVertexBuffer *oldSrc;
1747 /**TODO: instance and index data, see
1748 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1750 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
1751 **************/
1753 /* D3d9 only, but shouldn't hurt d3d8 */
1754 UINT streamFlags;
1756 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1757 if (streamFlags) {
1758 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1759 FIXME("stream index data not supported\n");
1761 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1762 FIXME("stream instance data not supported\n");
1766 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1768 if (StreamNumber >= MAX_STREAMS) {
1769 WARN("Stream out of range %d\n", StreamNumber);
1770 return WINED3DERR_INVALIDCALL;
1773 oldSrc = This->stateBlock->streamSource[StreamNumber];
1774 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1776 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
1777 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
1778 This->updateStateBlock->streamStride[StreamNumber] = Stride;
1779 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
1780 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
1781 This->updateStateBlock->streamFlags[StreamNumber] = streamFlags;
1783 /* Handle recording of state blocks */
1784 if (This->isRecordingState) {
1785 TRACE("Recording... not performing anything\n");
1786 return WINED3D_OK;
1789 /* Not recording... */
1790 /* Need to do a getParent and pass the reffs up */
1791 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
1792 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
1793 so for now, just count internally */
1794 if (pStreamData != NULL) {
1795 IWineD3DVertexBuffer_AddRef(pStreamData);
1797 if (oldSrc != NULL) {
1798 IWineD3DVertexBuffer_Release(oldSrc);
1801 return WINED3D_OK;
1804 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
1805 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1806 UINT streamFlags;
1808 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
1809 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
1812 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1813 if (streamFlags) {
1814 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1815 FIXME("stream index data not supported\n");
1817 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1818 FIXME("stream instance data not supported\n");
1822 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1824 if (StreamNumber >= MAX_STREAMS) {
1825 WARN("Stream out of range %d\n", StreamNumber);
1826 return WINED3DERR_INVALIDCALL;
1828 *pStream = This->stateBlock->streamSource[StreamNumber];
1829 *pStride = This->stateBlock->streamStride[StreamNumber];
1830 *pOffset = This->stateBlock->streamOffset[StreamNumber];
1832 if (*pStream == NULL) {
1833 FIXME("Attempting to get an empty stream %d, returning WINED3DERR_INVALIDCALL\n", StreamNumber);
1834 return WINED3DERR_INVALIDCALL;
1837 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
1838 return WINED3D_OK;
1841 /*Should be quite easy, just an extension of vertexdata
1842 ref...
1843 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1845 The divider is a bit odd though
1847 VertexOffset = StartVertex / Divider * StreamStride +
1848 VertexIndex / Divider * StreamStride + StreamOffset
1851 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
1852 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1854 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
1855 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (D3DSTREAMSOURCE_INSTANCEDATA | D3DSTREAMSOURCE_INDEXEDDATA );
1857 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
1858 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
1859 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
1861 if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
1862 FIXME("Stream indexing not fully supported\n");
1865 return WINED3D_OK;
1868 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
1869 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1871 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
1872 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
1874 TRACE("(%p) : returning %d\n", This, *Divider);
1876 return WINED3D_OK;
1879 /*****
1880 * Get / Set & Multiply Transform
1881 *****/
1882 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1883 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1885 /* Most of this routine, comments included copied from ddraw tree initially: */
1886 TRACE("(%p) : Transform State=%d\n", This, d3dts);
1888 /* Handle recording of state blocks */
1889 if (This->isRecordingState) {
1890 TRACE("Recording... not performing anything\n");
1891 This->updateStateBlock->changed.transform[d3dts] = TRUE;
1892 This->updateStateBlock->set.transform[d3dts] = TRUE;
1893 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1894 return WINED3D_OK;
1898 * If the new matrix is the same as the current one,
1899 * we cut off any further processing. this seems to be a reasonable
1900 * optimization because as was noticed, some apps (warcraft3 for example)
1901 * tend towards setting the same matrix repeatedly for some reason.
1903 * From here on we assume that the new matrix is different, wherever it matters.
1905 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1906 TRACE("The app is setting the same matrix over again\n");
1907 return WINED3D_OK;
1908 } else {
1909 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1913 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1914 where ViewMat = Camera space, WorldMat = world space.
1916 In OpenGL, camera and world space is combined into GL_MODELVIEW
1917 matrix. The Projection matrix stay projection matrix.
1920 /* Capture the times we can just ignore the change for now */
1921 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1922 This->modelview_valid = FALSE;
1923 return WINED3D_OK;
1925 } else if (d3dts == D3DTS_PROJECTION) {
1926 This->proj_valid = FALSE;
1927 return WINED3D_OK;
1929 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1930 /* Indexed Vertex Blending Matrices 256 -> 511 */
1931 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1932 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1933 return WINED3D_OK;
1936 /* Now we really are going to have to change a matrix */
1937 ENTER_GL();
1939 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1940 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
1941 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1942 unsigned int k;
1944 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1945 * NOTE: We have to reset the positions even if the light/plane is not currently
1946 * enabled, since the call to enable it will not reset the position.
1947 * NOTE2: Apparently texture transforms do NOT need reapplying
1950 PLIGHTINFOEL *lightChain = NULL;
1951 This->modelview_valid = FALSE;
1952 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
1954 glMatrixMode(GL_MODELVIEW);
1955 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1956 glPushMatrix();
1957 glLoadMatrixf((float *)lpmatrix);
1958 checkGLcall("glLoadMatrixf(...)");
1960 /* Reset lights */
1961 lightChain = This->stateBlock->lights;
1962 while (lightChain && lightChain->glIndex != -1) {
1963 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1964 checkGLcall("glLightfv posn");
1965 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1966 checkGLcall("glLightfv dirn");
1967 lightChain = lightChain->next;
1970 /* Reset Clipping Planes if clipping is enabled */
1971 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1972 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1973 checkGLcall("glClipPlane");
1975 glPopMatrix();
1977 } else { /* What was requested!?? */
1978 WARN("invalid matrix specified: %i\n", d3dts);
1981 /* Release lock, all done */
1982 LEAVE_GL();
1983 return WINED3D_OK;
1986 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1987 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1988 TRACE("(%p) : for Transform State %d\n", This, State);
1989 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1990 return WINED3D_OK;
1993 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1994 D3DMATRIX *mat = NULL;
1995 D3DMATRIX temp;
1997 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1998 * below means it will be recorded in a state block change, but it
1999 * works regardless where it is recorded.
2000 * If this is found to be wrong, change to StateBlock.
2002 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2003 TRACE("(%p) : For state %u\n", This, State);
2005 if (State < HIGHEST_TRANSFORMSTATE)
2007 mat = &This->updateStateBlock->transforms[State];
2008 } else {
2009 FIXME("Unhandled transform state!!\n");
2012 /* Copied from ddraw code: */
2013 temp.u.s._11 = (mat->u.s._11 * pMatrix->u.s._11) + (mat->u.s._21 * pMatrix->u.s._12) +
2014 (mat->u.s._31 * pMatrix->u.s._13) + (mat->u.s._41 * pMatrix->u.s._14);
2015 temp.u.s._21 = (mat->u.s._11 * pMatrix->u.s._21) + (mat->u.s._21 * pMatrix->u.s._22) +
2016 (mat->u.s._31 * pMatrix->u.s._23) + (mat->u.s._41 * pMatrix->u.s._24);
2017 temp.u.s._31 = (mat->u.s._11 * pMatrix->u.s._31) + (mat->u.s._21 * pMatrix->u.s._32) +
2018 (mat->u.s._31 * pMatrix->u.s._33) + (mat->u.s._41 * pMatrix->u.s._34);
2019 temp.u.s._41 = (mat->u.s._11 * pMatrix->u.s._41) + (mat->u.s._21 * pMatrix->u.s._42) +
2020 (mat->u.s._31 * pMatrix->u.s._43) + (mat->u.s._41 * pMatrix->u.s._44);
2022 temp.u.s._12 = (mat->u.s._12 * pMatrix->u.s._11) + (mat->u.s._22 * pMatrix->u.s._12) +
2023 (mat->u.s._32 * pMatrix->u.s._13) + (mat->u.s._42 * pMatrix->u.s._14);
2024 temp.u.s._22 = (mat->u.s._12 * pMatrix->u.s._21) + (mat->u.s._22 * pMatrix->u.s._22) +
2025 (mat->u.s._32 * pMatrix->u.s._23) + (mat->u.s._42 * pMatrix->u.s._24);
2026 temp.u.s._32 = (mat->u.s._12 * pMatrix->u.s._31) + (mat->u.s._22 * pMatrix->u.s._32) +
2027 (mat->u.s._32 * pMatrix->u.s._33) + (mat->u.s._42 * pMatrix->u.s._34);
2028 temp.u.s._42 = (mat->u.s._12 * pMatrix->u.s._41) + (mat->u.s._22 * pMatrix->u.s._42) +
2029 (mat->u.s._32 * pMatrix->u.s._43) + (mat->u.s._42 * pMatrix->u.s._44);
2031 temp.u.s._13 = (mat->u.s._13 * pMatrix->u.s._11) + (mat->u.s._23 * pMatrix->u.s._12) +
2032 (mat->u.s._33 * pMatrix->u.s._13) + (mat->u.s._43 * pMatrix->u.s._14);
2033 temp.u.s._23 = (mat->u.s._13 * pMatrix->u.s._21) + (mat->u.s._23 * pMatrix->u.s._22) +
2034 (mat->u.s._33 * pMatrix->u.s._23) + (mat->u.s._43 * pMatrix->u.s._24);
2035 temp.u.s._33 = (mat->u.s._13 * pMatrix->u.s._31) + (mat->u.s._23 * pMatrix->u.s._32) +
2036 (mat->u.s._33 * pMatrix->u.s._33) + (mat->u.s._43 * pMatrix->u.s._34);
2037 temp.u.s._43 = (mat->u.s._13 * pMatrix->u.s._41) + (mat->u.s._23 * pMatrix->u.s._42) +
2038 (mat->u.s._33 * pMatrix->u.s._43) + (mat->u.s._43 * pMatrix->u.s._44);
2040 temp.u.s._14 = (mat->u.s._14 * pMatrix->u.s._11) + (mat->u.s._24 * pMatrix->u.s._12) +
2041 (mat->u.s._34 * pMatrix->u.s._13) + (mat->u.s._44 * pMatrix->u.s._14);
2042 temp.u.s._24 = (mat->u.s._14 * pMatrix->u.s._21) + (mat->u.s._24 * pMatrix->u.s._22) +
2043 (mat->u.s._34 * pMatrix->u.s._23) + (mat->u.s._44 * pMatrix->u.s._24);
2044 temp.u.s._34 = (mat->u.s._14 * pMatrix->u.s._31) + (mat->u.s._24 * pMatrix->u.s._32) +
2045 (mat->u.s._34 * pMatrix->u.s._33) + (mat->u.s._44 * pMatrix->u.s._34);
2046 temp.u.s._44 = (mat->u.s._14 * pMatrix->u.s._41) + (mat->u.s._24 * pMatrix->u.s._42) +
2047 (mat->u.s._34 * pMatrix->u.s._43) + (mat->u.s._44 * pMatrix->u.s._44);
2049 /* Apply change via set transform - will reapply to eg. lights this way */
2050 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2053 /*****
2054 * Get / Set Light
2055 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
2056 *****/
2057 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2058 you can reference any indexes you want as long as that number max are enabled at any
2059 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2060 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2061 but when recording, just build a chain pretty much of commands to be replayed. */
2063 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2064 float rho;
2065 PLIGHTINFOEL *object, *temp;
2067 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2068 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2070 /* If recording state block, just add to end of lights chain */
2071 if (This->isRecordingState) {
2072 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2073 if (NULL == object) {
2074 return WINED3DERR_OUTOFVIDEOMEMORY;
2076 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2077 object->OriginalIndex = Index;
2078 object->glIndex = -1;
2079 object->changed = TRUE;
2081 /* Add to the END of the chain of lights changes to be replayed */
2082 if (This->updateStateBlock->lights == NULL) {
2083 This->updateStateBlock->lights = object;
2084 } else {
2085 temp = This->updateStateBlock->lights;
2086 while (temp->next != NULL) temp=temp->next;
2087 temp->next = object;
2089 TRACE("Recording... not performing anything more\n");
2090 return WINED3D_OK;
2093 /* Ok, not recording any longer so do real work */
2094 object = This->stateBlock->lights;
2095 while (object != NULL && object->OriginalIndex != Index) object = object->next;
2097 /* If we didn't find it in the list of lights, time to add it */
2098 if (object == NULL) {
2099 PLIGHTINFOEL *insertAt,*prevPos;
2101 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2102 if (NULL == object) {
2103 return WINED3DERR_OUTOFVIDEOMEMORY;
2105 object->OriginalIndex = Index;
2106 object->glIndex = -1;
2108 /* Add it to the front of list with the idea that lights will be changed as needed
2109 BUT after any lights currently assigned GL indexes */
2110 insertAt = This->stateBlock->lights;
2111 prevPos = NULL;
2112 while (insertAt != NULL && insertAt->glIndex != -1) {
2113 prevPos = insertAt;
2114 insertAt = insertAt->next;
2117 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2118 This->stateBlock->lights = object;
2119 } else if (insertAt == NULL) { /* End of list */
2120 prevPos->next = object;
2121 object->prev = prevPos;
2122 } else { /* Middle of chain */
2123 if (prevPos == NULL) {
2124 This->stateBlock->lights = object;
2125 } else {
2126 prevPos->next = object;
2128 object->prev = prevPos;
2129 object->next = insertAt;
2130 insertAt->prev = object;
2134 /* Initialize the object */
2135 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,
2136 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2137 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2138 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2139 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2140 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2141 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2143 /* Save away the information */
2144 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2146 switch (pLight->Type) {
2147 case D3DLIGHT_POINT:
2148 /* Position */
2149 object->lightPosn[0] = pLight->Position.x;
2150 object->lightPosn[1] = pLight->Position.y;
2151 object->lightPosn[2] = pLight->Position.z;
2152 object->lightPosn[3] = 1.0f;
2153 object->cutoff = 180.0f;
2154 /* FIXME: Range */
2155 break;
2157 case D3DLIGHT_DIRECTIONAL:
2158 /* Direction */
2159 object->lightPosn[0] = -pLight->Direction.x;
2160 object->lightPosn[1] = -pLight->Direction.y;
2161 object->lightPosn[2] = -pLight->Direction.z;
2162 object->lightPosn[3] = 0.0;
2163 object->exponent = 0.0f;
2164 object->cutoff = 180.0f;
2165 break;
2167 case D3DLIGHT_SPOT:
2168 /* Position */
2169 object->lightPosn[0] = pLight->Position.x;
2170 object->lightPosn[1] = pLight->Position.y;
2171 object->lightPosn[2] = pLight->Position.z;
2172 object->lightPosn[3] = 1.0;
2174 /* Direction */
2175 object->lightDirn[0] = pLight->Direction.x;
2176 object->lightDirn[1] = pLight->Direction.y;
2177 object->lightDirn[2] = pLight->Direction.z;
2178 object->lightDirn[3] = 1.0;
2181 * opengl-ish and d3d-ish spot lights use too different models for the
2182 * light "intensity" as a function of the angle towards the main light direction,
2183 * so we only can approximate very roughly.
2184 * however spot lights are rather rarely used in games (if ever used at all).
2185 * furthermore if still used, probably nobody pays attention to such details.
2187 if (pLight->Falloff == 0) {
2188 rho = 6.28f;
2189 } else {
2190 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2192 if (rho < 0.0001) rho = 0.0001f;
2193 object->exponent = -0.3/log(cos(rho/2));
2194 object->cutoff = pLight->Phi*90/M_PI;
2196 /* FIXME: Range */
2197 break;
2199 default:
2200 FIXME("Unrecognized light type %d\n", pLight->Type);
2203 /* Update the live definitions if the light is currently assigned a glIndex */
2204 if (object->glIndex != -1) {
2205 setup_light(iface, object->glIndex, object);
2207 return WINED3D_OK;
2210 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2211 PLIGHTINFOEL *lightInfo = NULL;
2212 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2213 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2215 /* Locate the light in the live lights */
2216 lightInfo = This->stateBlock->lights;
2217 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2219 if (lightInfo == NULL) {
2220 TRACE("Light information requested but light not defined\n");
2221 return WINED3DERR_INVALIDCALL;
2224 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
2225 return WINED3D_OK;
2228 /*****
2229 * Get / Set Light Enable
2230 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2231 *****/
2232 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2233 PLIGHTINFOEL *lightInfo = NULL;
2234 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2235 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2237 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2238 if (This->isRecordingState) {
2239 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2240 if (NULL == lightInfo) {
2241 return WINED3DERR_OUTOFVIDEOMEMORY;
2243 lightInfo->OriginalIndex = Index;
2244 lightInfo->glIndex = -1;
2245 lightInfo->enabledChanged = TRUE;
2247 /* Add to the END of the chain of lights changes to be replayed */
2248 if (This->updateStateBlock->lights == NULL) {
2249 This->updateStateBlock->lights = lightInfo;
2250 } else {
2251 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2252 while (temp->next != NULL) temp=temp->next;
2253 temp->next = lightInfo;
2255 TRACE("Recording... not performing anything more\n");
2256 return WINED3D_OK;
2259 /* Not recording... So, locate the light in the live lights */
2260 lightInfo = This->stateBlock->lights;
2261 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2263 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2264 if (lightInfo == NULL) {
2265 D3DLIGHT9 lightParms;
2266 /* Warning - untested code :-) Prob safe to change fixme to a trace but
2267 wait until someone confirms it seems to work! */
2268 TRACE("Light enabled requested but light not defined, so defining one!\n");
2269 lightParms.Type = D3DLIGHT_DIRECTIONAL;
2270 lightParms.Diffuse.r = 1.0;
2271 lightParms.Diffuse.g = 1.0;
2272 lightParms.Diffuse.b = 1.0;
2273 lightParms.Diffuse.a = 0.0;
2274 lightParms.Specular.r = 0.0;
2275 lightParms.Specular.g = 0.0;
2276 lightParms.Specular.b = 0.0;
2277 lightParms.Specular.a = 0.0;
2278 lightParms.Ambient.r = 0.0;
2279 lightParms.Ambient.g = 0.0;
2280 lightParms.Ambient.b = 0.0;
2281 lightParms.Ambient.a = 0.0;
2282 lightParms.Position.x = 0.0;
2283 lightParms.Position.y = 0.0;
2284 lightParms.Position.z = 0.0;
2285 lightParms.Direction.x = 0.0;
2286 lightParms.Direction.y = 0.0;
2287 lightParms.Direction.z = 1.0;
2288 lightParms.Range = 0.0;
2289 lightParms.Falloff = 0.0;
2290 lightParms.Attenuation0 = 0.0;
2291 lightParms.Attenuation1 = 0.0;
2292 lightParms.Attenuation2 = 0.0;
2293 lightParms.Theta = 0.0;
2294 lightParms.Phi = 0.0;
2295 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
2297 /* Search for it again! Should be fairly quick as near head of list */
2298 lightInfo = This->stateBlock->lights;
2299 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2300 if (lightInfo == NULL) {
2301 FIXME("Adding default lights has failed dismally\n");
2302 return WINED3DERR_INVALIDCALL;
2306 /* OK, we now have a light... */
2307 if (Enable == FALSE) {
2309 /* If we are disabling it, check it was enabled, and
2310 still only do something if it has assigned a glIndex (which it should have!) */
2311 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2312 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2313 ENTER_GL();
2314 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2315 checkGLcall("glDisable GL_LIGHT0+Index");
2316 LEAVE_GL();
2317 } else {
2318 TRACE("Nothing to do as light was not enabled\n");
2320 lightInfo->lightEnabled = FALSE;
2321 } else {
2323 /* We are enabling it. If it is enabled, it's really simple */
2324 if (lightInfo->lightEnabled) {
2325 /* nop */
2326 TRACE("Nothing to do as light was enabled\n");
2328 /* If it already has a glIndex, it's still simple */
2329 } else if (lightInfo->glIndex != -1) {
2330 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2331 lightInfo->lightEnabled = TRUE;
2332 ENTER_GL();
2333 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2334 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2335 LEAVE_GL();
2337 /* Otherwise got to find space - lights are ordered gl indexes first */
2338 } else {
2339 PLIGHTINFOEL *bsf = NULL;
2340 PLIGHTINFOEL *pos = This->stateBlock->lights;
2341 PLIGHTINFOEL *prev = NULL;
2342 int Index= 0;
2343 int glIndex = -1;
2345 /* Try to minimize changes as much as possible */
2346 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2348 /* Try to remember which index can be replaced if necessary */
2349 if (bsf==NULL && pos->lightEnabled == FALSE) {
2350 /* Found a light we can replace, save as best replacement */
2351 bsf = pos;
2354 /* Step to next space */
2355 prev = pos;
2356 pos = pos->next;
2357 Index ++;
2360 /* If we have too many active lights, fail the call */
2361 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2362 FIXME("Program requests too many concurrent lights\n");
2363 return WINED3DERR_INVALIDCALL;
2365 /* If we have allocated all lights, but not all are enabled,
2366 reuse one which is not enabled */
2367 } else if (Index == This->maxConcurrentLights) {
2368 /* use bsf - Simply swap the new light and the BSF one */
2369 PLIGHTINFOEL *bsfNext = bsf->next;
2370 PLIGHTINFOEL *bsfPrev = bsf->prev;
2372 /* Sort out ends */
2373 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2374 if (bsf->prev != NULL) {
2375 bsf->prev->next = lightInfo;
2376 } else {
2377 This->stateBlock->lights = lightInfo;
2380 /* If not side by side, lots of chains to update */
2381 if (bsf->next != lightInfo) {
2382 lightInfo->prev->next = bsf;
2383 bsf->next->prev = lightInfo;
2384 bsf->next = lightInfo->next;
2385 bsf->prev = lightInfo->prev;
2386 lightInfo->next = bsfNext;
2387 lightInfo->prev = bsfPrev;
2389 } else {
2390 /* Simple swaps */
2391 bsf->prev = lightInfo;
2392 bsf->next = lightInfo->next;
2393 lightInfo->next = bsf;
2394 lightInfo->prev = bsfPrev;
2398 /* Update states */
2399 glIndex = bsf->glIndex;
2400 bsf->glIndex = -1;
2401 lightInfo->glIndex = glIndex;
2402 lightInfo->lightEnabled = TRUE;
2404 /* Finally set up the light in gl itself */
2405 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2406 ENTER_GL();
2407 setup_light(iface, glIndex, lightInfo);
2408 glEnable(GL_LIGHT0 + glIndex);
2409 checkGLcall("glEnable GL_LIGHT0 new setup");
2410 LEAVE_GL();
2412 /* If we reached the end of the allocated lights, with space in the
2413 gl lights, setup a new light */
2414 } else if (pos->glIndex == -1) {
2416 /* We reached the end of the allocated gl lights, so already
2417 know the index of the next one! */
2418 glIndex = Index;
2419 lightInfo->glIndex = glIndex;
2420 lightInfo->lightEnabled = TRUE;
2422 /* In an ideal world, it's already in the right place */
2423 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2424 /* No need to move it */
2425 } else {
2426 /* Remove this light from the list */
2427 lightInfo->prev->next = lightInfo->next;
2428 if (lightInfo->next != NULL) {
2429 lightInfo->next->prev = lightInfo->prev;
2432 /* Add in at appropriate place (inbetween prev and pos) */
2433 lightInfo->prev = prev;
2434 lightInfo->next = pos;
2435 if (prev == NULL) {
2436 This->stateBlock->lights = lightInfo;
2437 } else {
2438 prev->next = lightInfo;
2440 if (pos != NULL) {
2441 pos->prev = lightInfo;
2445 /* Finally set up the light in gl itself */
2446 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2447 ENTER_GL();
2448 setup_light(iface, glIndex, lightInfo);
2449 glEnable(GL_LIGHT0 + glIndex);
2450 checkGLcall("glEnable GL_LIGHT0 new setup");
2451 LEAVE_GL();
2456 return WINED3D_OK;
2459 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2461 PLIGHTINFOEL *lightInfo = NULL;
2462 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2463 TRACE("(%p) : for idx(%ld)\n", This, Index);
2465 /* Locate the light in the live lights */
2466 lightInfo = This->stateBlock->lights;
2467 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2469 if (lightInfo == NULL) {
2470 TRACE("Light enabled state requested but light not defined\n");
2471 return WINED3DERR_INVALIDCALL;
2473 *pEnable = lightInfo->lightEnabled;
2474 return WINED3D_OK;
2477 /*****
2478 * Get / Set Clip Planes
2479 *****/
2480 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2481 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2482 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2484 /* Validate Index */
2485 if (Index >= GL_LIMITS(clipplanes)) {
2486 TRACE("Application has requested clipplane this device doesn't support\n");
2487 return WINED3DERR_INVALIDCALL;
2490 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2491 This->updateStateBlock->set.clipplane[Index] = TRUE;
2492 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2493 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2494 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2495 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2497 /* Handle recording of state blocks */
2498 if (This->isRecordingState) {
2499 TRACE("Recording... not performing anything\n");
2500 return WINED3D_OK;
2503 /* Apply it */
2505 ENTER_GL();
2507 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2508 glMatrixMode(GL_MODELVIEW);
2509 glPushMatrix();
2510 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2512 TRACE("Clipplane [%f,%f,%f,%f]\n",
2513 This->updateStateBlock->clipplane[Index][0],
2514 This->updateStateBlock->clipplane[Index][1],
2515 This->updateStateBlock->clipplane[Index][2],
2516 This->updateStateBlock->clipplane[Index][3]);
2517 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2518 checkGLcall("glClipPlane");
2520 glPopMatrix();
2521 LEAVE_GL();
2523 return WINED3D_OK;
2526 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2527 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2528 TRACE("(%p) : for idx %ld\n", This, Index);
2530 /* Validate Index */
2531 if (Index >= GL_LIMITS(clipplanes)) {
2532 TRACE("Application has requested clipplane this device doesn't support\n");
2533 return WINED3DERR_INVALIDCALL;
2536 pPlane[0] = This->stateBlock->clipplane[Index][0];
2537 pPlane[1] = This->stateBlock->clipplane[Index][1];
2538 pPlane[2] = This->stateBlock->clipplane[Index][2];
2539 pPlane[3] = This->stateBlock->clipplane[Index][3];
2540 return WINED3D_OK;
2543 /*****
2544 * Get / Set Clip Plane Status
2545 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2546 *****/
2547 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2548 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2549 FIXME("(%p) : stub\n", This);
2550 if (NULL == pClipStatus) {
2551 return WINED3DERR_INVALIDCALL;
2553 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2554 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2555 return WINED3D_OK;
2558 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2559 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2560 FIXME("(%p) : stub\n", This);
2561 if (NULL == pClipStatus) {
2562 return WINED3DERR_INVALIDCALL;
2564 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2565 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2566 return WINED3D_OK;
2569 /*****
2570 * Get / Set Material
2571 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2572 *****/
2573 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2574 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2576 This->updateStateBlock->changed.material = TRUE;
2577 This->updateStateBlock->set.material = TRUE;
2578 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2580 /* Handle recording of state blocks */
2581 if (This->isRecordingState) {
2582 TRACE("Recording... not performing anything\n");
2583 return WINED3D_OK;
2586 ENTER_GL();
2587 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2588 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2589 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2590 pMaterial->Ambient.b, pMaterial->Ambient.a);
2591 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2592 pMaterial->Specular.b, pMaterial->Specular.a);
2593 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2594 pMaterial->Emissive.b, pMaterial->Emissive.a);
2595 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2597 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2598 checkGLcall("glMaterialfv(GL_AMBIENT)");
2599 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2600 checkGLcall("glMaterialfv(GL_DIFFUSE)");
2602 /* Only change material color if specular is enabled, otherwise it is set to black */
2603 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2604 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2605 checkGLcall("glMaterialfv(GL_SPECULAR");
2606 } else {
2607 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2608 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2609 checkGLcall("glMaterialfv(GL_SPECULAR");
2611 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2612 checkGLcall("glMaterialfv(GL_EMISSION)");
2613 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2614 checkGLcall("glMaterialf(GL_SHININESS");
2616 LEAVE_GL();
2617 return WINED3D_OK;
2620 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2621 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2622 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2623 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2624 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2625 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2626 pMaterial->Ambient.b, pMaterial->Ambient.a);
2627 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2628 pMaterial->Specular.b, pMaterial->Specular.a);
2629 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2630 pMaterial->Emissive.b, pMaterial->Emissive.a);
2631 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2633 return WINED3D_OK;
2636 /*****
2637 * Get / Set Indices
2638 *****/
2639 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2640 UINT BaseVertexIndex) {
2641 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2642 IWineD3DIndexBuffer *oldIdxs;
2644 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2645 oldIdxs = This->updateStateBlock->pIndexData;
2647 This->updateStateBlock->changed.indices = TRUE;
2648 This->updateStateBlock->set.indices = TRUE;
2649 This->updateStateBlock->pIndexData = pIndexData;
2650 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2652 /* Handle recording of state blocks */
2653 if (This->isRecordingState) {
2654 TRACE("Recording... not performing anything\n");
2655 return WINED3D_OK;
2658 if (NULL != pIndexData) {
2659 IWineD3DIndexBuffer_AddRef(pIndexData);
2661 if (NULL != oldIdxs) {
2662 IWineD3DIndexBuffer_Release(oldIdxs);
2664 return WINED3D_OK;
2667 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2668 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2670 *ppIndexData = This->stateBlock->pIndexData;
2672 /* up ref count on ppindexdata */
2673 if (*ppIndexData) {
2674 IWineD3DIndexBuffer_AddRef(*ppIndexData);
2675 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2676 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
2677 }else{
2678 TRACE("(%p) No index data set\n", This);
2680 TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
2682 return WINED3D_OK;
2685 /*****
2686 * Get / Set Viewports
2687 *****/
2688 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2689 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2691 TRACE("(%p)\n", This);
2692 This->updateStateBlock->changed.viewport = TRUE;
2693 This->updateStateBlock->set.viewport = TRUE;
2694 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2696 /* Handle recording of state blocks */
2697 if (This->isRecordingState) {
2698 TRACE("Recording... not performing anything\n");
2699 return WINED3D_OK;
2701 This->viewport_changed = TRUE;
2703 ENTER_GL();
2705 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2706 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2708 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2709 checkGLcall("glDepthRange");
2710 /* Note: GL requires lower left, DirectX supplies upper left */
2711 /* TODO: replace usage of renderTarget with context management */
2712 glViewport(pViewport->X,
2713 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2714 pViewport->Width, pViewport->Height);
2716 checkGLcall("glViewport");
2718 LEAVE_GL();
2720 return WINED3D_OK;
2724 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2725 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2726 TRACE("(%p)\n", This);
2727 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2728 return WINED3D_OK;
2731 /*****
2732 * Get / Set Render States
2733 * TODO: Verify against dx9 definitions
2734 *****/
2735 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2737 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2738 DWORD OldValue = This->stateBlock->renderState[State];
2740 /* Simple way of referring to either a DWORD or a 4 byte float */
2741 union {
2742 DWORD d;
2743 float f;
2744 } tmpvalue;
2746 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2747 This->updateStateBlock->changed.renderState[State] = TRUE;
2748 This->updateStateBlock->set.renderState[State] = TRUE;
2749 This->updateStateBlock->renderState[State] = Value;
2751 /* Handle recording of state blocks */
2752 if (This->isRecordingState) {
2753 TRACE("Recording... not performing anything\n");
2754 return WINED3D_OK;
2757 ENTER_GL();
2759 switch (State) {
2760 case WINED3DRS_FILLMODE :
2761 switch ((D3DFILLMODE) Value) {
2762 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2763 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2764 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2765 default:
2766 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
2768 checkGLcall("glPolygonMode (fillmode)");
2769 break;
2771 case WINED3DRS_LIGHTING :
2772 if (Value) {
2773 glEnable(GL_LIGHTING);
2774 checkGLcall("glEnable GL_LIGHTING");
2775 } else {
2776 glDisable(GL_LIGHTING);
2777 checkGLcall("glDisable GL_LIGHTING");
2779 break;
2781 case WINED3DRS_ZENABLE :
2782 switch ((D3DZBUFFERTYPE) Value) {
2783 case D3DZB_FALSE:
2784 glDisable(GL_DEPTH_TEST);
2785 checkGLcall("glDisable GL_DEPTH_TEST");
2786 break;
2787 case D3DZB_TRUE:
2788 glEnable(GL_DEPTH_TEST);
2789 checkGLcall("glEnable GL_DEPTH_TEST");
2790 break;
2791 case D3DZB_USEW:
2792 glEnable(GL_DEPTH_TEST);
2793 checkGLcall("glEnable GL_DEPTH_TEST");
2794 FIXME("W buffer is not well handled\n");
2795 break;
2796 default:
2797 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2799 break;
2801 case WINED3DRS_CULLMODE :
2803 /* If we are culling "back faces with clockwise vertices" then
2804 set front faces to be counter clockwise and enable culling
2805 of back faces */
2806 switch ((D3DCULL) Value) {
2807 case D3DCULL_NONE:
2808 glDisable(GL_CULL_FACE);
2809 checkGLcall("glDisable GL_CULL_FACE");
2810 break;
2811 case D3DCULL_CW:
2812 glEnable(GL_CULL_FACE);
2813 checkGLcall("glEnable GL_CULL_FACE");
2814 if (This->renderUpsideDown) {
2815 glFrontFace(GL_CW);
2816 checkGLcall("glFrontFace GL_CW");
2817 } else {
2818 glFrontFace(GL_CCW);
2819 checkGLcall("glFrontFace GL_CCW");
2821 glCullFace(GL_BACK);
2822 break;
2823 case D3DCULL_CCW:
2824 glEnable(GL_CULL_FACE);
2825 checkGLcall("glEnable GL_CULL_FACE");
2826 if (This->renderUpsideDown) {
2827 glFrontFace(GL_CCW);
2828 checkGLcall("glFrontFace GL_CCW");
2829 } else {
2830 glFrontFace(GL_CW);
2831 checkGLcall("glFrontFace GL_CW");
2833 glCullFace(GL_BACK);
2834 break;
2835 default:
2836 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2838 break;
2840 case WINED3DRS_SHADEMODE :
2841 switch ((D3DSHADEMODE) Value) {
2842 case D3DSHADE_FLAT:
2843 glShadeModel(GL_FLAT);
2844 checkGLcall("glShadeModel");
2845 break;
2846 case D3DSHADE_GOURAUD:
2847 glShadeModel(GL_SMOOTH);
2848 checkGLcall("glShadeModel");
2849 break;
2850 case D3DSHADE_PHONG:
2851 FIXME("D3DSHADE_PHONG isn't supported?\n");
2853 LEAVE_GL();
2854 return WINED3DERR_INVALIDCALL;
2855 default:
2856 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2858 break;
2860 case WINED3DRS_DITHERENABLE :
2861 if (Value) {
2862 glEnable(GL_DITHER);
2863 checkGLcall("glEnable GL_DITHER");
2864 } else {
2865 glDisable(GL_DITHER);
2866 checkGLcall("glDisable GL_DITHER");
2868 break;
2870 case WINED3DRS_ZWRITEENABLE :
2871 if (Value) {
2872 glDepthMask(1);
2873 checkGLcall("glDepthMask");
2874 } else {
2875 glDepthMask(0);
2876 checkGLcall("glDepthMask");
2878 break;
2880 case WINED3DRS_ZFUNC :
2882 int glParm = GL_LESS;
2884 switch ((D3DCMPFUNC) Value) {
2885 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2886 case D3DCMP_LESS: glParm=GL_LESS; break;
2887 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2888 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2889 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2890 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2891 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2892 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2893 default:
2894 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2896 glDepthFunc(glParm);
2897 checkGLcall("glDepthFunc");
2899 break;
2901 case WINED3DRS_AMBIENT :
2903 float col[4];
2904 D3DCOLORTOGLFLOAT4(Value, col);
2905 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2906 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2907 checkGLcall("glLightModel for MODEL_AMBIENT");
2910 break;
2912 case WINED3DRS_ALPHABLENDENABLE :
2913 if (Value) {
2914 glEnable(GL_BLEND);
2915 checkGLcall("glEnable GL_BLEND");
2916 } else {
2917 glDisable(GL_BLEND);
2918 checkGLcall("glDisable GL_BLEND");
2920 break;
2922 case WINED3DRS_SRCBLEND :
2923 case WINED3DRS_DESTBLEND :
2925 int newVal = GL_ZERO;
2926 switch (Value) {
2927 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2928 case D3DBLEND_ONE : newVal = GL_ONE; break;
2929 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2930 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2931 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2932 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2933 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2934 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2935 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2936 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2937 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2939 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2940 This->srcBlend = newVal;
2941 This->dstBlend = newVal;
2942 break;
2944 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2945 This->srcBlend = newVal;
2946 This->dstBlend = newVal;
2947 break;
2948 default:
2949 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2952 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2953 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2954 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2955 glBlendFunc(This->srcBlend, This->dstBlend);
2957 checkGLcall("glBlendFunc");
2959 break;
2961 case WINED3DRS_ALPHATESTENABLE :
2962 if (Value) {
2963 glEnable(GL_ALPHA_TEST);
2964 checkGLcall("glEnable GL_ALPHA_TEST");
2965 } else {
2966 glDisable(GL_ALPHA_TEST);
2967 checkGLcall("glDisable GL_ALPHA_TEST");
2969 break;
2971 case WINED3DRS_ALPHAFUNC :
2973 int glParm = GL_LESS;
2974 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2976 switch ((D3DCMPFUNC) Value) {
2977 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2978 case D3DCMP_LESS: glParm = GL_LESS; break;
2979 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2980 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2981 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2982 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2983 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2984 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2985 default:
2986 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2988 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2989 glAlphaFunc(glParm, ref);
2990 This->alphafunc = glParm;
2991 checkGLcall("glAlphaFunc");
2993 break;
2995 case WINED3DRS_ALPHAREF :
2997 int glParm = This->alphafunc;
2998 float ref = 1.0f;
3000 ref = ((float) Value) / 255.0f;
3001 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
3002 glAlphaFunc(glParm, ref);
3003 checkGLcall("glAlphaFunc");
3005 break;
3007 case WINED3DRS_CLIPPLANEENABLE :
3008 case WINED3DRS_CLIPPING :
3010 /* Ensure we only do the changed clip planes */
3011 DWORD enable = 0xFFFFFFFF;
3012 DWORD disable = 0x00000000;
3014 /* If enabling / disabling all */
3015 if (State == WINED3DRS_CLIPPING) {
3016 if (Value) {
3017 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3018 disable = 0x00;
3019 } else {
3020 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3021 enable = 0x00;
3023 } else {
3024 enable = Value & ~OldValue;
3025 disable = ~Value & OldValue;
3028 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
3029 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
3030 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
3031 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
3032 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
3033 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
3035 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
3036 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
3037 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
3038 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
3039 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
3040 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
3042 /** update clipping status */
3043 if (enable) {
3044 This->stateBlock->clip_status.ClipUnion = 0;
3045 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
3046 } else {
3047 This->stateBlock->clip_status.ClipUnion = 0;
3048 This->stateBlock->clip_status.ClipIntersection = 0;
3051 break;
3053 case WINED3DRS_BLENDOP :
3055 int glParm = GL_FUNC_ADD;
3057 switch ((D3DBLENDOP) Value) {
3058 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
3059 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
3060 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3061 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
3062 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
3063 default:
3064 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
3066 TRACE("glBlendEquation(%x)\n", glParm);
3067 glBlendEquation(glParm);
3068 checkGLcall("glBlendEquation");
3070 break;
3072 case WINED3DRS_TEXTUREFACTOR :
3074 unsigned int i;
3076 /* Note the texture color applies to all textures whereas
3077 GL_TEXTURE_ENV_COLOR applies to active only */
3078 float col[4];
3079 D3DCOLORTOGLFLOAT4(Value, col);
3080 /* Set the default alpha blend color */
3081 glBlendColor(col[0], col[1], col[2], col[3]);
3082 checkGLcall("glBlendColor");
3084 /* And now the default texture color as well */
3085 for (i = 0; i < GL_LIMITS(textures); i++) {
3087 /* Note the D3DRS value applies to all textures, but GL has one
3088 per texture, so apply it now ready to be used! */
3089 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3090 GLACTIVETEXTURE(i);
3091 } else if (i>0) {
3092 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3095 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3096 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3099 break;
3101 case WINED3DRS_SPECULARENABLE :
3103 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3104 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3105 specular color. This is wrong:
3106 Separate specular color means the specular colour is maintained separately, whereas
3107 single color means it is merged in. However in both cases they are being used to
3108 some extent.
3109 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3110 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3111 running 1.4 yet!
3113 if (Value) {
3114 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3115 checkGLcall("glMaterialfv");
3116 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3117 glEnable(GL_COLOR_SUM_EXT);
3118 } else {
3119 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3121 checkGLcall("glEnable(GL_COLOR_SUM)");
3122 } else {
3123 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3125 /* for the case of enabled lighting: */
3126 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3127 checkGLcall("glMaterialfv");
3129 /* for the case of disabled lighting: */
3130 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3131 glDisable(GL_COLOR_SUM_EXT);
3132 } else {
3133 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3135 checkGLcall("glDisable(GL_COLOR_SUM)");
3138 break;
3140 case WINED3DRS_STENCILENABLE :
3141 if (Value) {
3142 glEnable(GL_STENCIL_TEST);
3143 checkGLcall("glEnable GL_STENCIL_TEST");
3144 } else {
3145 glDisable(GL_STENCIL_TEST);
3146 checkGLcall("glDisable GL_STENCIL_TEST");
3148 break;
3150 case WINED3DRS_STENCILFUNC :
3152 GLint func;
3153 GLint ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3154 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3156 func = GL_ALWAYS;
3157 switch ((D3DCMPFUNC)Value) {
3158 case D3DCMP_NEVER: func = GL_NEVER; break;
3159 case D3DCMP_LESS: func = GL_LESS; break;
3160 case D3DCMP_EQUAL: func = GL_EQUAL; break;
3161 case D3DCMP_LESSEQUAL: func = GL_LEQUAL; break;
3162 case D3DCMP_GREATER: func = GL_GREATER; break;
3163 case D3DCMP_NOTEQUAL: func = GL_NOTEQUAL; break;
3164 case D3DCMP_GREATEREQUAL: func = GL_GEQUAL; break;
3165 case D3DCMP_ALWAYS: func = GL_ALWAYS; break;
3166 default:
3167 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3169 This->stencilfunc = func;
3170 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3171 #if 0 /* Don't use OpenGL 2.0 calls for now */
3172 if(GL_EXTCALL(glStencilFuncSeparate)) {
3173 GL_EXTCALL(glStencilFuncSeparate(GL_FRONT, func, ref, mask));
3174 checkGLcall("glStencilFuncSeparate(GL_FRONT,...)");
3176 else
3177 #endif
3178 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3179 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3180 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3181 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
3182 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
3183 glStencilFunc(func, ref, mask);
3184 checkGLcall("glStencilFunc(...)");
3186 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3187 GL_EXTCALL(glStencilFuncSeparateATI(GL_FRONT, func, ref, mask));
3188 checkGLcall("glStencilFuncSeparateATI(GL_FRONT,...)");
3189 } else {
3190 TRACE("Separate stencil function not supported on this version of opengl");
3191 glStencilFunc(func, ref, mask);
3192 checkGLcall("glStencilFunc(...)");
3194 } else {
3195 glStencilFunc(func, ref, mask);
3196 checkGLcall("glStencilFunc(...)");
3198 break;
3200 case WINED3DRS_STENCILREF :
3202 int glParm = This->stencilfunc;
3203 int ref = 0;
3204 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3206 ref = Value;
3207 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3208 glStencilFunc(glParm, ref, mask);
3209 checkGLcall("glStencilFunc");
3211 break;
3213 case WINED3DRS_STENCILMASK :
3215 int glParm = This->stencilfunc;
3216 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3217 GLuint mask = Value;
3219 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3220 glStencilFunc(glParm, ref, mask);
3221 checkGLcall("glStencilFunc");
3223 break;
3225 case WINED3DRS_STENCILFAIL :
3226 case WINED3DRS_STENCILZFAIL :
3227 case WINED3DRS_STENCILPASS :
3229 GLint stencilFail;
3230 GLint depthFail;
3231 GLint stencilPass;
3233 GLint action = StencilOp(Value);
3235 glGetIntegerv(GL_STENCIL_FAIL, &stencilFail);
3236 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &depthFail);
3237 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &stencilPass);
3239 if(WINED3DRS_STENCILFAIL == State) {
3240 stencilFail = action;
3242 else if(WINED3DRS_STENCILZFAIL == State) {
3243 depthFail = action;
3245 else if(WINED3DRS_STENCILPASS == State) {
3246 stencilPass = action;
3249 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3250 #if 0 /* Don't use OpenGL 2.0 calls for now */
3251 if(GL_EXTCALL(glStencilOpSeparate)) {
3252 GL_EXTCALL(glStencilOpSeparate(GL_FRONT, stencilFail, depthFail, stencilPass));
3253 checkGLcall("glStencilOpSeparate(GL_FRONT,...)");
3255 else
3256 #endif
3257 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3258 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3259 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3260 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
3261 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
3262 glStencilOp(stencilFail, depthFail, stencilPass);
3263 checkGLcall("glStencilOp(...)");
3265 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3266 GL_EXTCALL(glStencilOpSeparateATI(GL_FRONT, stencilFail, depthFail, stencilPass));
3267 checkGLcall("glStencilOpSeparateATI(GL_FRONT,...)");
3268 } else {
3269 TRACE("Separate stencil operation not supported on this version of opengl");
3270 glStencilOp(stencilFail, depthFail, stencilPass);
3271 checkGLcall("glStencilOp(...)");
3273 } else {
3274 glStencilOp(stencilFail, depthFail, stencilPass);
3275 checkGLcall("glStencilOp(...)");
3277 break;
3279 case WINED3DRS_STENCILWRITEMASK :
3281 glStencilMask(Value);
3282 TRACE("glStencilMask(%lu)\n", Value);
3283 checkGLcall("glStencilMask");
3285 break;
3287 case WINED3DRS_FOGENABLE :
3289 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
3290 glEnable(GL_FOG);
3291 checkGLcall("glEnable GL_FOG");
3292 } else {
3293 glDisable(GL_FOG);
3294 checkGLcall("glDisable GL_FOG");
3297 break;
3299 case WINED3DRS_RANGEFOGENABLE :
3301 if (Value) {
3302 TRACE("Enabled RANGEFOG");
3303 } else {
3304 TRACE("Disabled RANGEFOG");
3307 break;
3309 case WINED3DRS_FOGCOLOR :
3311 float col[4];
3312 D3DCOLORTOGLFLOAT4(Value, col);
3313 /* Set the default alpha blend color */
3314 glFogfv(GL_FOG_COLOR, &col[0]);
3315 checkGLcall("glFog GL_FOG_COLOR");
3317 break;
3319 case WINED3DRS_FOGTABLEMODE :
3321 glHint(GL_FOG_HINT, GL_NICEST);
3322 switch (Value) {
3323 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3324 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3325 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3326 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3327 default:
3328 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3330 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3331 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3334 break;
3336 case WINED3DRS_FOGVERTEXMODE :
3338 glHint(GL_FOG_HINT, GL_FASTEST);
3339 switch (Value) {
3340 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3341 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3342 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3343 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3344 default:
3345 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3347 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3348 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
3351 break;
3353 case WINED3DRS_FOGSTART :
3355 tmpvalue.d = Value;
3356 glFogfv(GL_FOG_START, &tmpvalue.f);
3357 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3358 TRACE("Fog Start == %f\n", tmpvalue.f);
3360 break;
3362 case WINED3DRS_FOGEND :
3364 tmpvalue.d = Value;
3365 glFogfv(GL_FOG_END, &tmpvalue.f);
3366 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3367 TRACE("Fog End == %f\n", tmpvalue.f);
3369 break;
3371 case WINED3DRS_FOGDENSITY :
3373 tmpvalue.d = Value;
3374 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3375 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3377 break;
3379 case WINED3DRS_VERTEXBLEND :
3381 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3382 TRACE("Vertex Blending state to %ld\n", Value);
3384 break;
3386 case WINED3DRS_TWEENFACTOR :
3388 tmpvalue.d = Value;
3389 This->updateStateBlock->tween_factor = tmpvalue.f;
3390 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3392 break;
3394 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
3396 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3398 break;
3400 case WINED3DRS_COLORVERTEX :
3401 case WINED3DRS_DIFFUSEMATERIALSOURCE :
3402 case WINED3DRS_SPECULARMATERIALSOURCE :
3403 case WINED3DRS_AMBIENTMATERIALSOURCE :
3404 case WINED3DRS_EMISSIVEMATERIALSOURCE :
3406 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3408 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3409 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3410 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3411 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3412 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3413 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3415 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3416 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3417 Parm = GL_AMBIENT_AND_DIFFUSE;
3418 } else {
3419 Parm = GL_DIFFUSE;
3421 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3422 Parm = GL_AMBIENT;
3423 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3424 Parm = GL_EMISSION;
3425 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3426 Parm = GL_SPECULAR;
3427 } else {
3428 Parm = -1;
3431 if (Parm == -1) {
3432 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3433 } else {
3434 This->tracking_color = NEEDS_TRACKING;
3435 This->tracking_parm = Parm;
3438 } else {
3439 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3442 break;
3444 case WINED3DRS_LINEPATTERN :
3446 union {
3447 DWORD d;
3448 D3DLINEPATTERN lp;
3449 } tmppattern;
3450 tmppattern.d = Value;
3452 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3454 if (tmppattern.lp.wRepeatFactor) {
3455 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3456 checkGLcall("glLineStipple(repeat, linepattern)");
3457 glEnable(GL_LINE_STIPPLE);
3458 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3459 } else {
3460 glDisable(GL_LINE_STIPPLE);
3461 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3464 break;
3466 case WINED3DRS_ZBIAS : /* D3D8 only */
3468 if (Value) {
3469 tmpvalue.d = Value;
3470 TRACE("ZBias value %f\n", tmpvalue.f);
3471 glPolygonOffset(0, -tmpvalue.f);
3472 checkGLcall("glPolygonOffset(0, -Value)");
3473 glEnable(GL_POLYGON_OFFSET_FILL);
3474 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3475 glEnable(GL_POLYGON_OFFSET_LINE);
3476 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3477 glEnable(GL_POLYGON_OFFSET_POINT);
3478 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3479 } else {
3480 glDisable(GL_POLYGON_OFFSET_FILL);
3481 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3482 glDisable(GL_POLYGON_OFFSET_LINE);
3483 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3484 glDisable(GL_POLYGON_OFFSET_POINT);
3485 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3488 break;
3490 case WINED3DRS_NORMALIZENORMALS :
3491 if (Value) {
3492 glEnable(GL_NORMALIZE);
3493 checkGLcall("glEnable(GL_NORMALIZE);");
3494 } else {
3495 glDisable(GL_NORMALIZE);
3496 checkGLcall("glDisable(GL_NORMALIZE);");
3498 break;
3500 case WINED3DRS_POINTSIZE :
3501 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
3502 tmpvalue.d = Value;
3503 TRACE("Set point size to %f\n", tmpvalue.f);
3504 glPointSize(tmpvalue.f);
3505 checkGLcall("glPointSize(...);");
3506 break;
3508 case WINED3DRS_POINTSIZE_MIN :
3509 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3510 tmpvalue.d = Value;
3511 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3512 checkGLcall("glPointParameterfEXT(...);");
3513 } else {
3514 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3516 break;
3518 case WINED3DRS_POINTSIZE_MAX :
3519 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3520 tmpvalue.d = Value;
3521 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3522 checkGLcall("glPointParameterfEXT(...);");
3523 } else {
3524 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3526 break;
3528 case WINED3DRS_POINTSCALE_A :
3529 case WINED3DRS_POINTSCALE_B :
3530 case WINED3DRS_POINTSCALE_C :
3531 case WINED3DRS_POINTSCALEENABLE :
3534 * POINTSCALEENABLE controls how point size value is treated. If set to
3535 * true, the point size is scaled with respect to height of viewport.
3536 * When set to false point size is in pixels.
3538 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
3541 /* Default values */
3542 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3545 * Minimum valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
3546 * This means that OpenGL will clamp really small point sizes to 1.0f.
3547 * To correct for this we need to multiply by the scale factor when sizes
3548 * are less than 1.0f. scale_factor = 1.0f / point_size.
3550 GLfloat pointSize = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSIZE]);
3551 if(pointSize > 0.0f) {
3552 GLfloat scaleFactor;
3554 if(pointSize < 1.0f) {
3555 scaleFactor = pointSize * pointSize;
3556 } else {
3557 scaleFactor = 1.0f;
3560 if(This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3561 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]) /
3562 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3563 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]) /
3564 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3565 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) /
3566 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3570 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
3571 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
3572 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
3574 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3575 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3576 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
3577 } else {
3578 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
3580 break;
3582 case WINED3DRS_COLORWRITEENABLE :
3584 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3585 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3586 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3587 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3588 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3589 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3590 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3591 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3592 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3593 checkGLcall("glColorMask(...)");
3595 break;
3597 case WINED3DRS_LOCALVIEWER :
3599 GLint state = (Value) ? 1 : 0;
3600 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3601 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3603 break;
3605 case WINED3DRS_LASTPIXEL :
3607 if (Value) {
3608 TRACE("Last Pixel Drawing Enabled\n");
3609 } else {
3610 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3613 break;
3615 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3617 if (Value) {
3618 TRACE("Software Processing Enabled\n");
3619 } else {
3620 TRACE("Software Processing Disabled\n");
3623 break;
3625 /** not supported */
3626 case WINED3DRS_ZVISIBLE :
3628 LEAVE_GL();
3629 return WINED3DERR_INVALIDCALL;
3631 case WINED3DRS_POINTSPRITEENABLE :
3633 /* TODO: NV_POINT_SPRITE */
3634 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
3635 TRACE("Point sprites not supported\n");
3636 break;
3640 * Point sprites are always enabled. Value controls texture coordinate
3641 * replacement mode. Must be set true for point sprites to use
3642 * textures.
3644 glEnable(GL_POINT_SPRITE_ARB);
3645 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
3647 if (Value) {
3648 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
3649 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, TRUE)");
3650 } else {
3651 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, FALSE);
3652 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, FALSE)");
3654 break;
3656 case WINED3DRS_EDGEANTIALIAS :
3658 if(Value) {
3659 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3660 glEnable(GL_BLEND);
3661 checkGLcall("glEnable(GL_BLEND)");
3662 glEnable(GL_LINE_SMOOTH);
3663 checkGLcall("glEnable(GL_LINE_SMOOTH)");
3664 } else {
3665 glDisable(GL_BLEND);
3666 checkGLcall("glDisable(GL_BLEND)");
3667 glDisable(GL_LINE_SMOOTH);
3668 checkGLcall("glDisable(GL_LINE_SMOOTH)");
3670 break;
3672 case WINED3DRS_WRAP0 :
3673 case WINED3DRS_WRAP1 :
3674 case WINED3DRS_WRAP2 :
3675 case WINED3DRS_WRAP3 :
3676 case WINED3DRS_WRAP4 :
3677 case WINED3DRS_WRAP5 :
3678 case WINED3DRS_WRAP6 :
3679 case WINED3DRS_WRAP7 :
3680 case WINED3DRS_WRAP8 :
3681 case WINED3DRS_WRAP9 :
3682 case WINED3DRS_WRAP10 :
3683 case WINED3DRS_WRAP11 :
3684 case WINED3DRS_WRAP12 :
3685 case WINED3DRS_WRAP13 :
3686 case WINED3DRS_WRAP14 :
3687 case WINED3DRS_WRAP15 :
3689 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
3690 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
3691 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
3692 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
3693 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
3695 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
3697 TRACE("(%p)->(%s,%ld) Texture wraping not yet supported\n",This, debug_d3drenderstate(State), Value);
3698 break;
3699 case WINED3DRS_MULTISAMPLEANTIALIAS :
3701 if (!GL_SUPPORT(ARB_MULTISAMPLE)) {
3702 TRACE("Multisample antialiasing not supported\n");
3703 break;
3706 if(Value) {
3707 glEnable(GL_MULTISAMPLE_ARB);
3708 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
3709 } else {
3710 glDisable(GL_MULTISAMPLE_ARB);
3711 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
3713 break;
3715 case WINED3DRS_SCISSORTESTENABLE :
3717 if(Value) {
3718 glEnable(GL_SCISSOR_TEST);
3719 checkGLcall("glEnable(GL_SCISSOR_TEST)");
3720 } else {
3721 glDisable(GL_SCISSOR_TEST);
3722 checkGLcall("glDisable(GL_SCISSOR_TEST)");
3724 break;
3726 case WINED3DRS_SLOPESCALEDEPTHBIAS :
3728 if(Value) {
3729 tmpvalue.d = Value;
3730 glEnable(GL_POLYGON_OFFSET_FILL);
3731 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
3732 glPolygonOffset(tmpvalue.f, *((float*)&This->stateBlock->renderState[WINED3DRS_DEPTHBIAS]));
3733 checkGLcall("glPolygonOffset(...)");
3734 } else {
3735 glDisable(GL_POLYGON_OFFSET_FILL);
3736 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
3738 break;
3740 case WINED3DRS_ANTIALIASEDLINEENABLE :
3742 if(Value) {
3743 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3744 glEnable(GL_BLEND);
3745 checkGLcall("glEnable(GL_BLEND)");
3746 glEnable(GL_LINE_SMOOTH);
3747 checkGLcall("glEnable(GL_LINE_SMOOTH)");
3748 } else {
3749 glDisable(GL_BLEND);
3750 checkGLcall("glDisable(GL_BLEND)");
3751 glDisable(GL_LINE_SMOOTH);
3752 checkGLcall("glDisable(GL_LINE_SMOOTH)");
3754 break;
3756 case WINED3DRS_MULTISAMPLEMASK :
3757 case WINED3DRS_PATCHEDGESTYLE :
3758 case WINED3DRS_PATCHSEGMENTS :
3759 case WINED3DRS_DEBUGMONITORTOKEN :
3760 case WINED3DRS_POSITIONORDER :
3761 case WINED3DRS_NORMALORDER :
3762 /* Direct3D9 render states */
3763 case WINED3DRS_MINTESSELLATIONLEVEL :
3764 case WINED3DRS_MAXTESSELLATIONLEVEL :
3765 case WINED3DRS_ADAPTIVETESS_X :
3766 case WINED3DRS_ADAPTIVETESS_Y :
3767 case WINED3DRS_ADAPTIVETESS_Z :
3768 case WINED3DRS_ADAPTIVETESS_W :
3769 case WINED3DRS_ENABLEADAPTIVETESSELLATION :
3771 FIXME("(%p)->(%s,%ld) not handled yet\n", This, debug_d3drenderstate(State), Value);
3772 break;
3774 case WINED3DRS_TWOSIDEDSTENCILMODE :
3776 if(Value) {
3777 TRACE("Two-sided stencil mode enabled\n");
3778 } else {
3779 TRACE("Two-sided stencil mode disabled\n");
3781 break;
3783 case WINED3DRS_CCW_STENCILFAIL :
3784 case WINED3DRS_CCW_STENCILZFAIL :
3785 case WINED3DRS_CCW_STENCILPASS :
3787 GLint stencilFail;
3788 GLint depthFail;
3789 GLint stencilPass;
3791 GLint action = StencilOp(Value);
3793 glGetIntegerv(GL_STENCIL_BACK_FAIL, &stencilFail);
3794 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &depthFail);
3795 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS, &stencilPass);
3797 if(WINED3DRS_CCW_STENCILFAIL == State) {
3798 stencilFail = action;
3800 else if(WINED3DRS_CCW_STENCILZFAIL == State) {
3801 depthFail = action;
3803 else if(WINED3DRS_CCW_STENCILPASS == State) {
3804 stencilPass = action;
3807 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3808 #if 0 /* Don't use OpenGL 2.0 calls for now */
3809 if(GL_EXTCALL(glStencilOpSeparate)) {
3810 GL_EXTCALL(glStencilOpSeparate(GL_BACK, stencilFail, depthFail, stencilPass));
3811 checkGLcall("glStencilOpSeparate(GL_BACK,...)");
3813 else
3814 #endif
3815 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3816 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3817 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3818 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
3819 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
3820 glStencilOp(stencilFail, depthFail, stencilPass);
3821 checkGLcall("glStencilOp(...)");
3823 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3824 GL_EXTCALL(glStencilOpSeparateATI(GL_BACK, stencilFail, depthFail, stencilPass));
3825 checkGLcall("glStencilOpSeparateATI(GL_BACK,...)");
3826 } else {
3827 TRACE("Separate stencil operation not supported on this version of opengl");
3828 glStencilOp(stencilFail, depthFail, stencilPass);
3829 checkGLcall("glStencilOp(...)");
3831 } else {
3832 glStencilOp(stencilFail, depthFail, stencilPass);
3833 checkGLcall("glStencilOp(...)");
3835 break;
3837 case WINED3DRS_CCW_STENCILFUNC :
3839 GLint func;
3840 GLint ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3841 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3843 func = GL_ALWAYS;
3844 switch ((D3DCMPFUNC)Value) {
3845 case D3DCMP_NEVER: func = GL_NEVER; break;
3846 case D3DCMP_LESS: func = GL_LESS; break;
3847 case D3DCMP_EQUAL: func = GL_EQUAL; break;
3848 case D3DCMP_LESSEQUAL: func = GL_LEQUAL; break;
3849 case D3DCMP_GREATER: func = GL_GREATER; break;
3850 case D3DCMP_NOTEQUAL: func = GL_NOTEQUAL; break;
3851 case D3DCMP_GREATEREQUAL: func = GL_GEQUAL; break;
3852 case D3DCMP_ALWAYS: func = GL_ALWAYS; break;
3853 default:
3854 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3856 This->stencilfunc = func;
3857 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3858 #if 0 /* Don't use OpenGL 2.0 calls for now */
3859 if(GL_EXTCALL(glStencilFuncSeparate)) {
3860 GL_EXTCALL(glStencilFuncSeparate(GL_BACK, func, ref, mask));
3861 checkGLcall("glStencilFuncSeparate(GL_BACK,...)");
3863 else
3864 #endif
3865 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3866 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3867 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3868 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
3869 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
3870 glStencilFunc(func, ref, mask);
3871 checkGLcall("glStencilFunc(...)");
3873 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3874 GL_EXTCALL(glStencilFuncSeparateATI(GL_BACK, func, ref, mask));
3875 checkGLcall("glStencilFuncSeparateATI(GL_BACK,...)");
3876 } else {
3877 TRACE("Separate stencil function not supported on this version of opengl");
3878 glStencilFunc(func, ref, mask);
3879 checkGLcall("glStencilFunc(...)");
3881 } else {
3882 glStencilFunc(func, ref, mask);
3883 checkGLcall("glStencilFunc(...)");
3885 break;
3887 case WINED3DRS_COLORWRITEENABLE1 :
3888 case WINED3DRS_COLORWRITEENABLE2 :
3889 case WINED3DRS_COLORWRITEENABLE3 :
3890 case WINED3DRS_BLENDFACTOR :
3891 case WINED3DRS_SRGBWRITEENABLE :
3893 FIXME("(%p)->(%s,%ld) not handled yet\n", This, debug_d3drenderstate(State), Value);
3894 break;
3896 case WINED3DRS_DEPTHBIAS :
3898 if(Value) {
3899 tmpvalue.d = Value;
3900 glEnable(GL_POLYGON_OFFSET_FILL);
3901 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
3902 glPolygonOffset(*((float*)&This->stateBlock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS]), tmpvalue.f);
3903 checkGLcall("glPolygonOffset(...)");
3904 } else {
3905 glDisable(GL_POLYGON_OFFSET_FILL);
3906 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
3908 break;
3910 case WINED3DRS_SEPARATEALPHABLENDENABLE :
3911 case WINED3DRS_SRCBLENDALPHA :
3912 case WINED3DRS_DESTBLENDALPHA :
3913 case WINED3DRS_BLENDOPALPHA :
3914 FIXME("(%p)->(%s,%ld) not handled yet\n", This, debug_d3drenderstate(State), Value);
3915 break;
3916 default:
3917 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3920 LEAVE_GL();
3922 return WINED3D_OK;
3925 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3926 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3927 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3928 *pValue = This->stateBlock->renderState[State];
3929 return WINED3D_OK;
3932 /*****
3933 * Get / Set Sampler States
3934 * TODO: Verify against dx9 definitions
3935 *****/
3937 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3938 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3940 * SetSampler is designed to allow for more than the standard up to 8 textures
3941 * and Geforce has stopped supporting more than 6 standard textures in openGL.
3942 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3944 * http://developer.nvidia.com/object/General_FAQ.html#t6
3946 * There are two new settings for GForce
3947 * the sampler one:
3948 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3949 * and the texture one:
3950 * GL_MAX_TEXTURE_COORDS_ARB.
3951 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3952 ******************/
3953 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
3954 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
3956 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
3957 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE, Sampler, Type);
3958 return WINED3DERR_INVALIDCALL;
3960 TRACE("Setting sampler %ld %d to %ld\n", Sampler, Type, Value);
3961 This->updateStateBlock->samplerState[Sampler][Type] = Value;
3962 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
3963 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
3965 /* Handle recording of state blocks */
3966 if (This->isRecordingState) {
3967 TRACE("Recording... not performing anything\n");
3968 return WINED3D_OK;
3971 return WINED3D_OK;
3974 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3975 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3976 /** TODO: check that sampler is in range **/
3977 *Value = This->updateStateBlock->samplerState[Sampler][Type];
3978 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
3980 return WINED3D_OK;
3983 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3984 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3985 ENTER_GL();
3987 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3988 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3989 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3990 LEAVE_GL();
3992 return WINED3D_OK;
3995 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3996 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3997 GLint scissorBox[4];
3999 ENTER_GL();
4000 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4001 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
4002 pRect->left = scissorBox[1];
4003 pRect->top = scissorBox[2];
4004 pRect->right = scissorBox[1] + scissorBox[3];
4005 pRect->bottom = scissorBox[2] + scissorBox[4];
4006 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4007 LEAVE_GL();
4008 return WINED3D_OK;
4011 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
4012 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4013 IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
4015 TRACE("(%p) : pDecl=%p\n", This, pDecl);
4017 This->updateStateBlock->vertexDecl = pDecl;
4018 This->updateStateBlock->changed.vertexDecl = TRUE;
4019 This->updateStateBlock->set.vertexDecl = TRUE;
4021 if (This->isRecordingState) {
4022 TRACE("Recording... not performing anything\n");
4025 if (NULL != pDecl) {
4026 IWineD3DVertexDeclaration_AddRef(pDecl);
4028 if (NULL != oldDecl) {
4029 IWineD3DVertexDeclaration_Release(oldDecl);
4031 return WINED3D_OK;
4034 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
4035 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4037 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
4039 *ppDecl = This->stateBlock->vertexDecl;
4040 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
4041 return WINED3D_OK;
4044 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
4045 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4046 IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
4048 This->updateStateBlock->vertexShader = pShader;
4049 This->updateStateBlock->changed.vertexShader = TRUE;
4050 This->updateStateBlock->set.vertexShader = TRUE;
4052 if (This->isRecordingState) {
4053 TRACE("Recording... not performing anything\n");
4056 if (NULL != pShader) {
4057 IWineD3DVertexShader_AddRef(pShader);
4059 if (NULL != oldShader) {
4060 IWineD3DVertexShader_Release(oldShader);
4063 if (pShader != NULL && ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration != NULL) {
4064 TRACE("(%p) : setting vertexDeclaration(%p)\n", This, ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration);
4065 IWineD3DDevice_SetVertexDeclaration(iface, ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration);
4068 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4070 * TODO: merge HAL shaders context switching from prototype
4072 return WINED3D_OK;
4075 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
4076 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4078 if (NULL == ppShader) {
4079 return WINED3DERR_INVALIDCALL;
4081 *ppShader = This->stateBlock->vertexShader;
4082 if( NULL != *ppShader)
4083 IWineD3DVertexShader_AddRef(*ppShader);
4085 TRACE("(%p) : returning %p\n", This, *ppShader);
4086 return WINED3D_OK;
4089 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4090 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4092 int i;
4093 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4095 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4096 iface, dstData, srcData, type, start, count, registersize);
4098 if (type != WINESHADERCNST_NONE) {
4099 if (srcData == NULL || cnt < 0) {
4100 return WINED3DERR_INVALIDCALL;
4103 CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
4106 for (i = start; i < cnt + start; ++i) {
4107 This->updateStateBlock->changed.vertexShaderConstants[i] = TRUE;
4108 This->updateStateBlock->set.vertexShaderConstants[i] = TRUE;
4109 This->updateStateBlock->vertexShaderConstantT[i] = type;
4112 return WINED3D_OK;
4115 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4116 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4118 int i;
4119 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4121 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4122 iface, dstData, srcData, type, start, count, registersize);
4124 /* Verify that the requested shader constant was populated with the correct type */
4125 for (i = start; i < cnt + start; ++i) {
4126 if (This->updateStateBlock->vertexShaderConstantT[i] != type) {
4127 TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning WINED3DERR_INVALIDCALL\n",
4128 This, type, This->updateStateBlock->vertexShaderConstantT[i]);
4129 return WINED3DERR_INVALIDCALL;
4133 if (dstData == NULL || cnt < 0) {
4134 return WINED3DERR_INVALIDCALL;
4137 CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
4139 return WINED3D_OK;
4142 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
4143 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4145 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4146 This->updateStateBlock->vertexShaderConstantB,
4147 pConstantData,
4148 WINESHADERCNST_BOOL,
4149 StartRegister,
4150 BoolCount,
4151 sizeof(*pConstantData));
4154 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
4155 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4157 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4158 pConstantData,
4159 This->updateStateBlock->vertexShaderConstantB,
4160 WINESHADERCNST_BOOL,
4161 StartRegister,
4162 BoolCount,
4163 sizeof(*pConstantData));
4166 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
4167 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4169 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4170 This->updateStateBlock->vertexShaderConstantI,
4171 pConstantData,
4172 WINESHADERCNST_INTEGER,
4173 StartRegister,
4174 Vector4iCount,
4175 4 * sizeof(*pConstantData));
4178 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
4179 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4181 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4182 pConstantData,
4183 This->updateStateBlock->vertexShaderConstantI,
4184 WINESHADERCNST_INTEGER,
4185 StartRegister,
4186 Vector4iCount,
4187 4 * sizeof(*pConstantData));
4191 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
4192 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4194 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4195 This->updateStateBlock->vertexShaderConstantF,
4196 pConstantData,
4197 WINESHADERCNST_FLOAT,
4198 StartRegister,
4199 Vector4fCount,
4200 4 * sizeof(*pConstantData));
4203 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
4204 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4206 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4207 pConstantData,
4208 This->updateStateBlock->vertexShaderConstantF,
4209 WINESHADERCNST_FLOAT,
4210 StartRegister,
4211 Vector4fCount,
4212 4 * sizeof(*pConstantData));
4215 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
4216 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4217 NULL,
4218 NULL,
4219 WINESHADERCNST_NONE,
4220 StartRegister,
4221 VectorNCount,
4225 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
4226 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4227 IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader;
4228 This->updateStateBlock->pixelShader = pShader;
4229 This->updateStateBlock->changed.pixelShader = TRUE;
4230 This->updateStateBlock->set.pixelShader = TRUE;
4232 /* Handle recording of state blocks */
4233 if (This->isRecordingState) {
4234 TRACE("Recording... not performing anything\n");
4237 if (NULL != pShader) {
4238 IWineD3DPixelShader_AddRef(pShader);
4240 if (NULL != oldShader) {
4241 IWineD3DPixelShader_Release(oldShader);
4244 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4246 * TODO: merge HAL shaders context switching from prototype
4248 return WINED3D_OK;
4251 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
4252 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4254 if (NULL == ppShader) {
4255 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
4256 return WINED3DERR_INVALIDCALL;
4259 *ppShader = This->stateBlock->pixelShader;
4260 if (NULL != ppShader) {
4261 IWineD3DPixelShader_AddRef(*ppShader);
4263 TRACE("(%p) : returning %p\n", This, *ppShader);
4264 return WINED3D_OK;
4267 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4268 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4270 int i;
4271 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4273 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4274 iface, dstData, srcData, type, start, count, registersize);
4276 if (type != WINESHADERCNST_NONE) {
4277 if (srcData == NULL || cnt < 0) {
4278 return WINED3DERR_INVALIDCALL;
4281 CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
4284 for (i = start; i < cnt + start; ++i) {
4285 This->updateStateBlock->changed.pixelShaderConstants[i] = TRUE;
4286 This->updateStateBlock->set.pixelShaderConstants[i] = TRUE;
4287 This->updateStateBlock->pixelShaderConstantT[i] = type;
4290 return WINED3D_OK;
4293 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4294 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4296 int i;
4297 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4299 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4300 iface, dstData, srcData, type, start, count, registersize);
4302 /* Verify that the requested shader constant was populated with the correct type */
4303 for (i = start; i < cnt + start; ++i) {
4304 if (This->updateStateBlock->pixelShaderConstantT[i] != type) {
4305 TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning WINED3DERR_INVALIDCALL\n",
4306 This, type, This->updateStateBlock->pixelShaderConstantT[i]);
4307 return WINED3DERR_INVALIDCALL;
4311 if (dstData == NULL || cnt < 0) {
4312 return WINED3DERR_INVALIDCALL;
4315 CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
4317 return WINED3D_OK;
4320 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
4321 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4323 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4324 This->updateStateBlock->pixelShaderConstantB,
4325 pConstantData,
4326 WINESHADERCNST_BOOL,
4327 StartRegister,
4328 BoolCount,
4329 sizeof(*pConstantData));
4332 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
4333 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4335 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4336 pConstantData,
4337 This->updateStateBlock->pixelShaderConstantB,
4338 WINESHADERCNST_BOOL,
4339 StartRegister,
4340 BoolCount,
4341 sizeof(*pConstantData));
4344 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
4345 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4347 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4348 This->updateStateBlock->pixelShaderConstantI,
4349 pConstantData,
4350 WINESHADERCNST_INTEGER,
4351 StartRegister,
4352 Vector4iCount,
4353 4 * sizeof(*pConstantData));
4356 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
4357 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4359 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4360 pConstantData,
4361 This->updateStateBlock->pixelShaderConstantI,
4362 WINESHADERCNST_INTEGER,
4363 StartRegister,
4364 Vector4iCount,
4365 4 * sizeof(*pConstantData));
4368 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
4369 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4371 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4372 This->updateStateBlock->pixelShaderConstantF,
4373 pConstantData,
4374 WINESHADERCNST_FLOAT,
4375 StartRegister,
4376 Vector4fCount,
4377 4 * sizeof(*pConstantData));
4380 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
4381 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4383 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4384 pConstantData,
4385 This->updateStateBlock->pixelShaderConstantF,
4386 WINESHADERCNST_FLOAT,
4387 StartRegister,
4388 Vector4fCount,
4389 4 * sizeof(*pConstantData));
4392 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
4393 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4394 NULL,
4395 NULL,
4396 WINESHADERCNST_NONE,
4397 StartRegister,
4398 VectorNCount,
4402 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
4403 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4404 FIXME("(%p) : stub\n", This);
4405 return WINED3D_OK;
4408 /*****
4409 * Apply / Get / Set Texture Stage States
4410 * TODO: Verify against dx9 definitions
4411 *****/
4413 /* NOTE: It's expected that this function is going to be called lots of times with the same stage active, so make it the callers responsibility to GLACTIVETEXTURE(Stage) for better state management. Set the correct Texture unit active before calling ApplyTextureStageState */
4414 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
4415 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4416 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
4417 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4419 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4421 /* Check that the stage is within limits */
4422 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4423 TRACE("Attempt to access invalid texture rejected\n");
4424 return;
4427 ENTER_GL();
4429 switch (Type) {
4430 case WINED3DTSS_ALPHAOP :
4431 case WINED3DTSS_COLOROP :
4432 /* nothing to do as moved to drawprim for now */
4433 break;
4434 case WINED3DTSS_ADDRESSW :
4435 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
4436 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
4437 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
4439 } else {
4440 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
4441 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
4442 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
4443 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
4445 #endif
4446 case WINED3DTSS_TEXCOORDINDEX :
4448 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
4450 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
4451 one flag, you can still specify an index value, which the system uses to
4452 determine the texture wrapping mode.
4453 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
4454 means use the vertex position (camera-space) as the input texture coordinates
4455 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
4456 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
4457 to the TEXCOORDINDEX value */
4460 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
4462 switch (Value & 0xFFFF0000) {
4463 case D3DTSS_TCI_PASSTHRU:
4464 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
4465 glDisable(GL_TEXTURE_GEN_S);
4466 glDisable(GL_TEXTURE_GEN_T);
4467 glDisable(GL_TEXTURE_GEN_R);
4468 glDisable(GL_TEXTURE_GEN_Q);
4469 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
4470 break;
4472 case D3DTSS_TCI_CAMERASPACEPOSITION:
4473 /* CameraSpacePosition means use the vertex position, transformed to camera space,
4474 as the input texture coordinates for this stage's texture transformation. This
4475 equates roughly to EYE_LINEAR */
4477 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4478 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4479 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4480 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4481 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4483 glMatrixMode(GL_MODELVIEW);
4484 glPushMatrix();
4485 glLoadIdentity();
4486 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4487 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4488 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4489 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4490 glPopMatrix();
4492 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
4493 glEnable(GL_TEXTURE_GEN_S);
4494 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4495 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4496 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4497 glEnable(GL_TEXTURE_GEN_T);
4498 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4499 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4500 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4501 glEnable(GL_TEXTURE_GEN_R);
4502 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4503 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4504 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4506 break;
4508 case D3DTSS_TCI_CAMERASPACENORMAL:
4510 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4511 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4512 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4513 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4514 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4515 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
4517 glMatrixMode(GL_MODELVIEW);
4518 glPushMatrix();
4519 glLoadIdentity();
4520 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4521 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4522 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4523 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4524 glPopMatrix();
4526 glEnable(GL_TEXTURE_GEN_S);
4527 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4528 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4529 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4530 glEnable(GL_TEXTURE_GEN_T);
4531 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4532 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4533 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4534 glEnable(GL_TEXTURE_GEN_R);
4535 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4536 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4537 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4540 break;
4542 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
4544 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4545 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4546 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4547 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4548 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4549 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
4551 glMatrixMode(GL_MODELVIEW);
4552 glPushMatrix();
4553 glLoadIdentity();
4554 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4555 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4556 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4557 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4558 glPopMatrix();
4560 glEnable(GL_TEXTURE_GEN_S);
4561 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4562 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4563 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4564 glEnable(GL_TEXTURE_GEN_T);
4565 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4566 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4567 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4568 glEnable(GL_TEXTURE_GEN_R);
4569 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4570 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4571 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4574 break;
4576 /* Unhandled types: */
4577 default:
4578 /* Todo: */
4579 /* ? disable GL_TEXTURE_GEN_n ? */
4580 glDisable(GL_TEXTURE_GEN_S);
4581 glDisable(GL_TEXTURE_GEN_T);
4582 glDisable(GL_TEXTURE_GEN_R);
4583 glDisable(GL_TEXTURE_GEN_Q);
4584 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
4585 break;
4588 break;
4590 /* Unhandled */
4591 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
4592 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);
4593 break;
4595 case WINED3DTSS_BUMPENVMAT00 :
4596 case WINED3DTSS_BUMPENVMAT01 :
4597 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
4598 break;
4599 case WINED3DTSS_BUMPENVMAT10 :
4600 case WINED3DTSS_BUMPENVMAT11 :
4601 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
4602 break;
4604 case WINED3DTSS_BUMPENVLSCALE :
4605 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4606 break;
4608 case WINED3DTSS_BUMPENVLOFFSET :
4609 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4610 break;
4612 case WINED3DTSS_RESULTARG :
4613 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4614 break;
4616 default:
4617 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
4618 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4621 LEAVE_GL();
4623 return;
4626 /*****
4627 * Get / Set Texture Stage States
4628 * TODO: Verify against dx9 definitions
4629 *****/
4630 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
4631 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4633 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4635 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4637 /* Reject invalid texture units */
4638 if (Stage >= GL_LIMITS(textures)) {
4639 TRACE("Attempt to access invalid texture rejected\n");
4640 return WINED3DERR_INVALIDCALL;
4643 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
4644 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
4645 This->updateStateBlock->textureState[Stage][Type] = Value;
4647 return WINED3D_OK;
4650 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4651 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4652 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4653 *pValue = This->updateStateBlock->textureState[Stage][Type];
4654 return WINED3D_OK;
4657 /*****
4658 * Get / Set Texture
4659 *****/
4660 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4662 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4663 IWineD3DBaseTexture *oldTexture;
4665 oldTexture = This->updateStateBlock->textures[Stage];
4666 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
4668 #if 0 /* TODO: check so vertex textures */
4669 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
4670 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
4671 return WINED3D_OK;
4673 #endif
4675 /* Reject invalid texture units */
4676 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4677 WARN("Attempt to access invalid texture rejected\n");
4678 return WINED3DERR_INVALIDCALL;
4681 if(pTexture != NULL) {
4682 /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH; The same is
4683 * the case for WINED3DPOOL_SYSTEMMEM textures unless WINED3DDEVCAPS_TEXTURESYSTEMMORY is set.
4684 * We don't check the caps as GetDeviceCaps is inefficient and we don't set the cap anyway.
4686 if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH || ((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SYSTEMMEM) {
4687 WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
4688 return WINED3DERR_INVALIDCALL;
4692 oldTexture = This->updateStateBlock->textures[Stage];
4693 TRACE("GL_LIMITS %d\n",GL_LIMITS(textures));
4694 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
4696 This->updateStateBlock->set.textures[Stage] = TRUE;
4697 This->updateStateBlock->changed.textures[Stage] = TRUE;
4698 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
4699 This->updateStateBlock->textures[Stage] = pTexture;
4701 /* Handle recording of state blocks */
4702 if (This->isRecordingState) {
4703 TRACE("Recording... not performing anything\n");
4704 return WINED3D_OK;
4707 /** NOTE: MSDN says that setTexture increases the reference count,
4708 * and the the application nust set the texture back to null (or have a leaky application),
4709 * This means we should pass the refcount up to the parent
4710 *******************************/
4711 if (NULL != This->updateStateBlock->textures[Stage]) {
4712 IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
4715 if (NULL != oldTexture) {
4716 IWineD3DBaseTexture_Release(oldTexture);
4719 return WINED3D_OK;
4722 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4723 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4724 TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
4726 /* Reject invalid texture units */
4727 if (Stage >= GL_LIMITS(textures)) {
4728 TRACE("Attempt to access invalid texture rejected\n");
4729 return WINED3DERR_INVALIDCALL;
4731 *ppTexture=This->updateStateBlock->textures[Stage];
4732 if (*ppTexture)
4733 IWineD3DBaseTexture_AddRef(*ppTexture);
4734 else
4735 return WINED3DERR_INVALIDCALL;
4736 return WINED3D_OK;
4739 /*****
4740 * Get Back Buffer
4741 *****/
4742 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
4743 IWineD3DSurface **ppBackBuffer) {
4744 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4745 IWineD3DSwapChain *swapChain;
4746 HRESULT hr;
4748 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4750 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4751 if (hr == WINED3D_OK) {
4752 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4753 IWineD3DSwapChain_Release(swapChain);
4754 } else {
4755 *ppBackBuffer = NULL;
4757 return hr;
4760 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4761 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4762 WARN("(%p) : stub, calling idirect3d for now\n", This);
4763 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4766 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
4767 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4768 IWineD3DSwapChain *swapChain;
4769 HRESULT hr;
4771 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4772 if (hr == WINED3D_OK) {
4773 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4774 IWineD3DSwapChain_Release(swapChain);
4775 } else {
4776 FIXME("(%p) Error getting display mode\n", This);
4778 return hr;
4780 /*****
4781 * Stateblock related functions
4782 *****/
4784 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4785 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4786 IWineD3DStateBlockImpl *object;
4787 TRACE("(%p)", This);
4789 if (This->isRecordingState) {
4790 return WINED3DERR_INVALIDCALL;
4793 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4794 if (NULL == object ) {
4795 FIXME("(%p)Error allocating memory for stateblock\n", This);
4796 return E_OUTOFMEMORY;
4798 TRACE("(%p) creted object %p\n", This, object);
4799 object->wineD3DDevice= This;
4800 /** FIXME: object->parent = parent; **/
4801 object->parent = NULL;
4802 object->blockType = WINED3DSBT_ALL;
4803 object->ref = 1;
4804 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
4806 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4807 This->updateStateBlock = object;
4808 This->isRecordingState = TRUE;
4810 TRACE("(%p) recording stateblock %p\n",This , object);
4811 return WINED3D_OK;
4814 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4815 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4817 if (!This->isRecordingState) {
4818 FIXME("(%p) not recording! returning error\n", This);
4819 *ppStateBlock = NULL;
4820 return WINED3DERR_INVALIDCALL;
4823 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4824 This->isRecordingState = FALSE;
4825 This->updateStateBlock = This->stateBlock;
4826 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4827 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4828 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4829 return WINED3D_OK;
4832 /*****
4833 * Scene related functions
4834 *****/
4835 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4836 /* At the moment we have no need for any functionality at the beginning
4837 of a scene */
4838 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4839 TRACE("(%p) : stub\n", This);
4840 return WINED3D_OK;
4843 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4844 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4845 TRACE("(%p)\n", This);
4846 ENTER_GL();
4847 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4848 glFlush();
4849 checkGLcall("glFlush");
4851 TRACE("End Scene\n");
4852 if(This->renderTarget != NULL) {
4854 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4855 IUnknown *targetContainer = NULL;
4856 if (WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
4857 || WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
4858 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
4859 /** always dirtify for now. we must find a better way to see that surface have been modified
4860 (Modifications should will only occur via draw-primitive, but we do need better locking
4861 switching to render-to-texture should remove the overhead though.
4863 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4864 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
4865 IWineD3DSurface_PreLoad(This->renderTarget);
4866 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4867 IUnknown_Release(targetContainer);
4870 This->sceneEnded = TRUE;
4871 LEAVE_GL();
4872 return WINED3D_OK;
4875 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4876 CONST RECT* pSourceRect, CONST RECT* pDestRect,
4877 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4878 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4879 IWineD3DSwapChain *swapChain = NULL;
4880 int i;
4881 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4883 TRACE("(%p) Presenting the frame\n", This);
4885 for(i = 0 ; i < swapchains ; i ++) {
4887 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4888 TRACE("presentinng chain %d, %p\n", i, swapChain);
4889 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4890 IWineD3DSwapChain_Release(swapChain);
4893 return WINED3D_OK;
4896 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4897 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4898 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4900 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4901 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4902 when the depth-buffer format does not contain stencil buffer information, this method fails. */
4903 GLbitfield glMask = 0;
4904 GLboolean old_ztest;
4905 GLfloat old_z_clear_value;
4906 GLint old_stencil_clear_value;
4907 GLfloat old_color_clear_value[4];
4908 unsigned int i;
4909 CONST D3DRECT* curRect;
4911 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4912 Count, pRects, Flags, Z, Stencil);
4914 ENTER_GL();
4916 glEnable(GL_SCISSOR_TEST);
4917 checkGLcall("glEnable GL_SCISSOR_TEST");
4919 if (Count > 0 && pRects) {
4920 curRect = pRects;
4921 } else {
4922 curRect = NULL;
4925 /* Only set the values up once, as they are not changing */
4926 if (Flags & D3DCLEAR_STENCIL) {
4927 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4928 glClearStencil(Stencil);
4929 checkGLcall("glClearStencil");
4930 glMask = glMask | GL_STENCIL_BUFFER_BIT;
4931 glStencilMask(0xFFFFFFFF);
4934 if (Flags & D3DCLEAR_ZBUFFER) {
4935 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4936 glDepthMask(GL_TRUE);
4937 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4938 glClearDepth(Z);
4939 checkGLcall("glClearDepth");
4940 glMask = glMask | GL_DEPTH_BUFFER_BIT;
4943 if (Flags & D3DCLEAR_TARGET) {
4944 TRACE("Clearing screen with glClear to color %lx\n", Color);
4945 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4946 glClearColor(D3DCOLOR_R(Color),
4947 D3DCOLOR_G(Color),
4948 D3DCOLOR_B(Color),
4949 D3DCOLOR_A(Color));
4950 checkGLcall("glClearColor");
4952 /* Clear ALL colors! */
4953 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4954 glMask = glMask | GL_COLOR_BUFFER_BIT;
4957 /* Now process each rect in turn */
4958 for (i = 0; i < Count || i == 0; i++) {
4960 if (curRect) {
4961 /* Note gl uses lower left, width/height */
4962 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4963 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4964 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4965 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4966 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4967 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4968 checkGLcall("glScissor");
4969 } else {
4970 glScissor(This->stateBlock->viewport.X,
4971 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
4972 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4973 This->stateBlock->viewport.Width,
4974 This->stateBlock->viewport.Height);
4975 checkGLcall("glScissor");
4978 /* Clear the selected rectangle (or full screen) */
4979 glClear(glMask);
4980 checkGLcall("glClear");
4982 /* Step to the next rectangle */
4983 if (curRect) curRect = curRect + sizeof(D3DRECT);
4986 /* Restore the old values (why..?) */
4987 if (Flags & D3DCLEAR_STENCIL) {
4988 glClearStencil(old_stencil_clear_value);
4989 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4991 if (Flags & D3DCLEAR_ZBUFFER) {
4992 glDepthMask(old_ztest);
4993 glClearDepth(old_z_clear_value);
4995 if (Flags & D3DCLEAR_TARGET) {
4996 glClearColor(old_color_clear_value[0],
4997 old_color_clear_value[1],
4998 old_color_clear_value[2],
4999 old_color_clear_value[3]);
5000 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
5001 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
5002 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
5003 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
5006 glDisable(GL_SCISSOR_TEST);
5007 checkGLcall("glDisable");
5008 LEAVE_GL();
5010 return WINED3D_OK;
5013 /*****
5014 * Drawing functions
5015 *****/
5016 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
5017 UINT PrimitiveCount) {
5019 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5020 This->stateBlock->streamIsUP = FALSE;
5022 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
5023 debug_d3dprimitivetype(PrimitiveType),
5024 StartVertex, PrimitiveCount);
5025 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
5026 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
5029 return WINED3D_OK;
5032 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
5033 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
5034 D3DPRIMITIVETYPE PrimitiveType,
5035 INT baseVIndex, UINT minIndex,
5036 UINT NumVertices, UINT startIndex, UINT primCount) {
5038 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5039 UINT idxStride = 2;
5040 IWineD3DIndexBuffer *pIB;
5041 WINED3DINDEXBUFFER_DESC IdxBufDsc;
5043 pIB = This->stateBlock->pIndexData;
5044 This->stateBlock->streamIsUP = FALSE;
5046 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
5047 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5048 minIndex, NumVertices, startIndex, baseVIndex, primCount);
5050 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
5051 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
5052 idxStride = 2;
5053 } else {
5054 idxStride = 4;
5057 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
5058 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
5060 return WINED3D_OK;
5063 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
5064 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
5065 UINT VertexStreamZeroStride) {
5066 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5068 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
5069 debug_d3dprimitivetype(PrimitiveType),
5070 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
5072 /* release the stream source */
5073 if (This->stateBlock->streamSource[0] != NULL) {
5074 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5077 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5078 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5079 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5080 This->stateBlock->streamIsUP = TRUE;
5082 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
5083 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
5084 /* stream zero settings set to null at end, as per the msdn
5085 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
5087 This->stateBlock->streamStride[0] = 0;
5088 This->stateBlock->streamSource[0] = NULL;
5090 /*stream zero settings set to null at end, as per the msdn */
5091 return WINED3D_OK;
5094 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
5095 UINT MinVertexIndex, UINT NumVertices,
5096 UINT PrimitiveCount, CONST void* pIndexData,
5097 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
5098 UINT VertexStreamZeroStride) {
5099 int idxStride;
5100 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5102 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
5103 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5104 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
5105 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
5107 if (IndexDataFormat == WINED3DFMT_INDEX16) {
5108 idxStride = 2;
5109 } else {
5110 idxStride = 4;
5113 /* release the stream and index data */
5114 if (This->stateBlock->streamSource[0] != NULL) {
5115 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5117 if (This->stateBlock->pIndexData) {
5118 IWineD3DIndexBuffer_Release(This->stateBlock->pIndexData);
5121 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5122 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5123 This->stateBlock->streamIsUP = TRUE;
5124 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5126 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
5127 /* stream zero settings set to null at end as per the msdn
5128 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
5131 /* stream zero settings set to null at end as per the msdn */
5132 This->stateBlock->streamSource[0] = NULL;
5133 This->stateBlock->streamStride[0] = 0;
5135 return WINED3D_OK;
5138 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
5139 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
5140 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5141 HRESULT hr = WINED3D_OK;
5142 WINED3DRESOURCETYPE sourceType;
5143 WINED3DRESOURCETYPE destinationType;
5144 int i ,levels;
5146 /* TODO: think about moving the code into IWineD3DBaseTexture */
5148 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
5150 /* verify that the source and destination textures aren't NULL */
5151 if (NULL == pSourceTexture || NULL == pDestinationTexture) {
5152 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
5153 This, pSourceTexture, pDestinationTexture);
5154 hr = WINED3DERR_INVALIDCALL;
5157 if (pSourceTexture == pDestinationTexture) {
5158 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
5159 This, pSourceTexture, pDestinationTexture);
5160 hr = WINED3DERR_INVALIDCALL;
5162 /* Verify that the source and destination textures are the same type */
5163 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
5164 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
5166 if (sourceType != destinationType) {
5167 WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
5168 This);
5169 hr = WINED3DERR_INVALIDCALL;
5172 /* check that both textures have the identical numbers of levels */
5173 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
5174 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
5175 hr = WINED3DERR_INVALIDCALL;
5178 if (WINED3D_OK == hr) {
5180 /* Make sure that the destination texture is loaded */
5181 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
5183 /* Update every surface level of the texture */
5184 levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
5186 switch (sourceType) {
5187 case WINED3DRTYPE_TEXTURE:
5189 IWineD3DSurface *srcSurface;
5190 IWineD3DSurface *destSurface;
5192 for (i = 0 ; i < levels ; ++i) {
5193 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture, i, &srcSurface);
5194 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
5195 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5196 IWineD3DSurface_Release(srcSurface);
5197 IWineD3DSurface_Release(destSurface);
5198 if (WINED3D_OK != hr) {
5199 WARN("(%p) : Call to update surface failed\n", This);
5200 return hr;
5204 break;
5205 case WINED3DRTYPE_CUBETEXTURE:
5207 IWineD3DSurface *srcSurface;
5208 IWineD3DSurface *destSurface;
5209 WINED3DCUBEMAP_FACES faceType;
5211 for (i = 0 ; i < levels ; ++i) {
5212 /* Update each cube face */
5213 for (faceType = D3DCUBEMAP_FACE_POSITIVE_X; faceType <= D3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
5214 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture, faceType, i, &srcSurface);
5215 if (WINED3D_OK != hr) {
5216 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5217 } else {
5218 TRACE("Got srcSurface %p\n", srcSurface);
5220 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
5221 if (WINED3D_OK != hr) {
5222 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5223 } else {
5224 TRACE("Got desrSurface %p\n", destSurface);
5226 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5227 IWineD3DSurface_Release(srcSurface);
5228 IWineD3DSurface_Release(destSurface);
5229 if (WINED3D_OK != hr) {
5230 WARN("(%p) : Call to update surface failed\n", This);
5231 return hr;
5236 break;
5237 #if 0 /* TODO: Add support for volume textures */
5238 case WINED3DRTYPE_VOLUMETEXTURE:
5240 IWineD3DVolume srcVolume = NULL;
5241 IWineD3DSurface destVolume = NULL;
5243 for (i = 0 ; i < levels ; ++i) {
5244 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture, i, &srcVolume);
5245 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
5246 hr = IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
5247 IWineD3DVolume_Release(srcSurface);
5248 IWineD3DVolume_Release(destSurface);
5249 if (WINED3D_OK != hr) {
5250 WARN("(%p) : Call to update volume failed\n", This);
5251 return hr;
5255 break;
5256 #endif
5257 default:
5258 FIXME("(%p) : Unsupported source and destination type\n", This);
5259 hr = WINED3DERR_INVALIDCALL;
5263 return hr;
5266 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
5267 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
5268 CONST RECT* pDestRect, WINED3DTEXTUREFILTERTYPE Filter) {
5269 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5271 TRACE("(%p) : stub\n", This);
5272 return WINED3D_OK;
5274 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
5275 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5276 /** TODO: remove remove casts to IWineD3DSurfaceImpl *
5277 * NOTE It may be best to move the code into surface to occomplish this
5278 ****************************************/
5280 WINED3DSURFACE_DESC surfaceDesc;
5281 unsigned int surfaceWidth, surfaceHeight;
5282 glDescriptor *targetGlDescription = NULL;
5283 glDescriptor *surfaceGlDescription = NULL;
5284 IWineD3DSwapChainImpl *container = NULL;
5286 IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
5287 IWineD3DSurface_GetGlDesc(pSurface, &surfaceGlDescription);
5288 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5290 surfaceDesc.Width = &surfaceWidth;
5291 surfaceDesc.Height = &surfaceHeight;
5292 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5293 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
5295 /* Ok, I may need to setup some kind of active swapchain reference on the device */
5296 IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
5297 ENTER_GL();
5298 /* TODO: opengl Context switching for swapchains etc... */
5299 if (NULL != container || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
5300 if (NULL != container && (pRenderTarget == container->backBuffer)) {
5301 glReadBuffer(GL_BACK);
5302 vcheckGLcall("glReadBuffer(GL_BACK)");
5303 } else if ((NULL != container && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
5304 glReadBuffer(GL_FRONT);
5305 vcheckGLcall("glReadBuffer(GL_FRONT)");
5306 } else if (pRenderTarget == This->depthStencilBuffer) {
5307 FIXME("Reading of depthstencil not yet supported\n");
5310 glReadPixels(surfaceGlDescription->target,
5311 surfaceGlDescription->level,
5312 surfaceWidth,
5313 surfaceHeight,
5314 surfaceGlDescription->glFormat,
5315 surfaceGlDescription->glType,
5316 (void *)IWineD3DSurface_GetData(pSurface));
5317 vcheckGLcall("glReadPixels(...)");
5318 if(NULL != container ){
5319 IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
5321 } else {
5322 IWineD3DBaseTexture *container;
5323 GLenum textureDimensions = GL_TEXTURE_2D;
5325 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
5326 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
5327 IWineD3DBaseTexture_Release(container);
5329 /* TODO: 2D -> Cube surface coppies etc.. */
5330 if (surfaceGlDescription->target != textureDimensions) {
5331 FIXME("(%p) : Texture dimension mismatch\n", This);
5333 glEnable(textureDimensions);
5334 vcheckGLcall("glEnable(GL_TEXTURE_...)");
5335 /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
5336 glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
5337 vcheckGLcall("glBindTexture");
5338 glGetTexImage(surfaceGlDescription->target,
5339 surfaceGlDescription->level,
5340 surfaceGlDescription->glFormat,
5341 surfaceGlDescription->glType,
5342 (void *)IWineD3DSurface_GetData(pSurface));
5343 glDisable(textureDimensions);
5344 vcheckGLcall("glDisable(GL_TEXTURE_...)");
5347 LEAVE_GL();
5348 return WINED3D_OK;
5351 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
5352 IWineD3DSwapChain *swapChain;
5353 HRESULT hr;
5354 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5355 if(hr == WINED3D_OK) {
5356 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
5357 IWineD3DSwapChain_Release(swapChain);
5359 return hr;
5362 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5363 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5364 /* return a sensible default */
5365 *pNumPasses = 1;
5366 /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
5367 FIXME("(%p) : stub\n", This);
5368 return WINED3D_OK;
5371 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5372 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5373 int j;
5374 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5375 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5376 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5377 return WINED3DERR_INVALIDCALL;
5379 for (j = 0; j < 256; ++j) {
5380 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
5381 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5382 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
5383 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5385 TRACE("(%p) : returning\n", This);
5386 return WINED3D_OK;
5389 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5390 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5391 int j;
5392 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5393 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5394 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5395 return WINED3DERR_INVALIDCALL;
5397 for (j = 0; j < 256; ++j) {
5398 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
5399 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5400 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
5401 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5403 TRACE("(%p) : returning\n", This);
5404 return WINED3D_OK;
5407 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5408 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5409 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5410 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5411 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5412 return WINED3DERR_INVALIDCALL;
5414 /*TODO: stateblocks */
5415 This->currentPalette = PaletteNumber;
5416 TRACE("(%p) : returning\n", This);
5417 return WINED3D_OK;
5420 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
5421 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5422 if (PaletteNumber == NULL) {
5423 WARN("(%p) : returning Invalid Call\n", This);
5424 return WINED3DERR_INVALIDCALL;
5426 /*TODO: stateblocks */
5427 *PaletteNumber = This->currentPalette;
5428 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
5429 return WINED3D_OK;
5432 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
5433 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5434 static BOOL showFixmes = TRUE;
5435 if (showFixmes) {
5436 FIXME("(%p) : stub\n", This);
5437 showFixmes = FALSE;
5440 This->softwareVertexProcessing = bSoftware;
5441 return WINED3D_OK;
5445 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
5446 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5447 static BOOL showFixmes = TRUE;
5448 if (showFixmes) {
5449 FIXME("(%p) : stub\n", This);
5450 showFixmes = FALSE;
5452 return This->softwareVertexProcessing;
5456 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
5457 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5458 IWineD3DSwapChain *swapChain;
5459 HRESULT hr;
5461 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
5463 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5464 if(hr == WINED3D_OK){
5465 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
5466 IWineD3DSwapChain_Release(swapChain);
5467 }else{
5468 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
5470 return hr;
5474 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
5475 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5476 static BOOL showfixmes = TRUE;
5477 if(nSegments != 0.0f) {
5478 if( showfixmes) {
5479 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
5480 showfixmes = FALSE;
5483 return WINED3D_OK;
5486 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
5487 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5488 static BOOL showfixmes = TRUE;
5489 if( showfixmes) {
5490 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
5491 showfixmes = FALSE;
5493 return 0.0f;
5496 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
5497 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5498 /** TODO: remove casts to IWineD3DSurfaceImpl
5499 * NOTE: move code to surface to accomplish this
5500 ****************************************/
5501 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
5502 int srcWidth, srcHeight;
5503 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
5504 WINED3DFORMAT destFormat, srcFormat;
5505 UINT destSize;
5506 int destLeft, destTop;
5507 WINED3DPOOL srcPool, destPool;
5508 int offset = 0;
5509 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
5510 glDescriptor *glDescription = NULL;
5511 GLenum textureDimensions = GL_TEXTURE_2D;
5512 IWineD3DBaseTexture *baseTexture;
5514 WINED3DSURFACE_DESC winedesc;
5516 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
5517 memset(&winedesc, 0, sizeof(winedesc));
5518 winedesc.Width = &srcSurfaceWidth;
5519 winedesc.Height = &srcSurfaceHeight;
5520 winedesc.Pool = &srcPool;
5521 winedesc.Format = &srcFormat;
5523 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5525 winedesc.Width = &destSurfaceWidth;
5526 winedesc.Height = &destSurfaceHeight;
5527 winedesc.Pool = &destPool;
5528 winedesc.Format = &destFormat;
5529 winedesc.Size = &destSize;
5531 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5533 if(srcPool != WINED3DPOOL_SYSTEMMEM || destPool != WINED3DPOOL_DEFAULT){
5534 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
5535 return WINED3DERR_INVALIDCALL;
5538 if (destFormat == WINED3DFMT_UNKNOWN) {
5539 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5540 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5542 /* Get the update surface description */
5543 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5546 /* Make sure the surface is loaded and up to date */
5547 IWineD3DSurface_PreLoad(pDestinationSurface);
5549 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
5551 ENTER_GL();
5553 /* this needs to be done in lines if the sourceRect != the sourceWidth */
5554 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
5555 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
5556 destLeft = pDestPoint ? pDestPoint->x : 0;
5557 destTop = pDestPoint ? pDestPoint->y : 0;
5560 /* This function doesn't support compressed textures
5561 the pitch is just bytesPerPixel * width */
5562 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
5563 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
5564 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
5565 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
5567 /* TODO DXT formats */
5569 if(pSourceRect != NULL && pSourceRect->top != 0){
5570 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
5572 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
5573 ,This
5574 ,glDescription->level
5575 ,destLeft
5576 ,destTop
5577 ,srcWidth
5578 ,srcHeight
5579 ,glDescription->glFormat
5580 ,glDescription->glType
5581 ,IWineD3DSurface_GetData(pSourceSurface)
5584 /* Sanity check */
5585 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
5587 /* need to lock the surface to get the data */
5588 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5591 /* TODO: Cube and volume support */
5592 if(rowoffset != 0){
5593 /* not a whole row so we have to do it a line at a time */
5594 int j;
5596 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
5597 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5599 for(j = destTop ; j < (srcHeight + destTop) ; j++){
5601 glTexSubImage2D(glDescription->target
5602 ,glDescription->level
5603 ,destLeft
5605 ,srcWidth
5607 ,glDescription->glFormat
5608 ,glDescription->glType
5609 ,data /* could be quicker using */
5611 data += rowoffset;
5614 } else { /* Full width, so just write out the whole texture */
5616 if (WINED3DFMT_DXT1 == destFormat ||
5617 WINED3DFMT_DXT2 == destFormat ||
5618 WINED3DFMT_DXT3 == destFormat ||
5619 WINED3DFMT_DXT4 == destFormat ||
5620 WINED3DFMT_DXT5 == destFormat) {
5621 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
5622 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
5623 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
5624 FIXME("Updating part of a compressed texture is not supported at the moment\n");
5625 } if (destFormat != srcFormat) {
5626 FIXME("Updating mixed format compressed texture is not curretly support\n");
5627 } else {
5628 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
5629 glDescription->level,
5630 glDescription->glFormatInternal,
5631 srcWidth,
5632 srcHeight,
5634 destSize,
5635 IWineD3DSurface_GetData(pSourceSurface));
5637 } else {
5638 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
5642 } else {
5643 if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
5645 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
5646 to repack the data from pow2Width/Height to expected Width,Height, this makes the
5647 data returned by GetData non-power2 width/height with hardware non-power2
5648 pow2Width/height are set to surface width height, repacking isn't needed so it
5649 doesn't matter which function gets called. */
5650 glTexSubImage2D(glDescription->target
5651 ,glDescription->level
5652 ,destLeft
5653 ,destTop
5654 ,srcWidth
5655 ,srcHeight
5656 ,glDescription->glFormat
5657 ,glDescription->glType
5658 ,IWineD3DSurface_GetData(pSourceSurface)
5660 } else {
5662 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
5663 glTexSubImage2D(glDescription->target
5664 ,glDescription->level
5665 ,destLeft
5666 ,destTop
5667 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
5668 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
5669 ,glDescription->glFormat
5670 ,glDescription->glType
5671 ,IWineD3DSurface_GetData(pSourceSurface)
5677 checkGLcall("glTexSubImage2D");
5679 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
5680 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
5681 * surface bigger than it needs to be hmm.. */
5682 if (WINED3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
5683 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
5684 IWineD3DBaseTexture_Release(baseTexture);
5687 glDisable(textureDimensions); /* This needs to be managed better.... */
5688 LEAVE_GL();
5690 return WINED3D_OK;
5693 /* Used by DirectX 8 */
5694 HRESULT WINAPI IWineD3DDeviceImpl_CopyRects(IWineD3DDevice *iface,
5695 IWineD3DSurface* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
5696 IWineD3DSurface* pDestinationSurface, CONST POINT* pDestPointsArray) {
5698 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5699 HRESULT hr = WINED3D_OK;
5700 WINED3DFORMAT srcFormat, destFormat;
5701 UINT srcWidth, destWidth;
5702 UINT srcHeight, destHeight;
5703 UINT srcSize;
5704 WINED3DSURFACE_DESC winedesc;
5706 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
5707 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
5710 /* Check that the source texture is in WINED3DPOOL_SYSTEMMEM and the destination texture is in WINED3DPOOL_DEFAULT */
5711 memset(&winedesc, 0, sizeof(winedesc));
5713 winedesc.Format = &srcFormat;
5714 winedesc.Width = &srcWidth;
5715 winedesc.Height = &srcHeight;
5716 winedesc.Size = &srcSize;
5717 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5719 winedesc.Format = &destFormat;
5720 winedesc.Width = &destWidth;
5721 winedesc.Height = &destHeight;
5722 winedesc.Size = NULL;
5723 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5725 /* Check that the source and destination formats match */
5726 if (srcFormat != destFormat && WINED3DFMT_UNKNOWN != destFormat) {
5727 WARN("(%p) source %p format must match the dest %p format, returning WINED3DERR_INVALIDCALL\n", This, pSourceSurface, pDestinationSurface);
5728 return WINED3DERR_INVALIDCALL;
5729 } else if (WINED3DFMT_UNKNOWN == destFormat) {
5730 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5731 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5732 destFormat = srcFormat;
5735 /* Quick if complete copy ... */
5736 if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
5738 if (srcWidth == destWidth && srcHeight == destHeight) {
5739 WINED3DLOCKED_RECT lrSrc;
5740 WINED3DLOCKED_RECT lrDst;
5741 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, NULL, WINED3DLOCK_READONLY);
5742 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, NULL, 0L);
5743 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", srcWidth, srcHeight);
5745 memcpy(lrDst.pBits, lrSrc.pBits, srcSize);
5747 IWineD3DSurface_UnlockRect(pSourceSurface);
5748 IWineD3DSurface_UnlockRect(pDestinationSurface);
5749 TRACE("Unlocked src and dst\n");
5751 } else {
5753 FIXME("Wanted to copy all surfaces but size not compatible, returning WINED3DERR_INVALIDCALL\n");
5754 hr = WINED3DERR_INVALIDCALL;
5757 } else {
5759 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
5761 int bytesPerPixel = ((IWineD3DSurfaceImpl *) pSourceSurface)->bytesPerPixel;
5762 unsigned int i;
5764 /* Copy rect by rect */
5765 for (i = 0; i < cRects; ++i) {
5766 CONST RECT* r = &pSourceRectsArray[i];
5767 CONST POINT* p = &pDestPointsArray[i];
5768 int copyperline;
5769 int j;
5770 WINED3DLOCKED_RECT lrSrc;
5771 WINED3DLOCKED_RECT lrDst;
5772 RECT dest_rect;
5774 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
5775 if (srcFormat == WINED3DFMT_DXT1) {
5776 copyperline = ((r->right - r->left) * bytesPerPixel) / 2; /* DXT1 is half byte per pixel */
5777 } else {
5778 copyperline = ((r->right - r->left) * bytesPerPixel);
5781 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, r, WINED3DLOCK_READONLY);
5782 dest_rect.left = p->x;
5783 dest_rect.top = p->y;
5784 dest_rect.right = p->x + (r->right - r->left);
5785 dest_rect.bottom= p->y + (r->bottom - r->top);
5786 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, &dest_rect, 0L);
5787 TRACE("Locked src and dst\n");
5789 /* Find where to start */
5790 for (j = 0; j < (r->bottom - r->top - 1); ++j) {
5791 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
5793 IWineD3DSurface_UnlockRect(pSourceSurface);
5794 IWineD3DSurface_UnlockRect(pDestinationSurface);
5795 TRACE("Unlocked src and dst\n");
5797 } else {
5798 FIXME("Wanted to copy partial surfaces not implemented, returning WINED3DERR_INVALIDCALL\n");
5799 hr = WINED3DERR_INVALIDCALL;
5803 return hr;
5806 /* Implementation details at http://developer.nvidia.com/attach/6494
5808 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
5809 hmm.. no longer supported use
5810 OpenGL evaluators or tessellate surfaces within your application.
5813 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
5814 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
5815 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5816 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
5817 FIXME("(%p) : Stub\n", This);
5818 return WINED3D_OK;
5822 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
5823 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
5824 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5825 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
5826 FIXME("(%p) : Stub\n", This);
5827 return WINED3D_OK;
5830 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5831 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5832 TRACE("(%p) Handle(%d)\n", This, Handle);
5833 FIXME("(%p) : Stub\n", This);
5834 return WINED3D_OK;
5837 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
5838 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
5839 fill a surface with a block of color! */
5840 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5841 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
5842 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
5843 IWineD3DSwapChainImpl *container = NULL;
5844 BOOL isRenderTarget = FALSE;
5845 unsigned int width, height;
5846 unsigned int top, left;
5847 unsigned int u, v;
5848 DWORD *data;
5849 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
5851 if (surface->resource.pool != WINED3DPOOL_DEFAULT) {
5852 FIXME("call to colorfill with non WINED3DPOOL_DEFAULT surface\n");
5853 return WINED3DERR_INVALIDCALL;
5856 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
5857 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
5858 if (WINED3DUSAGE_RENDERTARGET & surface->resource.usage) {
5859 /* TODO: make sure we set everything back to the way it was, and context management!
5860 glGetIntegerv(GL_READ_BUFFER, &prev_read);
5861 vcheckGLcall("glIntegerv");
5862 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
5863 vcheckGLcall("glIntegerv");
5865 TRACE("Color fill to render targets may cause some graphics issues\n");
5866 if (pSurface == container->frontBuffer) {
5867 glDrawBuffer(GL_FRONT);
5868 } else {
5869 glDrawBuffer(GL_BACK);
5871 } else {
5872 if (WINED3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
5873 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld\n", surface, surface->resource.usage);
5874 } else {
5875 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
5877 if (container != NULL) {
5878 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5880 /* we can use GL_STENCIL_INDEX etc...*/
5881 return WINED3D_OK;
5883 if (container != NULL) {
5884 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5886 isRenderTarget = TRUE;
5888 /* TODO: drawing to GL_FRONT and GL_BACK */
5889 /* TODO: see if things can be speeded up by using the correct
5890 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
5891 if (pRect == NULL) {
5892 top = 0;
5893 left = 0;
5894 width = surface->currentDesc.Width;
5895 height = surface->currentDesc.Height;
5896 } else {
5897 left = pRect->x1;
5898 top = pRect->y1;
5899 width = pRect->x2 - left;
5900 height = pRect->y2 - top;
5903 data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
5904 /* Create a 'line' of color color, in the correct format for the surface */
5905 for (u = 0 ; u < width ; u ++) {
5906 data[u] = color;
5909 ENTER_GL();
5910 if (isRenderTarget == FALSE) {
5911 glDescriptor *glDesc;
5912 IWineD3DSurface_PreLoad(pSurface);
5914 /* draw a block of the coloured line on the sufrace */
5915 IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
5916 for (v = 0 ; v< height;v++) {
5917 glTexSubImage2D(glDesc->target
5918 ,glDesc->level /* level */
5919 ,left
5920 ,top + v
5921 ,width
5922 ,1 /* height */
5923 ,GL_RGBA
5924 ,GL_UNSIGNED_BYTE
5925 ,data
5928 checkGLcall("glTexSubImage2D");
5929 /* clean up */
5930 glDisable(glDesc->target);
5931 } else {
5932 /** FIXME: Using GLClear may be faster **/
5933 glRasterPos2i(left, top);
5934 glPixelZoom((float)width ,(float)height);
5935 glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
5936 checkGLcall("glDrawPixels");
5938 HeapFree(GetProcessHeap(), 0, data);
5939 LEAVE_GL();
5940 return WINED3D_OK;
5944 /* rendertarget and deptth stencil functions */
5945 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
5946 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5948 /* FIXME: Implelent RenderTargetIndex >0 */
5949 if(RenderTargetIndex > 0)
5950 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
5952 *ppRenderTarget = This->renderTarget;
5953 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
5954 /* Note inc ref on returned surface */
5955 if(*ppRenderTarget != NULL)
5956 IWineD3DSurface_AddRef(*ppRenderTarget);
5957 return WINED3D_OK;
5960 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5961 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5962 *ppZStencilSurface = This->depthStencilBuffer;
5963 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
5965 if(*ppZStencilSurface != NULL) {
5966 /* Note inc ref on returned surface */
5967 IWineD3DSurface_AddRef(*ppZStencilSurface);
5969 return WINED3D_OK;
5972 /* internal static helper functions */
5973 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5974 IWineD3DSurface *RenderSurface);
5976 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5977 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5978 HRESULT hr = WINED3D_OK;
5979 WINED3DVIEWPORT viewport;
5981 TRACE("(%p) Swapping rendertarget\n",This);
5982 if (RenderTargetIndex > 0) {
5983 FIXME("(%p) Render targets other than the first are not supported\n",This);
5984 RenderTargetIndex = 0;
5987 /* MSDN says that null disables the render target
5988 but a device must always be associated with a render target
5989 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5991 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5992 for more details
5994 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5995 FIXME("Trying to set render target 0 to NULL\n");
5996 return WINED3DERR_INVALIDCALL;
5998 /* TODO: replace Impl* usage with interface usage */
5999 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
6000 FIXME("(%p)Trying to set the render target to a surface(%p) that wasn't created with a usage of WINED3DUSAGE_RENDERTARGET\n",This ,pRenderTarget);
6001 return WINED3DERR_INVALIDCALL;
6003 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
6004 * builds, but I think wine counts as a 'debug' build for now.
6005 ******************************/
6006 /* If we are trying to set what we already have, don't bother */
6007 if (pRenderTarget == This->renderTarget) {
6008 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6009 } else {
6010 /* Otherwise, set the render target up */
6012 if (FALSE == This->sceneEnded) {
6013 IWineD3DDevice_EndScene(iface);
6015 TRACE("clearing renderer\n");
6016 /* IWineD3DDeviceImpl_CleanRender(iface); */
6017 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6018 depending on the renter target implementation being used.
6019 A shared context implementation will share all buffers between all rendertargets (including swapchains),
6020 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6021 stencil buffer and incure an extra memory overhead */
6022 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
6025 if (SUCCEEDED(hr)) {
6026 /* Finally, reset the viewport as the MSDN states. */
6027 /* TODO: Replace impl usage */
6028 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
6029 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
6030 viewport.X = 0;
6031 viewport.Y = 0;
6032 viewport.MaxZ = 1.0f;
6033 viewport.MinZ = 0.0f;
6034 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
6035 } else {
6036 FIXME("Unknown error setting the render target\n");
6038 This->sceneEnded = FALSE;
6039 return hr;
6042 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
6043 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6044 HRESULT hr = WINED3D_OK;
6045 IWineD3DSurface *tmp;
6047 TRACE("(%p) Swapping z-buffer\n",This);
6049 if (pNewZStencil == This->stencilBufferTarget) {
6050 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6051 } else {
6052 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6053 * depending on the renter target implementation being used.
6054 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
6055 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6056 * stencil buffer and incure an extra memory overhead
6057 ******************************************************/
6060 tmp = This->stencilBufferTarget;
6061 This->stencilBufferTarget = pNewZStencil;
6062 /* should we be calling the parent or the wined3d surface? */
6063 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
6064 if (NULL != tmp) IWineD3DSurface_Release(tmp);
6065 hr = WINED3D_OK;
6066 /** TODO: glEnable/glDisable on depth/stencil depending on
6067 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
6068 **********************************************************/
6071 return hr;
6075 #ifdef GL_VERSION_1_3
6076 /* Internal functions not in DirectX */
6077 /** TODO: move this off to the opengl context manager
6078 *(the swapchain doesn't need to know anything about offscreen rendering!)
6079 ****************************************************/
6081 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
6083 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6085 TRACE("(%p), %p\n", This, swapchain);
6087 if (swapchain->win != swapchain->drawable) {
6088 /* Set everything back the way it ws */
6089 swapchain->render_ctx = swapchain->glCtx;
6090 swapchain->drawable = swapchain->win;
6092 return WINED3D_OK;
6095 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
6096 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
6097 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6098 int i;
6099 unsigned int width;
6100 unsigned int height;
6101 WINED3DFORMAT format;
6102 WINED3DSURFACE_DESC surfaceDesc;
6103 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
6104 surfaceDesc.Width = &width;
6105 surfaceDesc.Height = &height;
6106 surfaceDesc.Format = &format;
6107 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
6108 *context = NULL;
6109 /* I need a get width/height function (and should do something with the format) */
6110 for (i = 0; i < CONTEXT_CACHE; ++i) {
6111 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
6112 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
6113 the pSurface can be set to 0 allowing it to be reused from cache **/
6114 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
6115 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
6116 *context = &This->contextCache[i];
6117 break;
6119 if (This->contextCache[i].Width == 0) {
6120 This->contextCache[i].pSurface = pSurface;
6121 This->contextCache[i].Width = width;
6122 This->contextCache[i].Height = height;
6123 *context = &This->contextCache[i];
6124 break;
6127 if (i == CONTEXT_CACHE) {
6128 int minUsage = 0x7FFFFFFF; /* MAX_INT */
6129 glContext *dropContext = 0;
6130 for (i = 0; i < CONTEXT_CACHE; i++) {
6131 if (This->contextCache[i].usedcount < minUsage) {
6132 dropContext = &This->contextCache[i];
6133 minUsage = This->contextCache[i].usedcount;
6136 /* clean up the context (this doesn't work for ATI at the moment */
6137 #if 0
6138 glXDestroyContext(swapchain->display, dropContext->context);
6139 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
6140 #endif
6141 FIXME("Leak\n");
6142 dropContext->Width = 0;
6143 dropContext->pSurface = pSurface;
6144 *context = dropContext;
6145 } else {
6146 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
6147 for (i = 0; i < CONTEXT_CACHE; i++) {
6148 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
6152 if (*context != NULL)
6153 return WINED3D_OK;
6154 else
6155 return E_OUTOFMEMORY;
6157 #endif
6159 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
6160 * the functionality needs splitting up so that we don't do more than we should do.
6161 * this only seems to impact performance a little.
6162 ******************************/
6163 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
6164 IWineD3DSurface *RenderSurface) {
6165 HRESULT ret = WINED3DERR_INVALIDCALL;
6168 * Currently only active for GLX >= 1.3
6169 * for others versions we'll have to use GLXPixmaps
6171 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
6172 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
6173 * so only check OpenGL version
6174 * ..........................
6175 * I don't believe that it is a problem with NVidia headers,
6176 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
6177 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
6178 * ATI Note:
6179 * Your application will report GLX version 1.2 on glXQueryVersion.
6180 * However, it is safe to call the GLX 1.3 functions as described below.
6182 #if defined(GL_VERSION_1_3)
6184 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6185 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
6186 IWineD3DSurface *tmp;
6187 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
6188 GLXFBConfig* cfgs = NULL;
6189 int nCfgs = 0;
6190 int attribs[256];
6191 int nAttribs = 0;
6192 IWineD3DSwapChain *currentSwapchain;
6193 IWineD3DSwapChainImpl *swapchain;
6194 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
6195 * but switch them off if the StencilSurface is set to NULL
6196 ** *********************************************************/
6197 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
6198 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
6200 /**TODO:
6201 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
6202 it StencilSurface != NULL && zBufferTarget == NULL switch it on
6205 #define PUSH1(att) attribs[nAttribs++] = (att);
6206 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
6208 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
6210 /** TODO: remove the reff to Impl (context manager should fix this!) **/
6211 IWineD3DSwapChainImpl *impSwapChain;
6212 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
6213 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
6214 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
6217 ENTER_GL();
6219 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
6220 PUSH2(GLX_X_RENDERABLE, TRUE);
6221 PUSH2(GLX_DOUBLEBUFFER, TRUE);
6222 TRACE("calling makeglcfg\n");
6223 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
6224 PUSH1(None);
6226 TRACE("calling chooseFGConfig\n");
6227 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
6228 attribs, &nCfgs);
6230 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
6231 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
6232 why we failed and only show this message once! */
6233 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"); /**/
6234 nAttribs = 0;
6235 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
6236 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
6237 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
6238 PUSH2(GLX_DOUBLEBUFFER, FALSE);
6239 TRACE("calling makeglcfg\n");
6240 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
6241 PUSH1(None);
6242 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
6243 attribs, &nCfgs);
6246 if (NULL != cfgs) {
6247 #ifdef EXTRA_TRACES
6248 int i;
6249 for (i = 0; i < nCfgs; ++i) {
6250 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
6251 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
6252 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
6255 if (NULL != This->renderTarget) {
6256 glFlush();
6257 vcheckGLcall("glFlush");
6258 /** This is only useful if the old render target was a swapchain,
6259 * we need to supercede this with a function that displays
6260 * the current buffer on the screen. This is easy to do in glx1.3 but
6261 * we need to do copy-write pixels in glx 1.2.
6262 ************************************************/
6263 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
6265 printf("Hit Enter to get next frame ...\n");
6266 getchar();
6268 #endif
6271 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&currentSwapchain) != WINED3D_OK) {
6272 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
6273 IWineD3DDevice_GetSwapChain(iface, 0, &currentSwapchain);
6277 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
6278 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
6279 **********************************************************************/
6280 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == WINED3D_OK) {
6281 /* We also need to make sure that the lights &co are also in the context of the swapchains */
6282 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
6283 TRACE("making swapchain active\n");
6284 if (RenderSurface != This->renderTarget) {
6285 if (RenderSurface == swapchain->backBuffer) {
6286 } else {
6287 /* This could be flagged so that some operations work directly with the front buffer */
6288 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
6290 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
6291 == False) {
6292 TRACE("Error in setting current context: context %p drawable %ld !\n",
6293 impSwapChain->glCtx, impSwapChain->win);
6296 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
6298 checkGLcall("glXMakeContextCurrent");
6300 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
6302 else if (pbuffer_support == TRUE && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
6304 /** ********************************************************************
6305 * This is a quickly hacked out implementation of offscreen textures.
6306 * It will work in most cases but there may be problems if the client
6307 * modifies the texture directly, or expects the contents of the rendertarget
6308 * to be persistent.
6310 * There are some real speed vs compatibility issues here:
6311 * we should really use a new context for every texture, but that eats ram.
6312 * we should also be restoring the texture to the pbuffer but that eats CPU
6313 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
6314 * but if this means reusing the display backbuffer then we need to make sure that
6315 * states are correctly preserved.
6316 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
6317 * and gain a good performance increase at the cost of compatibility.
6318 * I would suggest that, when this is the case, a user configurable flag be made
6319 * available, allowing the user to choose the best emulated experience for them.
6320 *********************************************************************/
6322 XVisualInfo *visinfo;
6323 glContext *newContext;
6325 /* Here were using a shared context model */
6326 if (WINED3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
6327 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6330 /* If the context doesn't exist then create a new one */
6331 /* TODO: This should really be part of findGlContext */
6332 if (NULL == newContext->context) {
6334 TRACE("making new buffer\n");
6335 nAttribs = 0;
6336 PUSH2(GLX_PBUFFER_WIDTH, newContext->Width);
6337 PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
6338 PUSH1(None);
6340 newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
6342 /** ****************************************
6343 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
6344 *they note:
6345 * In future releases, we may provide the calls glXCreateNewContext,
6346 * glXQueryDrawable and glXMakeContextCurrent.
6347 * so until then we have to use glXGetVisualFromFBConfig &co..
6348 ********************************************/
6351 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
6352 if (!visinfo) {
6353 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
6354 } else {
6355 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
6356 XFree(visinfo);
6359 if (NULL == newContext || NULL == newContext->context) {
6360 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6361 } else {
6362 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
6363 if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
6364 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
6367 /* Clean up the old context */
6368 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
6369 /* Set the current context of the swapchain to the new context */
6370 impSwapChain->drawable = newContext->drawable;
6371 impSwapChain->render_ctx = newContext->context;
6375 #if 1 /* Apply the stateblock to the new context
6376 FIXME: This is a bit of a hack, each context should know it's own state,
6377 the directX current directX state should then be applied to the context */
6379 BOOL oldRecording;
6380 IWineD3DStateBlockImpl *oldUpdateStateBlock;
6381 oldUpdateStateBlock = This->updateStateBlock;
6382 oldRecording= This->isRecordingState;
6383 This->isRecordingState = FALSE;
6384 This->updateStateBlock = This->stateBlock;
6385 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
6387 This->isRecordingState = oldRecording;
6388 This->updateStateBlock = oldUpdateStateBlock;
6390 #endif
6393 /* clean up the current rendertargets swapchain (if it belonged to one) */
6394 if (currentSwapchain != NULL) {
6395 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
6398 /* Were done with the opengl context management, setup the rendertargets */
6400 tmp = This->renderTarget;
6401 This->renderTarget = RenderSurface;
6402 IWineD3DSurface_AddRef(This->renderTarget);
6403 IWineD3DSurface_Release(tmp);
6408 DWORD value;
6409 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
6410 /* Check that the container is not a swapchain member */
6412 IWineD3DSwapChain *tmpSwapChain;
6413 if (WINED3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
6414 This->renderUpsideDown = TRUE;
6415 }else{
6416 This->renderUpsideDown = FALSE;
6417 IWineD3DSwapChain_Release(tmpSwapChain);
6419 /* Force updating the cull mode */
6420 TRACE("setting render state\n");
6421 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
6422 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
6424 /* Force updating projection matrix */
6425 This->last_was_rhw = FALSE;
6426 This->proj_valid = FALSE;
6429 ret = WINED3D_OK;
6431 if (cfgs != NULL) {
6432 XFree(cfgs);
6433 } else {
6434 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
6435 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
6438 #undef PUSH1
6439 #undef PUSH2
6440 if ( NULL != impSwapChain) {
6441 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
6443 LEAVE_GL();
6445 #endif
6446 return ret;
6449 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
6450 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
6451 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6452 /* TODO: the use of Impl is deprecated. */
6453 /* some basic validation checks */
6454 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
6456 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
6458 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
6459 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
6460 return WINED3DERR_INVALIDCALL;
6462 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
6463 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
6464 return WINED3DERR_INVALIDCALL;
6466 /* TODO: make the cursor 'real' */
6468 This->xHotSpot = XHotSpot;
6469 This->yHotSpot = YHotSpot;
6471 return WINED3D_OK;
6474 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
6475 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6476 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
6478 This->xScreenSpace = XScreenSpace;
6479 This->yScreenSpace = YScreenSpace;
6481 return;
6485 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
6486 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6487 TRACE("(%p) : visible(%d)\n", This, bShow);
6489 This->bCursorVisible = bShow;
6491 return WINED3D_OK;
6494 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
6495 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6496 TRACE("(%p) : state (%lu)\n", This, This->state);
6497 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
6498 switch (This->state) {
6499 case WINED3D_OK:
6500 return WINED3D_OK;
6501 case WINED3DERR_DEVICELOST:
6503 ResourceList *resourceList = This->resources;
6504 while (NULL != resourceList) {
6505 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
6506 return WINED3DERR_DEVICENOTRESET;
6507 resourceList = resourceList->next;
6509 return WINED3DERR_DEVICELOST;
6511 case WINED3DERR_DRIVERINTERNALERROR:
6512 return WINED3DERR_DRIVERINTERNALERROR;
6515 /* Unknown state */
6516 return WINED3DERR_DRIVERINTERNALERROR;
6520 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
6521 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6522 /** FIXME: Resource tracking needs to be done,
6523 * The closes we can do to this is set the priorities of all managed textures low
6524 * and then reset them.
6525 ***********************************************************/
6526 FIXME("(%p) : stub\n", This);
6527 return WINED3D_OK;
6530 HRESULT WINAPI IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
6531 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6532 /** FIXME: Resource trascking needs to be done.
6533 * in effect this pulls all non only default
6534 * textures out of video memory and deletes all glTextures (glDeleteTextures)
6535 * and should clear down the context and set it up according to pPresentationParameters
6536 ***********************************************************/
6537 FIXME("(%p) : stub\n", This);
6538 return WINED3D_OK;
6541 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
6542 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6543 /** FIXME: always true at the moment **/
6544 if(bEnableDialogs == FALSE) {
6545 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
6547 return WINED3D_OK;
6551 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
6552 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6553 TRACE("(%p) : pParameters %p\n", This, pParameters);
6555 *pParameters = This->createParms;
6556 return WINED3D_OK;
6559 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
6560 IWineD3DSwapChain *swapchain;
6561 HRESULT hrc = WINED3D_OK;
6563 TRACE("Relaying to swapchain\n");
6565 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
6566 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
6567 IWineD3DSwapChain_Release(swapchain);
6569 return;
6572 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
6573 IWineD3DSwapChain *swapchain;
6574 HRESULT hrc = WINED3D_OK;
6576 TRACE("Relaying to swapchain\n");
6578 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
6579 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
6580 IWineD3DSwapChain_Release(swapchain);
6582 return;
6586 /** ********************************************************
6587 * Notification functions
6588 ** ********************************************************/
6589 /** This function must be called in the release of a resource when ref == 0,
6590 * the contents of resource must still be correct,
6591 * any handels to other resource held by the caller must be closed
6592 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
6593 *****************************************************/
6594 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6595 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6596 ResourceList* resourceList;
6598 TRACE("(%p) : resource %p\n", This, resource);
6599 #if 0
6600 EnterCriticalSection(&resourceStoreCriticalSection);
6601 #endif
6602 /* add a new texture to the frot of the linked list */
6603 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
6604 resourceList->resource = resource;
6606 /* Get the old head */
6607 resourceList->next = This->resources;
6609 This->resources = resourceList;
6610 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
6612 #if 0
6613 LeaveCriticalSection(&resourceStoreCriticalSection);
6614 #endif
6615 return;
6618 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6619 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6620 ResourceList* resourceList = NULL;
6621 ResourceList* previousResourceList = NULL;
6623 TRACE("(%p) : resource %p\n", This, resource);
6625 #if 0
6626 EnterCriticalSection(&resourceStoreCriticalSection);
6627 #endif
6628 resourceList = This->resources;
6630 while (resourceList != NULL) {
6631 if(resourceList->resource == resource) break;
6632 previousResourceList = resourceList;
6633 resourceList = resourceList->next;
6636 if (resourceList == NULL) {
6637 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
6638 #if 0
6639 LeaveCriticalSection(&resourceStoreCriticalSection);
6640 #endif
6641 return;
6642 } else {
6643 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
6645 /* make sure we don't leave a hole in the list */
6646 if (previousResourceList != NULL) {
6647 previousResourceList->next = resourceList->next;
6648 } else {
6649 This->resources = resourceList->next;
6652 #if 0
6653 LeaveCriticalSection(&resourceStoreCriticalSection);
6654 #endif
6655 return;
6659 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
6660 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6661 int counter;
6663 TRACE("(%p) : resource %p\n", This, resource);
6664 switch(IWineD3DResource_GetType(resource)){
6665 case WINED3DRTYPE_SURFACE:
6666 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
6667 break;
6668 case WINED3DRTYPE_TEXTURE:
6669 case WINED3DRTYPE_CUBETEXTURE:
6670 case WINED3DRTYPE_VOLUMETEXTURE:
6671 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
6672 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6673 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6674 This->stateBlock->textures[counter] = NULL;
6676 if (This->updateStateBlock != This->stateBlock ){
6677 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6678 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6679 This->updateStateBlock->textures[counter] = NULL;
6683 break;
6684 case WINED3DRTYPE_VOLUME:
6685 /* TODO: nothing really? */
6686 break;
6687 case WINED3DRTYPE_VERTEXBUFFER:
6688 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
6690 int streamNumber;
6691 TRACE("Cleaning up stream pointers\n");
6693 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
6694 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
6695 FINDOUT: should changes.streamSource[StreamNumber] be set ?
6697 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6698 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
6699 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
6700 This->updateStateBlock->streamSource[streamNumber] = 0;
6701 /* Set changed flag? */
6704 if (This->stateBlock != NULL ) { /* only happens if there is an error in the application, or on reset/release (because we don't manage internal tracking properly) */
6705 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
6706 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
6707 This->stateBlock->streamSource[streamNumber] = 0;
6710 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
6711 else { /* This shouldn't happen */
6712 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
6714 #endif
6718 break;
6719 case WINED3DRTYPE_INDEXBUFFER:
6720 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
6721 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6722 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6723 This->updateStateBlock->pIndexData = NULL;
6726 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
6727 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6728 This->stateBlock->pIndexData = NULL;
6732 break;
6733 default:
6734 FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
6735 break;
6739 /* Remove the resoruce from the resourceStore */
6740 IWineD3DDeviceImpl_RemoveResource(iface, resource);
6742 TRACE("Resource released\n");
6747 /** This function is to be called by the swapchain when it is released and it's ref = 0
6748 *****************************************************/
6749 void WINAPI IWineD3DDeviceImpl_SwapChainReleased(IWineD3DDevice *iface, IWineD3DSwapChain *swapChain){
6750 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6751 SwapChainList **nextSwapchain;
6752 nextSwapchain = &This->swapchains;
6754 /* Check to see if the swapchian is being used as the render target */
6755 if (This->renderTarget != NULL) {
6756 IWineD3DSurface *swapchainBackBuffer;
6758 IWineD3DSwapChain_GetBackBuffer(swapChain, 0 ,( D3DBACKBUFFER_TYPE) 0, &swapchainBackBuffer);
6759 if (This->renderTarget == swapchainBackBuffer) {
6760 /* Don't know what to do, so warn and carry on as usual (which in this case leaves the renderterget in limbo) */
6761 FIXME("Atempting to release a swapchain that is currently beuing used as a render target, behaviour is undefined\n");
6765 /* Go through the swapchain list and try to find the swapchain being released */
6766 while(*nextSwapchain != NULL && (*nextSwapchain)->swapchain != swapChain) {
6767 nextSwapchain = &(*nextSwapchain)->next;
6770 /* Check to see if we found the swapchain */
6771 if (NULL != *nextSwapchain) {
6772 /* We found the swapchain so remove it from the list */
6773 TRACE("(%p) releasing swapchain(%p)\n", iface, swapChain);
6774 HeapFree(GetProcessHeap(), 0 , *nextSwapchain);
6775 *nextSwapchain = (*nextSwapchain)->next;
6776 } else {
6777 /* We didn't find the swapchain on the list, this can only heppen because of a programming error in wined3d */
6778 FIXME("(%p) Attempting to release a swapchain (%p) that hasn't been stored\n", iface, swapChain);
6781 TRACE("swapchain (%p) released\n", swapChain);
6782 return;
6785 /**********************************************************
6786 * IWineD3DDevice VTbl follows
6787 **********************************************************/
6789 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
6791 /*** IUnknown methods ***/
6792 IWineD3DDeviceImpl_QueryInterface,
6793 IWineD3DDeviceImpl_AddRef,
6794 IWineD3DDeviceImpl_Release,
6795 /*** IWineD3DDevice methods ***/
6796 IWineD3DDeviceImpl_GetParent,
6797 /*** Creation methods**/
6798 IWineD3DDeviceImpl_CreateVertexBuffer,
6799 IWineD3DDeviceImpl_CreateIndexBuffer,
6800 IWineD3DDeviceImpl_CreateStateBlock,
6801 IWineD3DDeviceImpl_CreateSurface,
6802 IWineD3DDeviceImpl_CreateTexture,
6803 IWineD3DDeviceImpl_CreateVolumeTexture,
6804 IWineD3DDeviceImpl_CreateVolume,
6805 IWineD3DDeviceImpl_CreateCubeTexture,
6806 IWineD3DDeviceImpl_CreateQuery,
6807 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
6808 IWineD3DDeviceImpl_CreateVertexDeclaration,
6809 IWineD3DDeviceImpl_CreateVertexShader,
6810 IWineD3DDeviceImpl_CreatePixelShader,
6811 /*** Odd functions **/
6812 IWineD3DDeviceImpl_EvictManagedResources,
6813 IWineD3DDeviceImpl_GetAvailableTextureMem,
6814 IWineD3DDeviceImpl_GetBackBuffer,
6815 IWineD3DDeviceImpl_GetCreationParameters,
6816 IWineD3DDeviceImpl_GetDeviceCaps,
6817 IWineD3DDeviceImpl_GetDirect3D,
6818 IWineD3DDeviceImpl_GetDisplayMode,
6819 IWineD3DDeviceImpl_GetNumberOfSwapChains,
6820 IWineD3DDeviceImpl_GetRasterStatus,
6821 IWineD3DDeviceImpl_GetSwapChain,
6822 IWineD3DDeviceImpl_Reset,
6823 IWineD3DDeviceImpl_SetDialogBoxMode,
6824 IWineD3DDeviceImpl_SetCursorProperties,
6825 IWineD3DDeviceImpl_SetCursorPosition,
6826 IWineD3DDeviceImpl_ShowCursor,
6827 IWineD3DDeviceImpl_TestCooperativeLevel,
6828 /*** Getters and setters **/
6829 IWineD3DDeviceImpl_SetClipPlane,
6830 IWineD3DDeviceImpl_GetClipPlane,
6831 IWineD3DDeviceImpl_SetClipStatus,
6832 IWineD3DDeviceImpl_GetClipStatus,
6833 IWineD3DDeviceImpl_SetCurrentTexturePalette,
6834 IWineD3DDeviceImpl_GetCurrentTexturePalette,
6835 IWineD3DDeviceImpl_SetDepthStencilSurface,
6836 IWineD3DDeviceImpl_GetDepthStencilSurface,
6837 IWineD3DDeviceImpl_SetFVF,
6838 IWineD3DDeviceImpl_GetFVF,
6839 IWineD3DDeviceImpl_SetGammaRamp,
6840 IWineD3DDeviceImpl_GetGammaRamp,
6841 IWineD3DDeviceImpl_SetIndices,
6842 IWineD3DDeviceImpl_GetIndices,
6843 IWineD3DDeviceImpl_SetLight,
6844 IWineD3DDeviceImpl_GetLight,
6845 IWineD3DDeviceImpl_SetLightEnable,
6846 IWineD3DDeviceImpl_GetLightEnable,
6847 IWineD3DDeviceImpl_SetMaterial,
6848 IWineD3DDeviceImpl_GetMaterial,
6849 IWineD3DDeviceImpl_SetNPatchMode,
6850 IWineD3DDeviceImpl_GetNPatchMode,
6851 IWineD3DDeviceImpl_SetPaletteEntries,
6852 IWineD3DDeviceImpl_GetPaletteEntries,
6853 IWineD3DDeviceImpl_SetPixelShader,
6854 IWineD3DDeviceImpl_GetPixelShader,
6855 IWineD3DDeviceImpl_SetPixelShaderConstant,
6856 IWineD3DDeviceImpl_GetPixelShaderConstant,
6857 IWineD3DDeviceImpl_SetPixelShaderConstantB,
6858 IWineD3DDeviceImpl_GetPixelShaderConstantB,
6859 IWineD3DDeviceImpl_SetPixelShaderConstantI,
6860 IWineD3DDeviceImpl_GetPixelShaderConstantI,
6861 IWineD3DDeviceImpl_SetPixelShaderConstantF,
6862 IWineD3DDeviceImpl_GetPixelShaderConstantF,
6863 IWineD3DDeviceImpl_SetPixelShaderConstantN,
6864 IWineD3DDeviceImpl_SetRenderState,
6865 IWineD3DDeviceImpl_GetRenderState,
6866 IWineD3DDeviceImpl_SetRenderTarget,
6867 IWineD3DDeviceImpl_GetRenderTarget,
6868 IWineD3DDeviceImpl_SetSamplerState,
6869 IWineD3DDeviceImpl_GetSamplerState,
6870 IWineD3DDeviceImpl_SetScissorRect,
6871 IWineD3DDeviceImpl_GetScissorRect,
6872 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
6873 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
6874 IWineD3DDeviceImpl_SetStreamSource,
6875 IWineD3DDeviceImpl_GetStreamSource,
6876 IWineD3DDeviceImpl_SetStreamSourceFreq,
6877 IWineD3DDeviceImpl_GetStreamSourceFreq,
6878 IWineD3DDeviceImpl_SetTexture,
6879 IWineD3DDeviceImpl_GetTexture,
6880 IWineD3DDeviceImpl_SetTextureStageState,
6881 IWineD3DDeviceImpl_GetTextureStageState,
6882 IWineD3DDeviceImpl_SetTransform,
6883 IWineD3DDeviceImpl_GetTransform,
6884 IWineD3DDeviceImpl_SetVertexDeclaration,
6885 IWineD3DDeviceImpl_GetVertexDeclaration,
6886 IWineD3DDeviceImpl_SetVertexShader,
6887 IWineD3DDeviceImpl_GetVertexShader,
6888 IWineD3DDeviceImpl_SetVertexShaderConstant,
6889 IWineD3DDeviceImpl_GetVertexShaderConstant,
6890 IWineD3DDeviceImpl_SetVertexShaderConstantB,
6891 IWineD3DDeviceImpl_GetVertexShaderConstantB,
6892 IWineD3DDeviceImpl_SetVertexShaderConstantI,
6893 IWineD3DDeviceImpl_GetVertexShaderConstantI,
6894 IWineD3DDeviceImpl_SetVertexShaderConstantF,
6895 IWineD3DDeviceImpl_GetVertexShaderConstantF,
6896 IWineD3DDeviceImpl_SetVertexShaderConstantN,
6897 IWineD3DDeviceImpl_SetViewport,
6898 IWineD3DDeviceImpl_GetViewport,
6899 IWineD3DDeviceImpl_MultiplyTransform,
6900 IWineD3DDeviceImpl_ValidateDevice,
6901 IWineD3DDeviceImpl_ProcessVertices,
6902 /*** State block ***/
6903 IWineD3DDeviceImpl_BeginStateBlock,
6904 IWineD3DDeviceImpl_EndStateBlock,
6905 /*** Scene management ***/
6906 IWineD3DDeviceImpl_BeginScene,
6907 IWineD3DDeviceImpl_EndScene,
6908 IWineD3DDeviceImpl_Present,
6909 IWineD3DDeviceImpl_Clear,
6910 /*** Drawing ***/
6911 IWineD3DDeviceImpl_DrawPrimitive,
6912 IWineD3DDeviceImpl_DrawIndexedPrimitive,
6913 IWineD3DDeviceImpl_DrawPrimitiveUP,
6914 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
6915 IWineD3DDeviceImpl_DrawRectPatch,
6916 IWineD3DDeviceImpl_DrawTriPatch,
6917 IWineD3DDeviceImpl_DeletePatch,
6918 IWineD3DDeviceImpl_ColorFill,
6919 IWineD3DDeviceImpl_UpdateTexture,
6920 IWineD3DDeviceImpl_UpdateSurface,
6921 IWineD3DDeviceImpl_CopyRects,
6922 IWineD3DDeviceImpl_StretchRect,
6923 IWineD3DDeviceImpl_GetRenderTargetData,
6924 IWineD3DDeviceImpl_GetFrontBufferData,
6925 /*** Internal use IWineD3DDevice methods ***/
6926 IWineD3DDeviceImpl_SetupTextureStates,
6927 /*** object tracking ***/
6928 IWineD3DDeviceImpl_SwapChainReleased,
6929 IWineD3DDeviceImpl_ResourceReleased
6933 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
6934 WINED3DRS_ALPHABLENDENABLE ,
6935 WINED3DRS_ALPHAFUNC ,
6936 WINED3DRS_ALPHAREF ,
6937 WINED3DRS_ALPHATESTENABLE ,
6938 WINED3DRS_BLENDOP ,
6939 WINED3DRS_COLORWRITEENABLE ,
6940 WINED3DRS_DESTBLEND ,
6941 WINED3DRS_DITHERENABLE ,
6942 WINED3DRS_FILLMODE ,
6943 WINED3DRS_FOGDENSITY ,
6944 WINED3DRS_FOGEND ,
6945 WINED3DRS_FOGSTART ,
6946 WINED3DRS_LASTPIXEL ,
6947 WINED3DRS_SHADEMODE ,
6948 WINED3DRS_SRCBLEND ,
6949 WINED3DRS_STENCILENABLE ,
6950 WINED3DRS_STENCILFAIL ,
6951 WINED3DRS_STENCILFUNC ,
6952 WINED3DRS_STENCILMASK ,
6953 WINED3DRS_STENCILPASS ,
6954 WINED3DRS_STENCILREF ,
6955 WINED3DRS_STENCILWRITEMASK ,
6956 WINED3DRS_STENCILZFAIL ,
6957 WINED3DRS_TEXTUREFACTOR ,
6958 WINED3DRS_WRAP0 ,
6959 WINED3DRS_WRAP1 ,
6960 WINED3DRS_WRAP2 ,
6961 WINED3DRS_WRAP3 ,
6962 WINED3DRS_WRAP4 ,
6963 WINED3DRS_WRAP5 ,
6964 WINED3DRS_WRAP6 ,
6965 WINED3DRS_WRAP7 ,
6966 WINED3DRS_ZENABLE ,
6967 WINED3DRS_ZFUNC ,
6968 WINED3DRS_ZWRITEENABLE
6971 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
6972 WINED3DTSS_ADDRESSW ,
6973 WINED3DTSS_ALPHAARG0 ,
6974 WINED3DTSS_ALPHAARG1 ,
6975 WINED3DTSS_ALPHAARG2 ,
6976 WINED3DTSS_ALPHAOP ,
6977 WINED3DTSS_BUMPENVLOFFSET ,
6978 WINED3DTSS_BUMPENVLSCALE ,
6979 WINED3DTSS_BUMPENVMAT00 ,
6980 WINED3DTSS_BUMPENVMAT01 ,
6981 WINED3DTSS_BUMPENVMAT10 ,
6982 WINED3DTSS_BUMPENVMAT11 ,
6983 WINED3DTSS_COLORARG0 ,
6984 WINED3DTSS_COLORARG1 ,
6985 WINED3DTSS_COLORARG2 ,
6986 WINED3DTSS_COLOROP ,
6987 WINED3DTSS_RESULTARG ,
6988 WINED3DTSS_TEXCOORDINDEX ,
6989 WINED3DTSS_TEXTURETRANSFORMFLAGS
6992 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
6993 WINED3DSAMP_ADDRESSU ,
6994 WINED3DSAMP_ADDRESSV ,
6995 WINED3DSAMP_ADDRESSW ,
6996 WINED3DSAMP_BORDERCOLOR ,
6997 WINED3DSAMP_MAGFILTER ,
6998 WINED3DSAMP_MINFILTER ,
6999 WINED3DSAMP_MIPFILTER ,
7000 WINED3DSAMP_MIPMAPLODBIAS ,
7001 WINED3DSAMP_MAXMIPLEVEL ,
7002 WINED3DSAMP_MAXANISOTROPY ,
7003 WINED3DSAMP_SRGBTEXTURE ,
7004 WINED3DSAMP_ELEMENTINDEX
7007 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
7008 WINED3DRS_AMBIENT ,
7009 WINED3DRS_AMBIENTMATERIALSOURCE ,
7010 WINED3DRS_CLIPPING ,
7011 WINED3DRS_CLIPPLANEENABLE ,
7012 WINED3DRS_COLORVERTEX ,
7013 WINED3DRS_DIFFUSEMATERIALSOURCE ,
7014 WINED3DRS_EMISSIVEMATERIALSOURCE ,
7015 WINED3DRS_FOGDENSITY ,
7016 WINED3DRS_FOGEND ,
7017 WINED3DRS_FOGSTART ,
7018 WINED3DRS_FOGTABLEMODE ,
7019 WINED3DRS_FOGVERTEXMODE ,
7020 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
7021 WINED3DRS_LIGHTING ,
7022 WINED3DRS_LOCALVIEWER ,
7023 WINED3DRS_MULTISAMPLEANTIALIAS ,
7024 WINED3DRS_MULTISAMPLEMASK ,
7025 WINED3DRS_NORMALIZENORMALS ,
7026 WINED3DRS_PATCHEDGESTYLE ,
7027 WINED3DRS_POINTSCALE_A ,
7028 WINED3DRS_POINTSCALE_B ,
7029 WINED3DRS_POINTSCALE_C ,
7030 WINED3DRS_POINTSCALEENABLE ,
7031 WINED3DRS_POINTSIZE ,
7032 WINED3DRS_POINTSIZE_MAX ,
7033 WINED3DRS_POINTSIZE_MIN ,
7034 WINED3DRS_POINTSPRITEENABLE ,
7035 WINED3DRS_RANGEFOGENABLE ,
7036 WINED3DRS_SPECULARMATERIALSOURCE ,
7037 WINED3DRS_TWEENFACTOR ,
7038 WINED3DRS_VERTEXBLEND
7041 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
7042 WINED3DTSS_TEXCOORDINDEX ,
7043 WINED3DTSS_TEXTURETRANSFORMFLAGS
7046 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
7047 WINED3DSAMP_DMAPOFFSET