- Output a FIXME when a surface with dimensions not being a power of
[wine/dcerpc.git] / dlls / wined3d / device.c
blob7634b19113aa178212093fb86700ca4efc39299d
1 /*
2 * IWineD3DDevice implementation
4 * Copyright 2002-2005 Jason Edmeades
5 * Copyright 2003-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "config.h"
25 #include "wined3d_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
28 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
29 WINE_DECLARE_DEBUG_CHANNEL(d3d_fps);
30 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
31 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
33 /* helper macros */
34 #define D3DMEMCHECK(object, ppResult) if(NULL == object){ *ppResult = NULL; WARN("Out of memory\n"); return D3DERR_OUTOFVIDEOMEMORY;}
36 #define D3DCREATEOBJECTINSTANCE(object, type){ \
37 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
38 D3DMEMCHECK(object, pp##type); \
39 object->lpVtbl = &IWineD3D##type##_Vtbl; \
40 object->wineD3DDevice = This; \
41 object->parent = parent; \
42 object->ref = 1; \
43 *pp##type = (IWineD3D##type *) object; \
46 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype){ \
47 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
48 D3DMEMCHECK(object, pp##type); \
49 object->lpVtbl = &IWineD3D##type##_Vtbl; \
50 object->resource.wineD3DDevice = This; \
51 object->resource.parent = parent; \
52 object->resource.resourceType = d3dtype; \
53 object->resource.ref = 1; \
54 object->resource.pool = Pool; \
55 object->resource.format = Format; \
56 object->resource.usage = Usage; \
57 object->resource.size = 0; \
58 object->resource.allocatedMemory = 0; \
59 *pp##type = (IWineD3D##type *) object; \
62 #define D3DINITILIZEBASETEXTURE(_basetexture) { \
63 _basetexture.levels = Levels; \
64 _basetexture.filterType = (Usage & D3DUSAGE_AUTOGENMIPMAP) ? D3DTEXF_LINEAR : D3DTEXF_NONE; \
65 _basetexture.LOD = 0; \
68 /**********************************************************
69 * Global variable / Constants follow
70 **********************************************************/
71 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
73 /**********************************************************
74 * Utility functions follow
75 **********************************************************/
76 /* Convert the D3DLIGHT properties into equivalent gl lights */
77 void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
79 float quad_att;
80 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
81 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
83 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
84 glMatrixMode(GL_MODELVIEW);
85 glPushMatrix();
86 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
88 /* Diffuse: */
89 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
90 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
91 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
92 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
93 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
94 checkGLcall("glLightfv");
96 /* Specular */
97 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
98 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
99 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
100 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
101 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
102 checkGLcall("glLightfv");
104 /* Ambient */
105 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
106 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
107 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
108 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
109 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
110 checkGLcall("glLightfv");
112 /* Attenuation - Are these right? guessing... */
113 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
114 checkGLcall("glLightf");
115 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
116 checkGLcall("glLightf");
118 quad_att = 1.4/(lightInfo->OriginalParms.Range*lightInfo->OriginalParms.Range);
119 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
120 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
121 checkGLcall("glLightf");
123 switch (lightInfo->OriginalParms.Type) {
124 case D3DLIGHT_POINT:
125 /* Position */
126 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
127 checkGLcall("glLightfv");
128 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
129 checkGLcall("glLightf");
130 /* FIXME: Range */
131 break;
133 case D3DLIGHT_SPOT:
134 /* Position */
135 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
136 checkGLcall("glLightfv");
137 /* Direction */
138 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
139 checkGLcall("glLightfv");
140 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
141 checkGLcall("glLightf");
142 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
143 checkGLcall("glLightf");
144 /* FIXME: Range */
145 break;
147 case D3DLIGHT_DIRECTIONAL:
148 /* Direction */
149 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
150 checkGLcall("glLightfv");
151 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
152 checkGLcall("glLightf");
153 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
154 checkGLcall("glLightf");
155 break;
157 default:
158 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
161 /* Restore the modelview matrix */
162 glPopMatrix();
165 /* Apply the current values to the specified texture stage */
166 void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Stage, DWORD Flags) {
167 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
168 int i = 0;
169 float col[4];
170 BOOL changeTexture = TRUE;
172 TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
173 for (i = 1; i < HIGHEST_TEXTURE_STATE; i++) {
175 BOOL skip = FALSE;
177 switch (i) {
178 /* Performance: For texture states where multiples effect the outcome, only bother
179 applying the last one as it will pick up all the other values */
180 case D3DTSS_COLORARG0: /* Will be picked up when setting color op */
181 case D3DTSS_COLORARG1: /* Will be picked up when setting color op */
182 case D3DTSS_COLORARG2: /* Will be picked up when setting color op */
183 case D3DTSS_ALPHAARG0: /* Will be picked up when setting alpha op */
184 case D3DTSS_ALPHAARG1: /* Will be picked up when setting alpha op */
185 case D3DTSS_ALPHAARG2: /* Will be picked up when setting alpha op */
186 skip = TRUE;
187 break;
189 /* Performance: If the texture states only impact settings for the texture unit
190 (compared to the texture object) then there is no need to reapply them. The
191 only time they need applying is the first time, since we cheat and put the
192 values into the stateblock without applying.
193 Per-texture unit: texture function (eg. combine), ops and args
194 texture env color
195 texture generation settings
196 Note: Due to some special conditions there may be a need to do particular ones
197 of these, which is what the Flags allows */
198 case D3DTSS_COLOROP:
199 case D3DTSS_TEXCOORDINDEX:
200 if (!(Flags == REAPPLY_ALL)) skip=TRUE;
201 break;
203 case D3DTSS_ALPHAOP:
204 if (!(Flags & REAPPLY_ALPHAOP)) skip=TRUE;
205 break;
207 default:
208 skip = FALSE;
211 if (skip == FALSE) {
212 /* Performance: Only change to this texture if we have to */
213 if (changeTexture) {
214 /* Make appropriate texture active */
215 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
216 GLACTIVETEXTURE(Stage);
217 } else if (Stage > 0) {
218 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
220 changeTexture = FALSE;
223 /* Now apply the change */
224 IWineD3DDevice_SetTextureStageState(iface, Stage, i, This->stateBlock->textureState[Stage][i]);
228 /* Note the D3DRS value applies to all textures, but GL has one
229 * per texture, so apply it now ready to be used!
231 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
232 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
233 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
235 TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
238 /**********************************************************
239 * IUnknown parts follows
240 **********************************************************/
242 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
244 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
245 /* FIXME: This needs to extend an IWineD3DBaseObject */
247 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
248 if (IsEqualGUID(riid, &IID_IUnknown)
249 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
250 IUnknown_AddRef(iface);
251 *ppobj = This;
252 return D3D_OK;
255 return E_NOINTERFACE;
258 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
259 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
260 ULONG refCount = InterlockedIncrement(&This->ref);
262 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
263 return refCount;
266 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
267 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
268 ULONG refCount = InterlockedDecrement(&This->ref);
270 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
272 if (!refCount) {
273 /* TODO: Clean up all the surfaces and textures! */
274 /* FIXME: Create targets and state blocks in d3d8 */
275 if (((IWineD3DImpl *)This->wineD3D)->dxVersion > 8) { /*We don't create a state block in d3d8 yet*/
276 /* NOTE: You must release the parent if the objects was created via a callback
277 ** ***************************/
278 IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->stateBlock);
280 IWineD3D_Release(This->wineD3D);
281 HeapFree(GetProcessHeap(), 0, This);
283 return refCount;
286 /**********************************************************
287 * IWineD3DDevice implementation follows
288 **********************************************************/
289 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
290 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
291 *pParent = This->parent;
292 IUnknown_AddRef(This->parent);
293 return D3D_OK;
296 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
297 DWORD FVF, D3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
298 IUnknown *parent) {
299 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
300 IWineD3DVertexBufferImpl *object;
301 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
302 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, D3DRTYPE_VERTEXBUFFER)
304 object->resource.size = Size;
305 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
306 object->FVF = FVF;
308 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
309 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
311 return D3D_OK;
314 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
315 WINED3DFORMAT Format, D3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
316 HANDLE *sharedHandle, IUnknown *parent) {
317 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
318 IWineD3DIndexBufferImpl *object;
319 TRACE("(%p) Creating index buffer\n", This);
321 /* Allocate the storage for the device */
322 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,D3DRTYPE_INDEXBUFFER)
324 object->resource.size = Length;
325 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
327 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
328 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
329 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
331 return D3D_OK;
334 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, D3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
336 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
337 IWineD3DStateBlockImpl *object;
339 D3DCREATEOBJECTINSTANCE(object, StateBlock)
340 object->blockType = Type;
342 /* Special case - Used during initialization to produce a placeholder stateblock
343 so other functions called can update a state block */
344 if (Type == (D3DSTATEBLOCKTYPE) 0) {
345 /* Don't bother increasing the reference count otherwise a device will never
346 be freed due to circular dependencies */
347 return D3D_OK;
350 /* Otherwise, might as well set the whole state block to the appropriate values */
351 IWineD3DDevice_AddRef(iface);
352 memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
353 FIXME("unfinished - needs to set up changed and set attributes\n");
354 return D3D_OK;
358 /* ************************************
359 MSDN:
360 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
362 Discard
363 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
365 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.
367 ******************************** */
369 HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height, WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **ppSurface,D3DRESOURCETYPE Type, DWORD Usage, D3DPOOL Pool, D3DMULTISAMPLE_TYPE MultiSample ,DWORD MultisampleQuality, HANDLE* pSharedHandle, IUnknown *parent) {
370 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
371 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
372 unsigned int pow2Width, pow2Height;
374 TRACE("(%p) Create surface\n",This);
376 /** FIXME: Check ranges on the inputs are valid
377 * MSDN
378 * MultisampleQuality
379 * [in] Quality level. The valid range is between zero and one less than the level
380 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
381 * Passing a larger value returns the error D3DERR_INVALIDCALL. The MultisampleQuality
382 * values of paired render targets, depth stencil surfaces, and the MultiSample type
383 * must all match.
384 *******************************/
388 * TODO: Discard MSDN
389 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
391 * If this flag is set, the contents of the depth stencil buffer will be
392 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
393 * with a different depth surface.
395 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
396 ***************************/
398 if(MultisampleQuality < 0) {
399 FIXME("Invalid multisample level %ld \n", MultisampleQuality);
400 return D3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
403 if(MultisampleQuality > 0){
404 FIXME("MultisampleQuality set to %ld, bstituting 0 \n" , MultisampleQuality);
405 MultisampleQuality=0;
408 /* Non-power2 support */
410 /* Find the nearest pow2 match */
411 pow2Width = pow2Height = 1;
412 while (pow2Width < Width) pow2Width <<= 1;
413 while (pow2Height < Height) pow2Height <<= 1;
415 if(pow2Width > Width || pow2Height > Height){
416 FIXME("non-power-two textures unsupported\n"); /* OpenGL provides support for these gratis */
417 return D3DERR_NOTAVAILABLE;
421 /** TODO: Check against the maximum texture sizes supported by the video card **/
423 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,D3DRTYPE_SURFACE)
424 object->container = (IUnknown*) This;
426 object->currentDesc.Width = Width;
427 object->currentDesc.Height = Height;
428 object->currentDesc.Level = Level;
429 object->currentDesc.MultiSampleType = MultiSample;
430 object->currentDesc.MultiSampleQuality = MultisampleQuality;
431 object->discard = Discard;
432 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
434 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
435 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
436 * space!
437 *********************************/
438 if (Format == WINED3DFMT_DXT1) {
439 /* DXT1 is half byte per pixel */
440 object->resource.size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4)) / 2;
442 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
443 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
444 object->resource.size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4));
445 } else {
446 object->resource.size = (Width * object->bytesPerPixel) * Height;
449 TRACE("Pool %d %d %d %d",Pool, D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM);
451 #if 0
452 /* TODO: Check that we have enough video ram left */
453 if(Pool == D3DPOOL_DEFAULT && IWineD3DDevice_GetAvailableTextureMem(iface) <= object->currentDesc.Size){
454 TRACE("Out of 'bogus' video memory\n");
455 HeapFree(GetProcessHeap(),0,object);
456 *ppSurface = NULL;
457 return D3DERR_OUTOFVIDEOMEMORY;
459 #endif
461 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
462 * this function is too deap to need to care about things like this.
463 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
464 * ****************************************/
465 switch(Pool) {
466 case D3DPOOL_SCRATCH:
467 if(Lockable == FALSE)
468 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
469 which are mutually exclusive, setting lockable to true\n");
470 Lockable = TRUE;
471 break;
472 case D3DPOOL_SYSTEMMEM:
473 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
474 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
475 case D3DPOOL_MANAGED:
476 if(Usage == D3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
477 Usage of DYNAMIC which are mutually exclusive, not doing \
478 anything just telling you.\n");
479 break;
480 case D3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
481 if(!(Usage & D3DUSAGE_DYNAMIC) && !(Usage & D3DUSAGE_RENDERTARGET)
482 && !(Usage && D3DUSAGE_DEPTHSTENCIL ) && Lockable == TRUE)
483 FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
484 break;
485 default:
486 FIXME("(%p) Unknown pool %d\n", This, Pool);
487 break;
490 if (Usage & D3DUSAGE_RENDERTARGET && Pool != D3DPOOL_DEFAULT){
491 FIXME("Trying to create a render target that isn't in the default pool\n");
495 object->locked = FALSE;
496 object->lockable = (WINED3DFMT_D16_LOCKABLE == Format) ? TRUE : Lockable;
497 /* TODO: memory management */
498 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
499 if(object->resource.allocatedMemory == NULL ) {
500 FIXME("Out of memory!\n");
501 HeapFree(GetProcessHeap(),0,object);
502 *ppSurface = NULL;
503 return D3DERR_OUTOFVIDEOMEMORY;
507 IWineD3DSurface_CleanDirtyRect(*ppSurface);
508 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
509 This, Width, Height, Format, debug_d3dformat(Format),
510 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
511 return D3D_OK;
515 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
516 DWORD Usage, WINED3DFORMAT Format, D3DPOOL Pool,
517 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
518 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
520 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
521 IWineD3DTextureImpl *object;
522 unsigned int i;
523 UINT tmpW;
524 UINT tmpH;
525 HRESULT hr;
527 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) .... \n", This, Width, Height, Levels, Usage);
529 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, D3DRTYPE_TEXTURE);
530 D3DINITILIZEBASETEXTURE(object->baseTexture);
531 object->width = Width;
532 object->height = Height;
534 /* Calculate levels for mip mapping */
535 if (Levels == 0) {
536 TRACE("calculating levels %d\n", object->baseTexture.levels);
537 object->baseTexture.levels++;
538 tmpW = Width;
539 tmpH = Height;
540 while (tmpW > 1 && tmpH > 1) {
541 tmpW = max(1, tmpW >> 1);
542 tmpH = max(1, tmpH >> 1);
543 object->baseTexture.levels++;
545 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
548 /* Generate all the surfaces */
549 tmpW = Width;
550 tmpH = Height;
551 for (i = 0; i < object->baseTexture.levels; i++)
553 /* use the callback to create the texture surface */
554 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
555 if(hr!= D3D_OK){
556 int j;
557 FIXME("Failed to create surface %p \n",object);
558 /* clean up */
559 for(j=0;j<i;j++){
560 IWineD3DSurface_Release(object->surfaces[j]);
562 /* heap free object */
563 HeapFree(GetProcessHeap(),0,object);
565 *ppTexture = NULL;
566 return hr;
569 IWineD3DSurface_SetContainer(object->surfaces[i], (IUnknown *)object);
570 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
571 /* calculate the next mipmap level */
572 tmpW = max(1, tmpW >> 1);
573 tmpH = max(1, tmpH >> 1);
576 TRACE("(%p) : Created texture %p\n", This, object);
577 return D3D_OK;
580 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
581 UINT Width, UINT Height, UINT Depth,
582 UINT Levels, DWORD Usage,
583 WINED3DFORMAT Format, D3DPOOL Pool,
584 IWineD3DVolumeTexture** ppVolumeTexture,
585 HANDLE* pSharedHandle, IUnknown *parent,
586 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
588 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
589 IWineD3DVolumeTextureImpl *object;
590 unsigned int i;
591 UINT tmpW;
592 UINT tmpH;
593 UINT tmpD;
595 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, D3DRTYPE_VOLUMETEXTURE);
596 D3DINITILIZEBASETEXTURE(object->baseTexture);
598 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
599 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
601 object->width = Width;
602 object->height = Height;
603 object->depth = Depth;
605 /* Calculate levels for mip mapping */
606 if (Levels == 0) {
607 object->baseTexture.levels++;
608 tmpW = Width;
609 tmpH = Height;
610 tmpD = Depth;
611 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
612 tmpW = max(1, tmpW >> 1);
613 tmpH = max(1, tmpH >> 1);
614 tmpD = max(1, tmpD >> 1);
615 object->baseTexture.levels++;
617 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
620 /* Generate all the surfaces */
621 tmpW = Width;
622 tmpH = Height;
623 tmpD = Depth;
625 for (i = 0; i < object->baseTexture.levels; i++)
627 /* Create the volume */
628 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
629 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
630 IWineD3DVolume_SetContainer(object->volumes[i], (IUnknown *)object);
632 tmpW = max(1, tmpW >> 1);
633 tmpH = max(1, tmpH >> 1);
634 tmpD = max(1, tmpD >> 1);
637 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
638 TRACE("(%p) : Created volume texture %p\n", This, object);
639 return D3D_OK;
642 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
643 UINT Width, UINT Height, UINT Depth,
644 DWORD Usage,
645 WINED3DFORMAT Format, D3DPOOL Pool,
646 IWineD3DVolume** ppVolume,
647 HANDLE* pSharedHandle, IUnknown *parent) {
649 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
650 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
652 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, D3DRTYPE_VOLUME)
654 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
655 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
657 object->currentDesc.Width = Width;
658 object->currentDesc.Height = Height;
659 object->currentDesc.Depth = Depth;
660 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
662 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
663 object->resource.size = (Width * object->bytesPerPixel) * Height * Depth;
664 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
665 object->lockable = TRUE;
666 object->locked = FALSE;
667 memset(&object->lockedBox, 0, sizeof(D3DBOX));
668 object->dirty = FALSE;
669 return IWineD3DVolume_CleanDirtyBox((IWineD3DVolume *) object);
672 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
673 UINT Levels, DWORD Usage,
674 WINED3DFORMAT Format, D3DPOOL Pool,
675 IWineD3DCubeTexture** ppCubeTexture,
676 HANDLE* pSharedHandle, IUnknown *parent,
677 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
679 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
680 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
681 unsigned int i,j;
682 UINT tmpW;
683 HRESULT hr;
685 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, D3DRTYPE_CUBETEXTURE);
686 D3DINITILIZEBASETEXTURE(object->baseTexture);
688 TRACE("(%p) Create Cube Texture \n", This);
690 object->edgeLength = EdgeLength;
692 /* Calculate levels for mip mapping */
693 if (Levels == 0) {
694 object->baseTexture.levels++;
695 tmpW = EdgeLength;
696 while (tmpW > 1) {
697 tmpW = max(1, tmpW / 2);
698 object->baseTexture.levels++;
700 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
703 /* Generate all the surfaces */
704 tmpW = EdgeLength;
705 for (i = 0; i < object->baseTexture.levels; i++) {
707 /* Create the 6 faces */
708 for (j = 0; j < 6; j++) {
710 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
711 i /* Level */, &object->surfaces[j][i],pSharedHandle);
713 if(hr!= D3D_OK){
714 /* clean up */
715 int k;
716 int l;
717 for (l=0;l<j;l++) {
718 IWineD3DSurface_Release(object->surfaces[j][i]);
720 for (k=0;k<i;k++) {
721 for (l=0;l<6;l++) {
722 IWineD3DSurface_Release(object->surfaces[l][j]);
726 FIXME("(%p) Failed to create surface\n",object);
727 HeapFree(GetProcessHeap(),0,object);
728 *ppCubeTexture = NULL;
729 return hr;
731 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IUnknown *)object);
732 TRACE("Created surface level %d @ %p, \n", i, object->surfaces[j][i]);
734 tmpW = max(1, tmpW >> 1);
737 TRACE("(%p) : Created Cube Texture %p\n", This, object);
738 *ppCubeTexture = (IWineD3DCubeTexture *) object;
739 return D3D_OK;
742 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent){
743 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
744 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
746 if(NULL == ppQuery){
747 /* Just a check to see if we support this type of query */
748 HRESULT hr = D3DERR_NOTAVAILABLE;
749 /* Lie and say everything is good (we can return ok fake data from a stub) */
750 switch(Type){
751 case WINED3DQUERYTYPE_VCACHE:
752 case WINED3DQUERYTYPE_RESOURCEMANAGER:
753 case WINED3DQUERYTYPE_VERTEXSTATS:
754 case WINED3DQUERYTYPE_EVENT:
755 case WINED3DQUERYTYPE_OCCLUSION:
756 case WINED3DQUERYTYPE_TIMESTAMP:
757 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
758 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
759 case WINED3DQUERYTYPE_PIPELINETIMINGS:
760 case WINED3DQUERYTYPE_INTERFACETIMINGS:
761 case WINED3DQUERYTYPE_VERTEXTIMINGS:
762 case WINED3DQUERYTYPE_PIXELTIMINGS:
763 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
764 case WINED3DQUERYTYPE_CACHEUTILIZATION:
765 hr = D3D_OK;
766 break;
767 default:
768 FIXME("(%p) Unhandled query type %d\n",This , Type);
770 FIXME("(%p) : Stub request for query type %d returned %ld\n", This, Type, hr);
771 return hr;
774 D3DCREATEOBJECTINSTANCE(object, Query)
775 object->type = Type;
776 object->extendedData = 0;
777 TRACE("(%p) : Created Query %p\n", This, object);
778 return D3D_OK;
781 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
782 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, void** ppSwapChain,
783 IUnknown* parent,
784 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
785 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil){
786 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
787 *ppSwapChain = NULL;
788 FIXME("(%p) : Stub\n",This);
789 return D3D_OK;
792 /** NOTE: These are ahead of the other getters and setters to save using a forward declartion **/
793 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
794 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
796 FIXME("(%p) : Stub\n",This);
797 return 1;
800 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, void** pSwapChain) {
801 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
803 FIXME("(%p) : Stub\n",This);
804 return D3D_OK;
807 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters){
808 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
810 FIXME("(%p) : Stub\n",This);
811 return D3D_OK;
815 /*****
816 * Vertex Declaration
817 *****/
818 /* TODO: Get ridd of thease and put the functions in the IWineD3DVertexDeclaration interface */
819 #if 1
820 extern HRESULT IWineD3DVertexDeclarationImpl_ParseDeclaration8(IWineD3DDeviceImpl * This, const DWORD* pDecl, IWineD3DVertexDeclarationImpl * object);
821 extern HRESULT IWineD3DVertexDeclarationImpl_ParseDeclaration9(IWineD3DDeviceImpl * This, const D3DVERTEXELEMENT9* pDecl, IWineD3DVertexDeclarationImpl * object);
824 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
825 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
826 IWineD3DVertexDeclarationImpl *object = NULL;
827 HRESULT hr = D3D_OK;
829 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
830 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
831 object->allFVF = 0;
833 if (8 == ((IWineD3DImpl *)This->wineD3D)->dxVersion) {
834 /** @TODO */
835 hr = IWineD3DVertexDeclarationImpl_ParseDeclaration8(This, (const DWORD*) pDeclaration, object);
836 } else {
837 hr = IWineD3DVertexDeclarationImpl_ParseDeclaration9(This, (const D3DVERTEXELEMENT9*) pDeclaration, object);
840 return hr;
844 #else
845 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration8(IWineD3DDevice* iface, const DWORD* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent){
846 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
847 IWineD3DVertexDeclarationImpl *object = NULL; /* NOTE: impl allowed, this is a create */
848 HRESULT hr = D3D_OK;
849 /* TODO: replace impl usage with a call to Version*/
850 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
851 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
852 object->allFVF = 0;
853 /* TODO: get ridd of the impl usage, we should only be using interfaces */
854 hr = IWineD3DVertexDeclarationImpl_ParseDeclaration8(This, pDeclaration, object);
856 return hr;
859 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration9(IWineD3DDevice* iface, const D3DVERTEXELEMENT9* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent){
860 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
861 IWineD3DVertexDeclarationImpl *object = NULL; /* NOTE: impl allowed, this is a create */
862 HRESULT hr = D3D_OK;
863 /* TODO: replace impl usage with a call to Version*/
864 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
865 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
866 object->allFVF = 0;
867 /* TODO: get ridd of the impl usage, we should only be using interfaces */
868 hr = IWineD3DVertexDeclarationImpl_ParseDeclaration9(This, pDeclaration, object);
870 return hr;
872 #endif
874 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
875 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DVertexShader** ppVertexShader, IUnknown *parent){
876 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
877 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
878 D3DCREATEOBJECTINSTANCE(object, VertexShader)
879 object->function = pFunction;
880 FIXME("(%p) : STUB: Created Vertex shader %p\n", This, ppVertexShader);
881 return D3D_OK;
885 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DPixelShader** ppPixelShader, IUnknown *parent){
886 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
887 FIXME("(%p) : Stub\n", This);
888 return D3D_OK;
891 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice* iface, IWineD3D** ppD3D){
892 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
893 *ppD3D= This->wineD3D;
894 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
895 IWineD3D_AddRef(*ppD3D);
896 return D3D_OK;
900 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
901 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
902 FIXME("Stub :(%p) returning 64Mib\n", This);
903 return 64*1024*1024;
907 /*****
908 * Get / Set FVF
909 *****/
910 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
911 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
913 /* Update the current state block */
914 This->updateStateBlock->fvf = fvf;
915 This->updateStateBlock->changed.fvf = TRUE;
916 This->updateStateBlock->set.fvf = TRUE;
918 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
920 /* No difference if recording or not */
921 return D3D_OK;
923 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
924 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
925 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
926 *pfvf = This->stateBlock->fvf;
927 return D3D_OK;
930 /*****
931 * Get / Set Stream Source
932 *****/
933 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
934 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
935 IWineD3DVertexBuffer *oldSrc;
937 oldSrc = This->stateBlock->stream_source[StreamNumber];
938 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
940 This->updateStateBlock->changed.stream_source[StreamNumber] = TRUE;
941 This->updateStateBlock->set.stream_source[StreamNumber] = TRUE;
942 This->updateStateBlock->stream_stride[StreamNumber] = Stride;
943 This->updateStateBlock->stream_source[StreamNumber] = pStreamData;
944 This->updateStateBlock->stream_offset[StreamNumber] = OffsetInBytes;
946 /* Handle recording of state blocks */
947 if (This->isRecordingState) {
948 TRACE("Recording... not performing anything\n");
949 return D3D_OK;
952 /* Not recording... */
953 if (oldSrc != NULL) IWineD3DVertexBuffer_Release(oldSrc);
954 if (pStreamData != NULL) IWineD3DVertexBuffer_AddRef(pStreamData);
956 return D3D_OK;
959 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
960 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
962 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->stateBlock->stream_source[StreamNumber], This->stateBlock->stream_stride[StreamNumber]);
963 *pStream = This->stateBlock->stream_source[StreamNumber];
964 *pStride = This->stateBlock->stream_stride[StreamNumber];
965 *pOffset = This->stateBlock->stream_offset[StreamNumber];
966 if (*pStream != NULL) IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
967 return D3D_OK;
970 /*Should be quite easy, just an extension of vertexdata
971 ref...
972 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
974 The divider is a bit odd though
976 VertexOffset = StartVertex / Divider * StreamStride +
977 VertexIndex / Divider * StreamStride + StreamOffset
980 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider){
981 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
983 FIXME("(%p) : stub\n", This);
984 return D3D_OK;
987 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider){
988 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
990 FIXME("(%p) : stub\n", This);
991 return D3D_OK;
995 /*****
996 * Get / Set & Multipy Transform
997 *****/
998 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
999 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1001 /* Most of this routine, comments included copied from ddraw tree initially: */
1002 TRACE("(%p) : Transform State=%d\n", This, d3dts);
1004 /* Handle recording of state blocks */
1005 if (This->isRecordingState) {
1006 TRACE("Recording... not performing anything\n");
1007 This->updateStateBlock->changed.transform[d3dts] = TRUE;
1008 This->updateStateBlock->set.transform[d3dts] = TRUE;
1009 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1010 return D3D_OK;
1014 * If the new matrix is the same as the current one,
1015 * we cut off any further processing. this seems to be a reasonable
1016 * optimization because as was noticed, some apps (warcraft3 for example)
1017 * tend towards setting the same matrix repeatedly for some reason.
1019 * From here on we assume that the new matrix is different, wherever it matters.
1021 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1022 TRACE("The app is setting the same matrix over again\n");
1023 return D3D_OK;
1024 } else {
1025 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1029 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1030 where ViewMat = Camera space, WorldMat = world space.
1032 In OpenGL, camera and world space is combined into GL_MODELVIEW
1033 matrix. The Projection matrix stay projection matrix.
1036 /* Capture the times we can just ignore the change for now */
1037 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1038 This->modelview_valid = FALSE;
1039 return D3D_OK;
1041 } else if (d3dts == D3DTS_PROJECTION) {
1042 This->proj_valid = FALSE;
1043 return D3D_OK;
1045 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1046 /* Indexed Vertex Blending Matrices 256 -> 511 */
1047 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1048 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1049 return D3D_OK;
1052 /* Now we really are going to have to change a matrix */
1053 ENTER_GL();
1055 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1056 if (d3dts < GL_LIMITS(textures)) {
1057 int tex = d3dts - D3DTS_TEXTURE0;
1058 GLACTIVETEXTURE(tex);
1059 set_texture_matrix((float *)lpmatrix,
1060 This->updateStateBlock->textureState[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
1063 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1064 unsigned int k;
1066 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1067 * NOTE: We have to reset the positions even if the light/plane is not currently
1068 * enabled, since the call to enable it will not reset the position.
1069 * NOTE2: Apparently texture transforms do NOT need reapplying
1072 PLIGHTINFOEL *lightChain = NULL;
1073 This->modelview_valid = FALSE;
1074 This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
1076 glMatrixMode(GL_MODELVIEW);
1077 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1078 glPushMatrix();
1079 glLoadMatrixf((float *)lpmatrix);
1080 checkGLcall("glLoadMatrixf(...)");
1082 /* Reset lights */
1083 lightChain = This->stateBlock->lights;
1084 while (lightChain && lightChain->glIndex != -1) {
1085 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1086 checkGLcall("glLightfv posn");
1087 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1088 checkGLcall("glLightfv dirn");
1089 lightChain = lightChain->next;
1092 /* Reset Clipping Planes if clipping is enabled */
1093 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1094 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1095 checkGLcall("glClipPlane");
1097 glPopMatrix();
1099 } else { /* What was requested!?? */
1100 WARN("invalid matrix specified: %i\n", d3dts);
1103 /* Release lock, all done */
1104 LEAVE_GL();
1105 return D3D_OK;
1108 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1109 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1110 TRACE("(%p) : for Transform State %d\n", This, State);
1111 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1112 return D3D_OK;
1115 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1116 D3DMATRIX *mat = NULL;
1117 D3DMATRIX temp;
1119 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1120 * below means it will be recorded in a state block change, but it
1121 * works regardless where it is recorded.
1122 * If this is found to be wrong, change to StateBlock.
1124 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1125 TRACE("(%p) : For state %u\n", This, State);
1127 if (State < HIGHEST_TRANSFORMSTATE)
1129 mat = &This->updateStateBlock->transforms[State];
1130 } else {
1131 FIXME("Unhandled transform state!!\n");
1134 /* Copied from ddraw code: */
1135 temp.u.s._11 = (mat->u.s._11 * pMatrix->u.s._11) + (mat->u.s._21 * pMatrix->u.s._12) + (mat->u.s._31 * pMatrix->u.s._13) + (mat->u.s._41 * pMatrix->u.s._14);
1136 temp.u.s._21 = (mat->u.s._11 * pMatrix->u.s._21) + (mat->u.s._21 * pMatrix->u.s._22) + (mat->u.s._31 * pMatrix->u.s._23) + (mat->u.s._41 * pMatrix->u.s._24);
1137 temp.u.s._31 = (mat->u.s._11 * pMatrix->u.s._31) + (mat->u.s._21 * pMatrix->u.s._32) + (mat->u.s._31 * pMatrix->u.s._33) + (mat->u.s._41 * pMatrix->u.s._34);
1138 temp.u.s._41 = (mat->u.s._11 * pMatrix->u.s._41) + (mat->u.s._21 * pMatrix->u.s._42) + (mat->u.s._31 * pMatrix->u.s._43) + (mat->u.s._41 * pMatrix->u.s._44);
1140 temp.u.s._12 = (mat->u.s._12 * pMatrix->u.s._11) + (mat->u.s._22 * pMatrix->u.s._12) + (mat->u.s._32 * pMatrix->u.s._13) + (mat->u.s._42 * pMatrix->u.s._14);
1141 temp.u.s._22 = (mat->u.s._12 * pMatrix->u.s._21) + (mat->u.s._22 * pMatrix->u.s._22) + (mat->u.s._32 * pMatrix->u.s._23) + (mat->u.s._42 * pMatrix->u.s._24);
1142 temp.u.s._32 = (mat->u.s._12 * pMatrix->u.s._31) + (mat->u.s._22 * pMatrix->u.s._32) + (mat->u.s._32 * pMatrix->u.s._33) + (mat->u.s._42 * pMatrix->u.s._34);
1143 temp.u.s._42 = (mat->u.s._12 * pMatrix->u.s._41) + (mat->u.s._22 * pMatrix->u.s._42) + (mat->u.s._32 * pMatrix->u.s._43) + (mat->u.s._42 * pMatrix->u.s._44);
1145 temp.u.s._13 = (mat->u.s._13 * pMatrix->u.s._11) + (mat->u.s._23 * pMatrix->u.s._12) + (mat->u.s._33 * pMatrix->u.s._13) + (mat->u.s._43 * pMatrix->u.s._14);
1146 temp.u.s._23 = (mat->u.s._13 * pMatrix->u.s._21) + (mat->u.s._23 * pMatrix->u.s._22) + (mat->u.s._33 * pMatrix->u.s._23) + (mat->u.s._43 * pMatrix->u.s._24);
1147 temp.u.s._33 = (mat->u.s._13 * pMatrix->u.s._31) + (mat->u.s._23 * pMatrix->u.s._32) + (mat->u.s._33 * pMatrix->u.s._33) + (mat->u.s._43 * pMatrix->u.s._34);
1148 temp.u.s._43 = (mat->u.s._13 * pMatrix->u.s._41) + (mat->u.s._23 * pMatrix->u.s._42) + (mat->u.s._33 * pMatrix->u.s._43) + (mat->u.s._43 * pMatrix->u.s._44);
1150 temp.u.s._14 = (mat->u.s._14 * pMatrix->u.s._11) + (mat->u.s._24 * pMatrix->u.s._12) + (mat->u.s._34 * pMatrix->u.s._13) + (mat->u.s._44 * pMatrix->u.s._14);
1151 temp.u.s._24 = (mat->u.s._14 * pMatrix->u.s._21) + (mat->u.s._24 * pMatrix->u.s._22) + (mat->u.s._34 * pMatrix->u.s._23) + (mat->u.s._44 * pMatrix->u.s._24);
1152 temp.u.s._34 = (mat->u.s._14 * pMatrix->u.s._31) + (mat->u.s._24 * pMatrix->u.s._32) + (mat->u.s._34 * pMatrix->u.s._33) + (mat->u.s._44 * pMatrix->u.s._34);
1153 temp.u.s._44 = (mat->u.s._14 * pMatrix->u.s._41) + (mat->u.s._24 * pMatrix->u.s._42) + (mat->u.s._34 * pMatrix->u.s._43) + (mat->u.s._44 * pMatrix->u.s._44);
1155 /* Apply change via set transform - will reapply to eg. lights this way */
1156 IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
1157 return D3D_OK;
1160 /*****
1161 * Get / Set Light
1162 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
1163 *****/
1164 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1165 you can reference any indexes you want as long as that number max are enabled at any
1166 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1167 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1168 but when recording, just build a chain pretty much of commands to be replayed. */
1170 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
1171 float rho;
1172 PLIGHTINFOEL *object, *temp;
1174 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1175 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1177 /* If recording state block, just add to end of lights chain */
1178 if (This->isRecordingState) {
1179 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1180 if (NULL == object) {
1181 return D3DERR_OUTOFVIDEOMEMORY;
1183 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1184 object->OriginalIndex = Index;
1185 object->glIndex = -1;
1186 object->changed = TRUE;
1188 /* Add to the END of the chain of lights changes to be replayed */
1189 if (This->updateStateBlock->lights == NULL) {
1190 This->updateStateBlock->lights = object;
1191 } else {
1192 temp = This->updateStateBlock->lights;
1193 while (temp->next != NULL) temp=temp->next;
1194 temp->next = object;
1196 TRACE("Recording... not performing anything more\n");
1197 return D3D_OK;
1200 /* Ok, not recording any longer so do real work */
1201 object = This->stateBlock->lights;
1202 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1204 /* If we didn't find it in the list of lights, time to add it */
1205 if (object == NULL) {
1206 PLIGHTINFOEL *insertAt,*prevPos;
1208 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1209 if (NULL == object) {
1210 return D3DERR_OUTOFVIDEOMEMORY;
1212 object->OriginalIndex = Index;
1213 object->glIndex = -1;
1215 /* Add it to the front of list with the idea that lights will be changed as needed
1216 BUT after any lights currently assigned GL indexes */
1217 insertAt = This->stateBlock->lights;
1218 prevPos = NULL;
1219 while (insertAt != NULL && insertAt->glIndex != -1) {
1220 prevPos = insertAt;
1221 insertAt = insertAt->next;
1224 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1225 This->stateBlock->lights = object;
1226 } else if (insertAt == NULL) { /* End of list */
1227 prevPos->next = object;
1228 object->prev = prevPos;
1229 } else { /* Middle of chain */
1230 if (prevPos == NULL) {
1231 This->stateBlock->lights = object;
1232 } else {
1233 prevPos->next = object;
1235 object->prev = prevPos;
1236 object->next = insertAt;
1237 insertAt->prev = object;
1241 /* Initialze the object */
1242 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,
1243 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1244 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1245 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1246 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1247 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1248 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1250 /* Save away the information */
1251 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1253 switch (pLight->Type) {
1254 case D3DLIGHT_POINT:
1255 /* Position */
1256 object->lightPosn[0] = pLight->Position.x;
1257 object->lightPosn[1] = pLight->Position.y;
1258 object->lightPosn[2] = pLight->Position.z;
1259 object->lightPosn[3] = 1.0f;
1260 object->cutoff = 180.0f;
1261 /* FIXME: Range */
1262 break;
1264 case D3DLIGHT_DIRECTIONAL:
1265 /* Direction */
1266 object->lightPosn[0] = -pLight->Direction.x;
1267 object->lightPosn[1] = -pLight->Direction.y;
1268 object->lightPosn[2] = -pLight->Direction.z;
1269 object->lightPosn[3] = 0.0;
1270 object->exponent = 0.0f;
1271 object->cutoff = 180.0f;
1272 break;
1274 case D3DLIGHT_SPOT:
1275 /* Position */
1276 object->lightPosn[0] = pLight->Position.x;
1277 object->lightPosn[1] = pLight->Position.y;
1278 object->lightPosn[2] = pLight->Position.z;
1279 object->lightPosn[3] = 1.0;
1281 /* Direction */
1282 object->lightDirn[0] = pLight->Direction.x;
1283 object->lightDirn[1] = pLight->Direction.y;
1284 object->lightDirn[2] = pLight->Direction.z;
1285 object->lightDirn[3] = 1.0;
1288 * opengl-ish and d3d-ish spot lights use too different models for the
1289 * light "intensity" as a function of the angle towards the main light direction,
1290 * so we only can approximate very roughly.
1291 * however spot lights are rather rarely used in games (if ever used at all).
1292 * furthermore if still used, probably nobody pays attention to such details.
1294 if (pLight->Falloff == 0) {
1295 rho = 6.28f;
1296 } else {
1297 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1299 if (rho < 0.0001) rho = 0.0001f;
1300 object->exponent = -0.3/log(cos(rho/2));
1301 object->cutoff = pLight->Phi*90/M_PI;
1303 /* FIXME: Range */
1304 break;
1306 default:
1307 FIXME("Unrecognized light type %d\n", pLight->Type);
1310 /* Update the live definitions if the light is currently assigned a glIndex */
1311 if (object->glIndex != -1) {
1312 setup_light(iface, object->glIndex, object);
1314 return D3D_OK;
1317 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
1318 PLIGHTINFOEL *lightInfo = NULL;
1319 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1320 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1322 /* Locate the light in the live lights */
1323 lightInfo = This->stateBlock->lights;
1324 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1326 if (lightInfo == NULL) {
1327 TRACE("Light information requested but light not defined\n");
1328 return D3DERR_INVALIDCALL;
1331 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
1332 return D3D_OK;
1335 /*****
1336 * Get / Set Light Enable
1337 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
1338 *****/
1339 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
1340 PLIGHTINFOEL *lightInfo = NULL;
1341 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1342 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1344 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1345 if (This->isRecordingState) {
1346 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1347 if (NULL == lightInfo) {
1348 return D3DERR_OUTOFVIDEOMEMORY;
1350 lightInfo->OriginalIndex = Index;
1351 lightInfo->glIndex = -1;
1352 lightInfo->enabledChanged = TRUE;
1354 /* Add to the END of the chain of lights changes to be replayed */
1355 if (This->updateStateBlock->lights == NULL) {
1356 This->updateStateBlock->lights = lightInfo;
1357 } else {
1358 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
1359 while (temp->next != NULL) temp=temp->next;
1360 temp->next = lightInfo;
1362 TRACE("Recording... not performing anything more\n");
1363 return D3D_OK;
1366 /* Not recording... So, locate the light in the live lights */
1367 lightInfo = This->stateBlock->lights;
1368 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1370 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1371 if (lightInfo == NULL) {
1372 D3DLIGHT9 lightParms;
1373 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1374 wait until someone confirms it seems to work! */
1375 TRACE("Light enabled requested but light not defined, so defining one!\n");
1376 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1377 lightParms.Diffuse.r = 1.0;
1378 lightParms.Diffuse.g = 1.0;
1379 lightParms.Diffuse.b = 1.0;
1380 lightParms.Diffuse.a = 0.0;
1381 lightParms.Specular.r = 0.0;
1382 lightParms.Specular.g = 0.0;
1383 lightParms.Specular.b = 0.0;
1384 lightParms.Specular.a = 0.0;
1385 lightParms.Ambient.r = 0.0;
1386 lightParms.Ambient.g = 0.0;
1387 lightParms.Ambient.b = 0.0;
1388 lightParms.Ambient.a = 0.0;
1389 lightParms.Position.x = 0.0;
1390 lightParms.Position.y = 0.0;
1391 lightParms.Position.z = 0.0;
1392 lightParms.Direction.x = 0.0;
1393 lightParms.Direction.y = 0.0;
1394 lightParms.Direction.z = 1.0;
1395 lightParms.Range = 0.0;
1396 lightParms.Falloff = 0.0;
1397 lightParms.Attenuation0 = 0.0;
1398 lightParms.Attenuation1 = 0.0;
1399 lightParms.Attenuation2 = 0.0;
1400 lightParms.Theta = 0.0;
1401 lightParms.Phi = 0.0;
1402 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
1404 /* Search for it again! Should be fairly quick as near head of list */
1405 lightInfo = This->stateBlock->lights;
1406 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1407 if (lightInfo == NULL) {
1408 FIXME("Adding default lights has failed dismally\n");
1409 return D3DERR_INVALIDCALL;
1413 /* OK, we now have a light... */
1414 if (Enable == FALSE) {
1416 /* If we are disabling it, check it was enabled, and
1417 still only do something if it has assigned a glIndex (which it should have!) */
1418 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
1419 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1420 ENTER_GL();
1421 glDisable(GL_LIGHT0 + lightInfo->glIndex);
1422 checkGLcall("glDisable GL_LIGHT0+Index");
1423 LEAVE_GL();
1424 } else {
1425 TRACE("Nothing to do as light was not enabled\n");
1427 lightInfo->lightEnabled = FALSE;
1428 } else {
1430 /* We are enabling it. If it is enabled, it's really simple */
1431 if (lightInfo->lightEnabled) {
1432 /* nop */
1433 TRACE("Nothing to do as light was enabled\n");
1435 /* If it already has a glIndex, it's still simple */
1436 } else if (lightInfo->glIndex != -1) {
1437 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
1438 lightInfo->lightEnabled = TRUE;
1439 ENTER_GL();
1440 glEnable(GL_LIGHT0 + lightInfo->glIndex);
1441 checkGLcall("glEnable GL_LIGHT0+Index already setup");
1442 LEAVE_GL();
1444 /* Otherwise got to find space - lights are ordered gl indexes first */
1445 } else {
1446 PLIGHTINFOEL *bsf = NULL;
1447 PLIGHTINFOEL *pos = This->stateBlock->lights;
1448 PLIGHTINFOEL *prev = NULL;
1449 int Index= 0;
1450 int glIndex = -1;
1452 /* Try to minimize changes as much as possible */
1453 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
1455 /* Try to remember which index can be replaced if necessary */
1456 if (bsf==NULL && pos->lightEnabled == FALSE) {
1457 /* Found a light we can replace, save as best replacement */
1458 bsf = pos;
1461 /* Step to next space */
1462 prev = pos;
1463 pos = pos->next;
1464 Index ++;
1467 /* If we have too many active lights, fail the call */
1468 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
1469 FIXME("Program requests too many concurrent lights\n");
1470 return D3DERR_INVALIDCALL;
1472 /* If we have allocated all lights, but not all are enabled,
1473 reuse one which is not enabled */
1474 } else if (Index == This->maxConcurrentLights) {
1475 /* use bsf - Simply swap the new light and the BSF one */
1476 PLIGHTINFOEL *bsfNext = bsf->next;
1477 PLIGHTINFOEL *bsfPrev = bsf->prev;
1479 /* Sort out ends */
1480 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
1481 if (bsf->prev != NULL) {
1482 bsf->prev->next = lightInfo;
1483 } else {
1484 This->stateBlock->lights = lightInfo;
1487 /* If not side by side, lots of chains to update */
1488 if (bsf->next != lightInfo) {
1489 lightInfo->prev->next = bsf;
1490 bsf->next->prev = lightInfo;
1491 bsf->next = lightInfo->next;
1492 bsf->prev = lightInfo->prev;
1493 lightInfo->next = bsfNext;
1494 lightInfo->prev = bsfPrev;
1496 } else {
1497 /* Simple swaps */
1498 bsf->prev = lightInfo;
1499 bsf->next = lightInfo->next;
1500 lightInfo->next = bsf;
1501 lightInfo->prev = bsfPrev;
1505 /* Update states */
1506 glIndex = bsf->glIndex;
1507 bsf->glIndex = -1;
1508 lightInfo->glIndex = glIndex;
1509 lightInfo->lightEnabled = TRUE;
1511 /* Finally set up the light in gl itself */
1512 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
1513 ENTER_GL();
1514 setup_light(iface, glIndex, lightInfo);
1515 glEnable(GL_LIGHT0 + glIndex);
1516 checkGLcall("glEnable GL_LIGHT0 new setup");
1517 LEAVE_GL();
1519 /* If we reached the end of the allocated lights, with space in the
1520 gl lights, setup a new light */
1521 } else if (pos->glIndex == -1) {
1523 /* We reached the end of the allocated gl lights, so already
1524 know the index of the next one! */
1525 glIndex = Index;
1526 lightInfo->glIndex = glIndex;
1527 lightInfo->lightEnabled = TRUE;
1529 /* In an ideal world, it's already in the right place */
1530 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
1531 /* No need to move it */
1532 } else {
1533 /* Remove this light from the list */
1534 lightInfo->prev->next = lightInfo->next;
1535 if (lightInfo->next != NULL) {
1536 lightInfo->next->prev = lightInfo->prev;
1539 /* Add in at appropriate place (inbetween prev and pos) */
1540 lightInfo->prev = prev;
1541 lightInfo->next = pos;
1542 if (prev == NULL) {
1543 This->stateBlock->lights = lightInfo;
1544 } else {
1545 prev->next = lightInfo;
1547 if (pos != NULL) {
1548 pos->prev = lightInfo;
1552 /* Finally set up the light in gl itself */
1553 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
1554 ENTER_GL();
1555 setup_light(iface, glIndex, lightInfo);
1556 glEnable(GL_LIGHT0 + glIndex);
1557 checkGLcall("glEnable GL_LIGHT0 new setup");
1558 LEAVE_GL();
1563 return D3D_OK;
1566 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
1568 PLIGHTINFOEL *lightInfo = NULL;
1569 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1570 TRACE("(%p) : for idx(%ld)\n", This, Index);
1572 /* Locate the light in the live lights */
1573 lightInfo = This->stateBlock->lights;
1574 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1576 if (lightInfo == NULL) {
1577 TRACE("Light enabled state requested but light not defined\n");
1578 return D3DERR_INVALIDCALL;
1580 *pEnable = lightInfo->lightEnabled;
1581 return D3D_OK;
1584 /*****
1585 * Get / Set Clip Planes
1586 *****/
1587 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
1588 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1589 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
1591 /* Validate Index */
1592 if (Index >= GL_LIMITS(clipplanes)) {
1593 TRACE("Application has requested clipplane this device doesn't support\n");
1594 return D3DERR_INVALIDCALL;
1597 This->updateStateBlock->changed.clipplane[Index] = TRUE;
1598 This->updateStateBlock->set.clipplane[Index] = TRUE;
1599 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
1600 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
1601 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
1602 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
1604 /* Handle recording of state blocks */
1605 if (This->isRecordingState) {
1606 TRACE("Recording... not performing anything\n");
1607 return D3D_OK;
1610 /* Apply it */
1612 ENTER_GL();
1614 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
1615 glMatrixMode(GL_MODELVIEW);
1616 glPushMatrix();
1617 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
1619 TRACE("Clipplane [%f,%f,%f,%f]\n",
1620 This->updateStateBlock->clipplane[Index][0],
1621 This->updateStateBlock->clipplane[Index][1],
1622 This->updateStateBlock->clipplane[Index][2],
1623 This->updateStateBlock->clipplane[Index][3]);
1624 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
1625 checkGLcall("glClipPlane");
1627 glPopMatrix();
1628 LEAVE_GL();
1630 return D3D_OK;
1633 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
1634 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1635 TRACE("(%p) : for idx %ld\n", This, Index);
1637 /* Validate Index */
1638 if (Index >= GL_LIMITS(clipplanes)) {
1639 TRACE("Application has requested clipplane this device doesn't support\n");
1640 return D3DERR_INVALIDCALL;
1643 pPlane[0] = This->stateBlock->clipplane[Index][0];
1644 pPlane[1] = This->stateBlock->clipplane[Index][1];
1645 pPlane[2] = This->stateBlock->clipplane[Index][2];
1646 pPlane[3] = This->stateBlock->clipplane[Index][3];
1647 return D3D_OK;
1650 /*****
1651 * Get / Set Clip Plane Status
1652 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
1653 *****/
1654 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
1655 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1656 FIXME("(%p) : stub\n", This);
1657 if (NULL == pClipStatus) {
1658 return D3DERR_INVALIDCALL;
1660 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
1661 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
1662 return D3D_OK;
1665 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
1666 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1667 FIXME("(%p) : stub\n", This);
1668 if (NULL == pClipStatus) {
1669 return D3DERR_INVALIDCALL;
1671 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
1672 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
1673 return D3D_OK;
1676 /*****
1677 * Get / Set Material
1678 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
1679 *****/
1680 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
1681 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1683 This->updateStateBlock->changed.material = TRUE;
1684 This->updateStateBlock->set.material = TRUE;
1685 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
1687 /* Handle recording of state blocks */
1688 if (This->isRecordingState) {
1689 TRACE("Recording... not performing anything\n");
1690 return D3D_OK;
1693 ENTER_GL();
1694 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1695 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1696 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1697 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1698 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1700 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
1701 checkGLcall("glMaterialfv");
1702 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
1703 checkGLcall("glMaterialfv");
1705 /* Only change material color if specular is enabled, otherwise it is set to black */
1706 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
1707 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
1708 checkGLcall("glMaterialfv");
1709 } else {
1710 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1711 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1712 checkGLcall("glMaterialfv");
1714 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
1715 checkGLcall("glMaterialfv");
1716 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
1717 checkGLcall("glMaterialf");
1719 LEAVE_GL();
1720 return D3D_OK;
1723 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
1724 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1725 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
1726 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1727 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1728 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1729 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1730 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1731 return D3D_OK;
1734 /*****
1735 * Get / Set Indices
1736 *****/
1737 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
1738 UINT BaseVertexIndex) {
1739 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1740 IWineD3DIndexBuffer *oldIdxs;
1742 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
1743 oldIdxs = This->updateStateBlock->pIndexData;
1745 This->updateStateBlock->changed.indices = TRUE;
1746 This->updateStateBlock->set.indices = TRUE;
1747 This->updateStateBlock->pIndexData = pIndexData;
1748 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
1750 /* Handle recording of state blocks */
1751 if (This->isRecordingState) {
1752 TRACE("Recording... not performing anything\n");
1753 return D3D_OK;
1756 if (oldIdxs) IWineD3DIndexBuffer_Release(oldIdxs);
1757 if (pIndexData) IWineD3DIndexBuffer_AddRef(This->stateBlock->pIndexData);
1758 return D3D_OK;
1761 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
1762 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1764 *ppIndexData = This->stateBlock->pIndexData;
1766 /* up ref count on ppindexdata */
1767 if (*ppIndexData) IWineD3DIndexBuffer_AddRef(*ppIndexData);
1768 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
1770 return D3D_OK;
1773 /*****
1774 * Get / Set Viewports
1775 *****/
1776 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
1777 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1779 TRACE("(%p)\n", This);
1780 This->updateStateBlock->changed.viewport = TRUE;
1781 This->updateStateBlock->set.viewport = TRUE;
1782 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
1784 /* Handle recording of state blocks */
1785 if (This->isRecordingState) {
1786 TRACE("Recording... not performing anything\n");
1787 return D3D_OK;
1790 ENTER_GL();
1792 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
1793 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
1795 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
1796 checkGLcall("glDepthRange");
1797 /* Note: GL requires lower left, DirectX supplies upper left */
1798 /* TODO: replace usage of renderTarget with context management */
1799 glViewport(pViewport->X, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
1800 pViewport->Width, pViewport->Height);
1801 checkGLcall("glViewport");
1803 LEAVE_GL();
1805 return D3D_OK;
1809 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
1810 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1811 TRACE("(%p)\n", This);
1812 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
1813 return D3D_OK;
1816 /*****
1817 * Get / Set Render States
1818 * TODO: Verify against dx9 definitions
1819 *****/
1820 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
1822 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1823 DWORD OldValue = This->stateBlock->renderState[State];
1825 /* Simple way of referring to either a DWORD or a 4 byte float */
1826 union {
1827 DWORD d;
1828 float f;
1829 } tmpvalue;
1831 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
1832 This->updateStateBlock->changed.renderState[State] = TRUE;
1833 This->updateStateBlock->set.renderState[State] = TRUE;
1834 This->updateStateBlock->renderState[State] = Value;
1836 /* Handle recording of state blocks */
1837 if (This->isRecordingState) {
1838 TRACE("Recording... not performing anything\n");
1839 return D3D_OK;
1842 ENTER_GL();
1844 switch (State) {
1845 case WINED3DRS_FILLMODE :
1846 switch ((D3DFILLMODE) Value) {
1847 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
1848 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
1849 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
1850 default:
1851 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
1853 checkGLcall("glPolygonMode (fillmode)");
1854 break;
1856 case WINED3DRS_LIGHTING :
1857 if (Value) {
1858 glEnable(GL_LIGHTING);
1859 checkGLcall("glEnable GL_LIGHTING");
1860 } else {
1861 glDisable(GL_LIGHTING);
1862 checkGLcall("glDisable GL_LIGHTING");
1864 break;
1866 case WINED3DRS_ZENABLE :
1867 switch ((D3DZBUFFERTYPE) Value) {
1868 case D3DZB_FALSE:
1869 glDisable(GL_DEPTH_TEST);
1870 checkGLcall("glDisable GL_DEPTH_TEST");
1871 break;
1872 case D3DZB_TRUE:
1873 glEnable(GL_DEPTH_TEST);
1874 checkGLcall("glEnable GL_DEPTH_TEST");
1875 break;
1876 case D3DZB_USEW:
1877 glEnable(GL_DEPTH_TEST);
1878 checkGLcall("glEnable GL_DEPTH_TEST");
1879 FIXME("W buffer is not well handled\n");
1880 break;
1881 default:
1882 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
1884 break;
1886 case WINED3DRS_CULLMODE :
1888 /* If we are culling "back faces with clockwise vertices" then
1889 set front faces to be counter clockwise and enable culling
1890 of back faces */
1891 switch ((D3DCULL) Value) {
1892 case D3DCULL_NONE:
1893 glDisable(GL_CULL_FACE);
1894 checkGLcall("glDisable GL_CULL_FACE");
1895 break;
1896 case D3DCULL_CW:
1897 glEnable(GL_CULL_FACE);
1898 checkGLcall("glEnable GL_CULL_FACE");
1899 if (This->renderUpsideDown) {
1900 glFrontFace(GL_CW);
1901 checkGLcall("glFrontFace GL_CW");
1902 } else {
1903 glFrontFace(GL_CCW);
1904 checkGLcall("glFrontFace GL_CCW");
1906 glCullFace(GL_BACK);
1907 break;
1908 case D3DCULL_CCW:
1909 glEnable(GL_CULL_FACE);
1910 checkGLcall("glEnable GL_CULL_FACE");
1911 if (This->renderUpsideDown) {
1912 glFrontFace(GL_CCW);
1913 checkGLcall("glFrontFace GL_CCW");
1914 } else {
1915 glFrontFace(GL_CW);
1916 checkGLcall("glFrontFace GL_CW");
1918 glCullFace(GL_BACK);
1919 break;
1920 default:
1921 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
1923 break;
1925 case WINED3DRS_SHADEMODE :
1926 switch ((D3DSHADEMODE) Value) {
1927 case D3DSHADE_FLAT:
1928 glShadeModel(GL_FLAT);
1929 checkGLcall("glShadeModel");
1930 break;
1931 case D3DSHADE_GOURAUD:
1932 glShadeModel(GL_SMOOTH);
1933 checkGLcall("glShadeModel");
1934 break;
1935 case D3DSHADE_PHONG:
1936 FIXME("D3DSHADE_PHONG isn't supported?\n");
1938 LEAVE_GL();
1939 return D3DERR_INVALIDCALL;
1940 default:
1941 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
1943 break;
1945 case WINED3DRS_DITHERENABLE :
1946 if (Value) {
1947 glEnable(GL_DITHER);
1948 checkGLcall("glEnable GL_DITHER");
1949 } else {
1950 glDisable(GL_DITHER);
1951 checkGLcall("glDisable GL_DITHER");
1953 break;
1955 case WINED3DRS_ZWRITEENABLE :
1956 if (Value) {
1957 glDepthMask(1);
1958 checkGLcall("glDepthMask");
1959 } else {
1960 glDepthMask(0);
1961 checkGLcall("glDepthMask");
1963 break;
1965 case WINED3DRS_ZFUNC :
1967 int glParm = GL_LESS;
1969 switch ((D3DCMPFUNC) Value) {
1970 case D3DCMP_NEVER: glParm=GL_NEVER; break;
1971 case D3DCMP_LESS: glParm=GL_LESS; break;
1972 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
1973 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
1974 case D3DCMP_GREATER: glParm=GL_GREATER; break;
1975 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
1976 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
1977 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
1978 default:
1979 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
1981 glDepthFunc(glParm);
1982 checkGLcall("glDepthFunc");
1984 break;
1986 case WINED3DRS_AMBIENT :
1988 float col[4];
1989 D3DCOLORTOGLFLOAT4(Value, col);
1990 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
1991 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
1992 checkGLcall("glLightModel for MODEL_AMBIENT");
1995 break;
1997 case WINED3DRS_ALPHABLENDENABLE :
1998 if (Value) {
1999 glEnable(GL_BLEND);
2000 checkGLcall("glEnable GL_BLEND");
2001 } else {
2002 glDisable(GL_BLEND);
2003 checkGLcall("glDisable GL_BLEND");
2005 break;
2007 case WINED3DRS_SRCBLEND :
2008 case WINED3DRS_DESTBLEND :
2010 int newVal = GL_ZERO;
2011 switch (Value) {
2012 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2013 case D3DBLEND_ONE : newVal = GL_ONE; break;
2014 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2015 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2016 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2017 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2018 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2019 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2020 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2021 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2022 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2024 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2025 This->srcBlend = newVal;
2026 This->dstBlend = newVal;
2027 break;
2029 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2030 This->srcBlend = newVal;
2031 This->dstBlend = newVal;
2032 break;
2033 default:
2034 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2037 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2038 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2039 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2040 glBlendFunc(This->srcBlend, This->dstBlend);
2042 checkGLcall("glBlendFunc");
2044 break;
2046 case WINED3DRS_ALPHATESTENABLE :
2047 if (Value) {
2048 glEnable(GL_ALPHA_TEST);
2049 checkGLcall("glEnable GL_ALPHA_TEST");
2050 } else {
2051 glDisable(GL_ALPHA_TEST);
2052 checkGLcall("glDisable GL_ALPHA_TEST");
2054 break;
2056 case WINED3DRS_ALPHAFUNC :
2058 int glParm = GL_LESS;
2059 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2061 switch ((D3DCMPFUNC) Value) {
2062 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2063 case D3DCMP_LESS: glParm = GL_LESS; break;
2064 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2065 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2066 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2067 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2068 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2069 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2070 default:
2071 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2073 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2074 glAlphaFunc(glParm, ref);
2075 This->alphafunc = glParm;
2076 checkGLcall("glAlphaFunc");
2078 break;
2080 case WINED3DRS_ALPHAREF :
2082 int glParm = This->alphafunc;
2083 float ref = 1.0f;
2085 ref = ((float) Value) / 255.0f;
2086 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2087 glAlphaFunc(glParm, ref);
2088 checkGLcall("glAlphaFunc");
2090 break;
2092 case WINED3DRS_CLIPPLANEENABLE :
2093 case WINED3DRS_CLIPPING :
2095 /* Ensure we only do the changed clip planes */
2096 DWORD enable = 0xFFFFFFFF;
2097 DWORD disable = 0x00000000;
2099 /* If enabling / disabling all */
2100 if (State == WINED3DRS_CLIPPING) {
2101 if (Value) {
2102 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2103 disable = 0x00;
2104 } else {
2105 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2106 enable = 0x00;
2108 } else {
2109 enable = Value & ~OldValue;
2110 disable = ~Value & OldValue;
2113 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2114 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2115 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2116 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2117 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2118 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2120 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2121 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2122 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2123 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2124 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2125 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2127 /** update clipping status */
2128 if (enable) {
2129 This->stateBlock->clip_status.ClipUnion = 0;
2130 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
2131 } else {
2132 This->stateBlock->clip_status.ClipUnion = 0;
2133 This->stateBlock->clip_status.ClipIntersection = 0;
2136 break;
2138 case WINED3DRS_BLENDOP :
2140 int glParm = GL_FUNC_ADD;
2142 switch ((D3DBLENDOP) Value) {
2143 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2144 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2145 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2146 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2147 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2148 default:
2149 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2151 TRACE("glBlendEquation(%x)\n", glParm);
2152 glBlendEquation(glParm);
2153 checkGLcall("glBlendEquation");
2155 break;
2157 case WINED3DRS_TEXTUREFACTOR :
2159 unsigned int i;
2161 /* Note the texture color applies to all textures whereas
2162 GL_TEXTURE_ENV_COLOR applies to active only */
2163 float col[4];
2164 D3DCOLORTOGLFLOAT4(Value, col);
2165 /* Set the default alpha blend color */
2166 glBlendColor(col[0], col[1], col[2], col[3]);
2167 checkGLcall("glBlendColor");
2169 /* And now the default texture color as well */
2170 for (i = 0; i < GL_LIMITS(textures); i++) {
2172 /* Note the D3DRS value applies to all textures, but GL has one
2173 per texture, so apply it now ready to be used! */
2174 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2175 GLACTIVETEXTURE(i);
2176 } else if (i>0) {
2177 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2180 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2181 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2184 break;
2186 case WINED3DRS_SPECULARENABLE :
2188 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2189 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2190 specular color. This is wrong:
2191 Separate specular color means the specular colour is maintained separately, whereas
2192 single color means it is merged in. However in both cases they are being used to
2193 some extent.
2194 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2195 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2196 running 1.4 yet!
2198 if (Value) {
2199 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2200 checkGLcall("glMaterialfv");
2201 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2202 glEnable(GL_COLOR_SUM_EXT);
2203 } else {
2204 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2206 checkGLcall("glEnable(GL_COLOR_SUM)");
2207 } else {
2208 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2210 /* for the case of enabled lighting: */
2211 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2212 checkGLcall("glMaterialfv");
2214 /* for the case of disabled lighting: */
2215 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2216 glDisable(GL_COLOR_SUM_EXT);
2217 } else {
2218 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2220 checkGLcall("glDisable(GL_COLOR_SUM)");
2223 break;
2225 case WINED3DRS_STENCILENABLE :
2226 if (Value) {
2227 glEnable(GL_STENCIL_TEST);
2228 checkGLcall("glEnable GL_STENCIL_TEST");
2229 } else {
2230 glDisable(GL_STENCIL_TEST);
2231 checkGLcall("glDisable GL_STENCIL_TEST");
2233 break;
2235 case WINED3DRS_STENCILFUNC :
2237 int glParm = GL_ALWAYS;
2238 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2239 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2241 switch ((D3DCMPFUNC) Value) {
2242 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2243 case D3DCMP_LESS: glParm=GL_LESS; break;
2244 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2245 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2246 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2247 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2248 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2249 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2250 default:
2251 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2253 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2254 This->stencilfunc = glParm;
2255 glStencilFunc(glParm, ref, mask);
2256 checkGLcall("glStencilFunc");
2258 break;
2260 case WINED3DRS_STENCILREF :
2262 int glParm = This->stencilfunc;
2263 int ref = 0;
2264 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2266 ref = Value;
2267 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2268 glStencilFunc(glParm, ref, mask);
2269 checkGLcall("glStencilFunc");
2271 break;
2273 case WINED3DRS_STENCILMASK :
2275 int glParm = This->stencilfunc;
2276 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2277 GLuint mask = Value;
2279 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2280 glStencilFunc(glParm, ref, mask);
2281 checkGLcall("glStencilFunc");
2283 break;
2285 case WINED3DRS_STENCILFAIL :
2287 GLenum fail ;
2288 GLenum zpass ;
2289 GLenum zfail ;
2291 fail = StencilOp(Value);
2292 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2293 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2294 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2295 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2297 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2298 glStencilOp(fail, zfail, zpass);
2299 checkGLcall("glStencilOp(fail, zfail, zpass);");
2301 break;
2302 case WINED3DRS_STENCILZFAIL :
2304 GLenum fail ;
2305 GLenum zpass ;
2306 GLenum zfail ;
2308 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2309 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2310 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2311 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2312 zfail = StencilOp(Value);
2314 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2315 glStencilOp(fail, zfail, zpass);
2316 checkGLcall("glStencilOp(fail, zfail, zpass);");
2318 break;
2319 case WINED3DRS_STENCILPASS :
2321 GLenum fail ;
2322 GLenum zpass ;
2323 GLenum zfail ;
2325 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2326 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2327 zpass = StencilOp(Value);
2328 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2329 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2331 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2332 glStencilOp(fail, zfail, zpass);
2333 checkGLcall("glStencilOp(fail, zfail, zpass);");
2335 break;
2337 case WINED3DRS_STENCILWRITEMASK :
2339 glStencilMask(Value);
2340 TRACE("glStencilMask(%lu)\n", Value);
2341 checkGLcall("glStencilMask");
2343 break;
2345 case WINED3DRS_FOGENABLE :
2347 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2348 glEnable(GL_FOG);
2349 checkGLcall("glEnable GL_FOG");
2350 } else {
2351 glDisable(GL_FOG);
2352 checkGLcall("glDisable GL_FOG");
2355 break;
2357 case WINED3DRS_RANGEFOGENABLE :
2359 if (Value) {
2360 TRACE("Enabled RANGEFOG");
2361 } else {
2362 TRACE("Disabled RANGEFOG");
2365 break;
2367 case WINED3DRS_FOGCOLOR :
2369 float col[4];
2370 D3DCOLORTOGLFLOAT4(Value, col);
2371 /* Set the default alpha blend color */
2372 glFogfv(GL_FOG_COLOR, &col[0]);
2373 checkGLcall("glFog GL_FOG_COLOR");
2375 break;
2377 case WINED3DRS_FOGTABLEMODE :
2379 glHint(GL_FOG_HINT, GL_NICEST);
2380 switch (Value) {
2381 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2382 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2383 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2384 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2385 default:
2386 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
2388 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2389 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
2392 break;
2394 case WINED3DRS_FOGVERTEXMODE :
2396 glHint(GL_FOG_HINT, GL_FASTEST);
2397 switch (Value) {
2398 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2399 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2400 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2401 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2402 default:
2403 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
2405 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2406 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
2409 break;
2411 case WINED3DRS_FOGSTART :
2413 tmpvalue.d = Value;
2414 glFogfv(GL_FOG_START, &tmpvalue.f);
2415 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2416 TRACE("Fog Start == %f\n", tmpvalue.f);
2418 break;
2420 case WINED3DRS_FOGEND :
2422 tmpvalue.d = Value;
2423 glFogfv(GL_FOG_END, &tmpvalue.f);
2424 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2425 TRACE("Fog End == %f\n", tmpvalue.f);
2427 break;
2429 case WINED3DRS_FOGDENSITY :
2431 tmpvalue.d = Value;
2432 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
2433 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2435 break;
2437 case WINED3DRS_VERTEXBLEND :
2439 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2440 TRACE("Vertex Blending state to %ld\n", Value);
2442 break;
2444 case WINED3DRS_TWEENFACTOR :
2446 tmpvalue.d = Value;
2447 This->updateStateBlock->tween_factor = tmpvalue.f;
2448 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
2450 break;
2452 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
2454 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2456 break;
2458 case WINED3DRS_COLORVERTEX :
2459 case WINED3DRS_DIFFUSEMATERIALSOURCE :
2460 case WINED3DRS_SPECULARMATERIALSOURCE :
2461 case WINED3DRS_AMBIENTMATERIALSOURCE :
2462 case WINED3DRS_EMISSIVEMATERIALSOURCE :
2464 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2466 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
2467 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2468 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
2469 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
2470 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
2471 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
2473 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2474 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2475 Parm = GL_AMBIENT_AND_DIFFUSE;
2476 } else {
2477 Parm = GL_DIFFUSE;
2479 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2480 Parm = GL_AMBIENT;
2481 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2482 Parm = GL_EMISSION;
2483 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2484 Parm = GL_SPECULAR;
2485 } else {
2486 Parm = -1;
2489 if (Parm == -1) {
2490 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2491 } else {
2492 This->tracking_color = NEEDS_TRACKING;
2493 This->tracking_parm = Parm;
2496 } else {
2497 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2500 break;
2502 case WINED3DRS_LINEPATTERN :
2504 union {
2505 DWORD d;
2506 D3DLINEPATTERN lp;
2507 } tmppattern;
2508 tmppattern.d = Value;
2510 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2512 if (tmppattern.lp.wRepeatFactor) {
2513 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2514 checkGLcall("glLineStipple(repeat, linepattern)");
2515 glEnable(GL_LINE_STIPPLE);
2516 checkGLcall("glEnable(GL_LINE_STIPPLE);");
2517 } else {
2518 glDisable(GL_LINE_STIPPLE);
2519 checkGLcall("glDisable(GL_LINE_STIPPLE);");
2522 break;
2524 case WINED3DRS_ZBIAS :
2526 if (Value) {
2527 tmpvalue.d = Value;
2528 TRACE("ZBias value %f\n", tmpvalue.f);
2529 glPolygonOffset(0, -tmpvalue.f);
2530 checkGLcall("glPolygonOffset(0, -Value)");
2531 glEnable(GL_POLYGON_OFFSET_FILL);
2532 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
2533 glEnable(GL_POLYGON_OFFSET_LINE);
2534 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
2535 glEnable(GL_POLYGON_OFFSET_POINT);
2536 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
2537 } else {
2538 glDisable(GL_POLYGON_OFFSET_FILL);
2539 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
2540 glDisable(GL_POLYGON_OFFSET_LINE);
2541 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
2542 glDisable(GL_POLYGON_OFFSET_POINT);
2543 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
2546 break;
2548 case WINED3DRS_NORMALIZENORMALS :
2549 if (Value) {
2550 glEnable(GL_NORMALIZE);
2551 checkGLcall("glEnable(GL_NORMALIZE);");
2552 } else {
2553 glDisable(GL_NORMALIZE);
2554 checkGLcall("glDisable(GL_NORMALIZE);");
2556 break;
2558 case WINED3DRS_POINTSIZE :
2559 tmpvalue.d = Value;
2560 TRACE("Set point size to %f\n", tmpvalue.f);
2561 glPointSize(tmpvalue.f);
2562 checkGLcall("glPointSize(...);");
2563 break;
2565 case WINED3DRS_POINTSIZE_MIN :
2566 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2567 tmpvalue.d = Value;
2568 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
2569 checkGLcall("glPointParameterfEXT(...);");
2570 } else {
2571 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
2573 break;
2575 case WINED3DRS_POINTSIZE_MAX :
2576 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2577 tmpvalue.d = Value;
2578 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
2579 checkGLcall("glPointParameterfEXT(...);");
2580 } else {
2581 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
2583 break;
2585 case WINED3DRS_POINTSCALE_A :
2586 case WINED3DRS_POINTSCALE_B :
2587 case WINED3DRS_POINTSCALE_C :
2588 case WINED3DRS_POINTSCALEENABLE :
2590 /* If enabled, supply the parameters, otherwise fall back to defaults */
2591 if (This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
2592 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2593 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]);
2594 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]);
2595 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]);
2597 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2598 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2599 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2600 } else {
2601 TRACE("WINED3DRS_POINTSCALEENABLE not supported on this opengl\n");
2603 } else {
2604 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2605 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2606 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2607 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2608 } else {
2609 TRACE("WINED3DRS_POINTSCALEENABLE not supported, but not on either\n");
2612 break;
2615 case WINED3DRS_COLORWRITEENABLE :
2617 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
2618 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
2619 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
2620 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
2621 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
2622 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
2623 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
2624 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
2625 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
2626 checkGLcall("glColorMask(...)");
2628 break;
2630 case WINED3DRS_LOCALVIEWER :
2632 GLint state = (Value) ? 1 : 0;
2633 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
2634 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
2636 break;
2638 case WINED3DRS_LASTPIXEL :
2640 if (Value) {
2641 TRACE("Last Pixel Drawing Enabled\n");
2642 } else {
2643 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
2646 break;
2648 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
2650 if (Value) {
2651 TRACE("Software Processing Enabled\n");
2652 } else {
2653 TRACE("Software Processing Disabled\n");
2656 break;
2658 /** not supported */
2659 case WINED3DRS_ZVISIBLE :
2661 LEAVE_GL();
2662 return D3DERR_INVALIDCALL;
2665 /* Unhandled yet...! */
2666 case WINED3DRS_EDGEANTIALIAS :
2667 case WINED3DRS_WRAP0 :
2668 case WINED3DRS_WRAP1 :
2669 case WINED3DRS_WRAP2 :
2670 case WINED3DRS_WRAP3 :
2671 case WINED3DRS_WRAP4 :
2672 case WINED3DRS_WRAP5 :
2673 case WINED3DRS_WRAP6 :
2674 case WINED3DRS_WRAP7 :
2675 case WINED3DRS_POINTSPRITEENABLE :
2676 case WINED3DRS_MULTISAMPLEANTIALIAS :
2677 case WINED3DRS_MULTISAMPLEMASK :
2678 case WINED3DRS_PATCHEDGESTYLE :
2679 case WINED3DRS_PATCHSEGMENTS :
2680 case WINED3DRS_DEBUGMONITORTOKEN :
2681 case WINED3DRS_POSITIONORDER :
2682 case WINED3DRS_NORMALORDER :
2683 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
2684 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
2685 break;
2686 default:
2687 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
2690 LEAVE_GL();
2692 return D3D_OK;
2695 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
2696 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2697 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
2698 *pValue = This->stateBlock->renderState[State];
2699 return D3D_OK;
2702 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value){
2703 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2705 FIXME("(%p) : stub\n", This);
2706 return D3D_OK;
2709 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value){
2710 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2712 FIXME("(%p) : stub\n", This);
2713 return D3D_OK;
2717 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect){
2718 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2719 ENTER_GL();
2721 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
2722 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
2723 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
2724 LEAVE_GL();
2725 return D3D_OK;
2728 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect){
2729 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2730 GLint scissorBox[4];
2732 ENTER_GL();
2733 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
2734 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
2735 pRect->left = scissorBox[1];
2736 pRect->top = scissorBox[2];
2737 pRect->right = scissorBox[1] + scissorBox[3];
2738 pRect->bottom = scissorBox[2] + scissorBox[4];
2739 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
2740 LEAVE_GL();
2741 return D3D_OK;
2744 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
2745 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2747 TRACE("(%p) : pDecl=%p\n", This, pDecl);
2749 IWineD3DVertexDeclaration_AddRef(pDecl);
2750 if (NULL != This->updateStateBlock->vertexDecl) {
2751 IWineD3DVertexDeclaration_Release(This->updateStateBlock->vertexDecl);
2753 This->updateStateBlock->vertexDecl = pDecl;
2754 This->updateStateBlock->changed.vertexDecl = TRUE;
2755 This->updateStateBlock->set.vertexDecl = TRUE;
2756 return D3D_OK;
2759 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
2760 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2762 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
2764 *ppDecl = This->updateStateBlock->vertexDecl;
2765 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
2766 return D3D_OK;
2769 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader){
2770 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2772 static BOOL showFixmes = TRUE;
2774 This->updateStateBlock->vertexShader = pShader;
2775 This->updateStateBlock->changed.vertexShader = TRUE;
2776 This->updateStateBlock->set.vertexShader = TRUE;
2778 if(pShader == NULL){
2779 /* clear down the shader */
2780 TRACE("Clear down the shader\n");
2781 }else{
2782 if(showFixmes){
2783 FIXME("(%p) : stub pShader(%p)\n", This, pShader);
2784 showFixmes = FALSE;
2788 return D3D_OK;
2790 /** FIXME: refernece counting? **/
2791 if (pShader == NULL) { /* only valid with non FVF shaders */
2792 TRACE_(d3d_shader)("(%p) : FVF Shader, pShader=%p\n", This, pShader);
2793 This->updateStateBlock->vertexShader = NULL;
2794 } else {
2795 TRACE_(d3d_shader)("(%p) : Created shader, pShader=%p\n", This, pShader);
2796 This->updateStateBlock->vertexShader = pShader;
2799 This->updateStateBlock->changed.vertexShader = TRUE;
2800 This->updateStateBlock->set.vertexShader = TRUE;
2802 /* Handle recording of state blocks */
2803 if (This->isRecordingState) {
2804 TRACE("Recording... not performing anything\n");
2805 return D3D_OK;
2808 * TODO: merge HAL shaders context switching from prototype
2810 return D3D_OK;
2814 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader){
2815 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2816 *ppShader = This->stateBlock->vertexShader;
2817 if(*ppShader != NULL)
2818 IWineD3DVertexShader_AddRef(*ppShader);
2819 TRACE("(%p) : returning %p\n", This, *ppShader);
2820 return D3D_OK;
2823 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
2824 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2826 TRACE("(%p) : stub\n", This);
2827 return D3D_OK;
2830 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
2831 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2832 TRACE("(%p) : stub\n", This);
2833 return D3D_OK;
2836 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
2837 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2838 TRACE("(%p) : stub\n", This);
2839 return D3D_OK;
2842 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
2843 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2844 TRACE("(%p) : stub\n", This);
2845 return D3D_OK;
2848 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
2849 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2850 TRACE("(%p) : stub\n", This);
2851 return D3D_OK;
2854 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
2855 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2856 TRACE("(%p) : stub\n", This);
2857 return D3D_OK;
2860 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader){
2861 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2862 TRACE("(%p) : stub\n", This);
2863 return D3D_OK;
2866 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader){
2867 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2868 TRACE("(%p) : stub\n", This);
2869 return D3D_OK;
2873 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
2874 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2875 TRACE("(%p) : stub\n", This);
2876 return D3D_OK;
2879 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
2880 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2881 TRACE("(%p) : stub\n", This);
2882 return D3D_OK;
2885 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
2886 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2887 TRACE("(%p) : stub\n", This);
2888 return D3D_OK;
2891 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
2892 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2893 TRACE("(%p) : stub\n", This);
2894 return D3D_OK;
2897 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
2898 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2899 TRACE("(%p) : stub\n", This);
2900 return D3D_OK;
2903 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
2904 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2905 TRACE("(%p) : stub\n", This);
2906 return D3D_OK;
2909 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags){
2910 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2911 FIXME("(%p) : stub\n", This);
2912 return D3D_OK;
2915 /*****
2916 * Get / Set Texture Stage States
2917 * TODO: Verify against dx9 definitions
2918 *****/
2919 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
2920 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2921 union {
2922 float f;
2923 DWORD d;
2924 } tmpvalue;
2926 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
2928 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
2930 /* Reject invalid texture units */
2931 if (Stage >= GL_LIMITS(textures)) {
2932 TRACE("Attempt to access invalid texture rejected\n");
2933 return D3DERR_INVALIDCALL;
2936 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
2937 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
2938 This->updateStateBlock->textureState[Stage][Type] = Value;
2940 /* Handle recording of state blocks */
2941 if (This->isRecordingState) {
2942 TRACE("Recording... not performing anything\n");
2943 return D3D_OK;
2946 ENTER_GL();
2948 /* Make appropriate texture active */
2949 VTRACE(("Activating appropriate texture state %ld\n", Stage));
2950 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2951 GLACTIVETEXTURE(Stage);
2952 } else if (Stage > 0) {
2953 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2956 switch (Type) {
2958 case D3DTSS_MINFILTER :
2959 case D3DTSS_MIPFILTER :
2961 DWORD ValueMIN = This->stateBlock->textureState[Stage][D3DTSS_MINFILTER];
2962 DWORD ValueMIP = This->stateBlock->textureState[Stage][D3DTSS_MIPFILTER];
2963 GLint realVal = GL_LINEAR;
2965 if (ValueMIN == D3DTEXF_NONE) {
2966 /* Doesn't really make sense - Windows just seems to disable
2967 mipmapping when this occurs */
2968 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
2969 realVal = GL_LINEAR;
2970 } else if (ValueMIN == D3DTEXF_POINT) {
2971 /* GL_NEAREST_* */
2972 if (ValueMIP == D3DTEXF_NONE) {
2973 realVal = GL_NEAREST;
2974 } else if (ValueMIP == D3DTEXF_POINT) {
2975 realVal = GL_NEAREST_MIPMAP_NEAREST;
2976 } else if (ValueMIP == D3DTEXF_LINEAR) {
2977 realVal = GL_NEAREST_MIPMAP_LINEAR;
2978 } else {
2979 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
2980 realVal = GL_NEAREST;
2982 } else if (ValueMIN == D3DTEXF_LINEAR) {
2983 /* GL_LINEAR_* */
2984 if (ValueMIP == D3DTEXF_NONE) {
2985 realVal = GL_LINEAR;
2986 } else if (ValueMIP == D3DTEXF_POINT) {
2987 realVal = GL_LINEAR_MIPMAP_NEAREST;
2988 } else if (ValueMIP == D3DTEXF_LINEAR) {
2989 realVal = GL_LINEAR_MIPMAP_LINEAR;
2990 } else {
2991 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
2992 realVal = GL_LINEAR;
2994 } else if (ValueMIN == D3DTEXF_ANISOTROPIC) {
2995 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2996 if (ValueMIP == D3DTEXF_NONE) {
2997 realVal = GL_LINEAR_MIPMAP_LINEAR;
2998 } else if (ValueMIP == D3DTEXF_POINT) {
2999 realVal = GL_LINEAR_MIPMAP_NEAREST;
3000 } else if (ValueMIP == D3DTEXF_LINEAR) {
3001 realVal = GL_LINEAR_MIPMAP_LINEAR;
3002 } else {
3003 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3004 realVal = GL_LINEAR;
3006 } else {
3007 WARN("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MINFILTER. But not supported by OpenGL driver\n");
3008 realVal = GL_LINEAR;
3010 } else {
3011 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3012 realVal = GL_LINEAR_MIPMAP_LINEAR;
3015 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3016 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3017 checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
3019 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3021 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMIN) {
3022 glTexParameteri(This->stateBlock->textureDimensions[Stage],
3023 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3024 This->stateBlock->textureState[Stage][D3DTSS_MAXANISOTROPY]);
3025 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3028 break;
3030 case D3DTSS_MAGFILTER :
3032 DWORD ValueMAG = This->stateBlock->textureState[Stage][D3DTSS_MAGFILTER];
3033 GLint realVal = GL_NEAREST;
3035 if (ValueMAG == D3DTEXF_POINT) {
3036 realVal = GL_NEAREST;
3037 } else if (ValueMAG == D3DTEXF_LINEAR) {
3038 realVal = GL_LINEAR;
3039 } else if (ValueMAG == D3DTEXF_ANISOTROPIC) {
3040 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3041 realVal = GL_LINEAR;
3042 } else {
3043 FIXME("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MAGFILTER. But not supported by current OpenGL driver\n");
3044 realVal = GL_NEAREST;
3046 } else {
3047 FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", ValueMAG);
3048 realVal = GL_NEAREST;
3050 TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", ValueMAG, realVal);
3051 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, realVal);
3052 checkGLcall("glTexParameter GL_TEXTURE_MAG_FILTER, ...");
3054 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3056 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMAG) {
3057 glTexParameteri(This->stateBlock->textureDimensions[Stage],
3058 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3059 This->stateBlock->textureState[Stage][D3DTSS_MAXANISOTROPY]);
3060 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3063 break;
3065 case D3DTSS_MAXMIPLEVEL :
3068 * Not really the same, but the more apprioprate than nothing
3070 glTexParameteri(This->stateBlock->textureDimensions[Stage],
3071 GL_TEXTURE_BASE_LEVEL,
3072 This->stateBlock->textureState[Stage][D3DTSS_MAXMIPLEVEL]);
3073 checkGLcall("glTexParameteri GL_TEXTURE_BASE_LEVEL ...");
3075 break;
3077 case D3DTSS_MAXANISOTROPY :
3079 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3080 glTexParameteri(This->stateBlock->textureDimensions[Stage],
3081 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3082 This->stateBlock->textureState[Stage][D3DTSS_MAXANISOTROPY]);
3083 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3086 break;
3088 case D3DTSS_MIPMAPLODBIAS :
3090 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3091 tmpvalue.d = Value;
3092 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3093 GL_TEXTURE_LOD_BIAS_EXT,
3094 tmpvalue.f);
3095 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
3098 break;
3100 case D3DTSS_ALPHAOP :
3101 case D3DTSS_COLOROP :
3104 if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
3105 /* TODO: Disable by making this and all later levels disabled */
3106 glDisable(GL_TEXTURE_1D);
3107 checkGLcall("Disable GL_TEXTURE_1D");
3108 glDisable(GL_TEXTURE_2D);
3109 checkGLcall("Disable GL_TEXTURE_2D");
3110 glDisable(GL_TEXTURE_3D);
3111 checkGLcall("Disable GL_TEXTURE_3D");
3112 break; /* Don't bother setting the texture operations */
3113 } else {
3114 /* Enable only the appropriate texture dimension */
3115 if (Type == D3DTSS_COLOROP) {
3116 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3117 glEnable(GL_TEXTURE_1D);
3118 checkGLcall("Enable GL_TEXTURE_1D");
3119 } else {
3120 glDisable(GL_TEXTURE_1D);
3121 checkGLcall("Disable GL_TEXTURE_1D");
3123 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3124 if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
3125 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
3126 checkGLcall("Enable GL_TEXTURE_2D");
3127 } else {
3128 glEnable(GL_TEXTURE_2D);
3129 checkGLcall("Enable GL_TEXTURE_2D");
3131 } else {
3132 glDisable(GL_TEXTURE_2D);
3133 checkGLcall("Disable GL_TEXTURE_2D");
3135 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3136 glEnable(GL_TEXTURE_3D);
3137 checkGLcall("Enable GL_TEXTURE_3D");
3138 } else {
3139 glDisable(GL_TEXTURE_3D);
3140 checkGLcall("Disable GL_TEXTURE_3D");
3142 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3143 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3144 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3145 } else {
3146 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3147 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3151 /* Drop through... (Except disable case) */
3152 case D3DTSS_COLORARG0 :
3153 case D3DTSS_COLORARG1 :
3154 case D3DTSS_COLORARG2 :
3155 case D3DTSS_ALPHAARG0 :
3156 case D3DTSS_ALPHAARG1 :
3157 case D3DTSS_ALPHAARG2 :
3159 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 ||
3160 Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3161 if (isAlphaArg) {
3162 set_tex_op(iface, TRUE, Stage, This->stateBlock->textureState[Stage][D3DTSS_ALPHAOP],
3163 This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG1],
3164 This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG2],
3165 This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG0]);
3166 } else {
3167 set_tex_op(iface, FALSE, Stage, This->stateBlock->textureState[Stage][D3DTSS_COLOROP],
3168 This->stateBlock->textureState[Stage][D3DTSS_COLORARG1],
3169 This->stateBlock->textureState[Stage][D3DTSS_COLORARG2],
3170 This->stateBlock->textureState[Stage][D3DTSS_COLORARG0]);
3173 break;
3176 case D3DTSS_ADDRESSU :
3177 case D3DTSS_ADDRESSV :
3178 case D3DTSS_ADDRESSW :
3180 GLint wrapParm = GL_REPEAT;
3182 switch (Value) {
3183 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3184 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3185 case D3DTADDRESS_BORDER:
3187 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3188 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3189 } else {
3190 /* FIXME: Not right, but better */
3191 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3192 wrapParm = GL_REPEAT;
3195 break;
3196 case D3DTADDRESS_MIRROR:
3198 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3199 wrapParm = GL_MIRRORED_REPEAT_ARB;
3200 } else {
3201 /* Unsupported in OpenGL pre-1.4 */
3202 FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3203 wrapParm = GL_REPEAT;
3206 break;
3207 case D3DTADDRESS_MIRRORONCE:
3209 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3210 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3211 } else {
3212 FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3213 wrapParm = GL_REPEAT;
3216 break;
3218 default:
3219 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3220 wrapParm = GL_REPEAT;
3223 switch (Type) {
3224 case D3DTSS_ADDRESSU:
3225 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
3226 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3227 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3228 break;
3229 case D3DTSS_ADDRESSV:
3230 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
3231 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3232 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3233 break;
3234 case D3DTSS_ADDRESSW:
3235 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
3236 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3237 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3238 break;
3239 default: /* nop */
3240 break; /** stupic compilator */
3243 break;
3245 case D3DTSS_BORDERCOLOR :
3247 float col[4];
3248 D3DCOLORTOGLFLOAT4(Value, col);
3249 TRACE("Setting border color for %x to %lx\n", This->stateBlock->textureDimensions[Stage], Value);
3250 glTexParameterfv(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3251 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3253 break;
3255 case D3DTSS_TEXCOORDINDEX :
3257 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3259 /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include
3260 one flag, you can still specify an index value, which the system uses to
3261 determine the texture wrapping mode.
3262 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3263 means use the vertex position (camera-space) as the input texture coordinates
3264 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
3265 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3266 to the TEXCOORDINDEX value */
3268 /**
3269 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3271 switch (Value & 0xFFFF0000) {
3272 case D3DTSS_TCI_PASSTHRU:
3273 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3274 glDisable(GL_TEXTURE_GEN_S);
3275 glDisable(GL_TEXTURE_GEN_T);
3276 glDisable(GL_TEXTURE_GEN_R);
3277 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3278 break;
3280 case D3DTSS_TCI_CAMERASPACEPOSITION:
3281 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3282 as the input texture coordinates for this stage's texture transformation. This
3283 equates roughly to EYE_LINEAR */
3285 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3286 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3287 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3288 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3289 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3291 glMatrixMode(GL_MODELVIEW);
3292 glPushMatrix();
3293 glLoadIdentity();
3294 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3295 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3296 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3297 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3298 glPopMatrix();
3300 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3301 glEnable(GL_TEXTURE_GEN_S);
3302 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3303 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3304 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3305 glEnable(GL_TEXTURE_GEN_T);
3306 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3307 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3308 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3309 glEnable(GL_TEXTURE_GEN_R);
3310 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3311 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3312 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3314 break;
3316 case D3DTSS_TCI_CAMERASPACENORMAL:
3318 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3319 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3320 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3321 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3322 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3323 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3325 glMatrixMode(GL_MODELVIEW);
3326 glPushMatrix();
3327 glLoadIdentity();
3328 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3329 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3330 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3331 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3332 glPopMatrix();
3334 glEnable(GL_TEXTURE_GEN_S);
3335 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3336 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3337 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3338 glEnable(GL_TEXTURE_GEN_T);
3339 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3340 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3341 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3342 glEnable(GL_TEXTURE_GEN_R);
3343 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3344 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3345 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3348 break;
3350 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3352 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3353 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3354 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3355 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3356 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3357 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3359 glMatrixMode(GL_MODELVIEW);
3360 glPushMatrix();
3361 glLoadIdentity();
3362 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3363 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3364 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3365 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3366 glPopMatrix();
3368 glEnable(GL_TEXTURE_GEN_S);
3369 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3370 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3371 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3372 glEnable(GL_TEXTURE_GEN_T);
3373 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3374 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3375 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3376 glEnable(GL_TEXTURE_GEN_R);
3377 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3378 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3379 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3382 break;
3384 /* Unhandled types: */
3385 default:
3386 /* Todo: */
3387 /* ? disable GL_TEXTURE_GEN_n ? */
3388 glDisable(GL_TEXTURE_GEN_S);
3389 glDisable(GL_TEXTURE_GEN_T);
3390 glDisable(GL_TEXTURE_GEN_R);
3391 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
3392 break;
3395 break;
3397 /* Unhandled */
3398 case D3DTSS_TEXTURETRANSFORMFLAGS :
3399 set_texture_matrix((float *)&This->stateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
3400 break;
3402 case D3DTSS_BUMPENVMAT00 :
3403 case D3DTSS_BUMPENVMAT01 :
3404 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
3405 break;
3406 case D3DTSS_BUMPENVMAT10 :
3407 case D3DTSS_BUMPENVMAT11 :
3408 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
3409 break;
3411 case D3DTSS_BUMPENVLSCALE :
3412 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3413 break;
3415 case D3DTSS_BUMPENVLOFFSET :
3416 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3417 break;
3419 case D3DTSS_RESULTARG :
3420 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3421 break;
3423 default:
3424 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3425 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3428 LEAVE_GL();
3430 return D3D_OK;
3433 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
3434 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3435 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
3436 *pValue = This->updateStateBlock->textureState[Stage][Type];
3437 return D3D_OK;
3440 /*****
3441 * Get / Set Texture
3442 *****/
3443 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
3445 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3446 IWineD3DBaseTexture *oldTexture;
3447 BOOL reapplyStates = TRUE;
3448 DWORD reapplyFlags = 0;
3449 INT oldTextureDimensions = -1;
3450 D3DRESOURCETYPE textureType;
3452 oldTexture = This->updateStateBlock->textures[Stage];
3453 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3455 /* Reject invalid texture units */
3456 if (Stage >= GL_LIMITS(textures)) {
3457 TRACE("Attempt to access invalid texture rejected\n");
3458 return D3DERR_INVALIDCALL;
3461 This->updateStateBlock->set.textures[Stage] = TRUE;
3462 This->updateStateBlock->changed.textures[Stage] = TRUE;
3463 This->updateStateBlock->textures[Stage] = pTexture;
3465 /* Handle recording of state blocks */
3466 if (This->isRecordingState) {
3467 TRACE("Recording... not performing anything\n");
3468 return D3D_OK;
3471 oldTextureDimensions = This->updateStateBlock->textureDimensions[Stage];
3473 ENTER_GL();
3475 /* Make appropriate texture active */
3476 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3477 GLACTIVETEXTURE(Stage);
3479 } else if (Stage>0) {
3480 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3483 /** NOTE: MSDN says that setTexture increases the reference count,
3484 * and the the application nust set the texture back to null (or have a leaky application),
3485 * This means we should pass the refcount upto the parent
3486 *******************************/
3487 if (NULL != oldTexture) {
3489 IUnknown *textureParent;
3490 IWineD3DBaseTexture_GetParent(oldTexture, (IUnknown **)&textureParent);
3491 IUnknown_Release(textureParent);
3492 IUnknown_Release(textureParent); /** NOTE: Twice because GetParent adds a ref **/
3493 oldTexture = NULL;
3497 if (NULL != pTexture) {
3498 IUnknown *textureParent;
3499 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[Stage], (IUnknown **)&textureParent);
3500 /** NOTE: GetParent will increase the ref count for me, I won't clean up untill the texture is set to NULL **/
3502 /* Now setup the texture appropraitly */
3503 textureType = IWineD3DBaseTexture_GetType(pTexture);
3505 if (textureType == D3DRTYPE_TEXTURE) {
3507 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
3508 TRACE("Skipping setting texture as old == new\n");
3509 reapplyStates = FALSE;
3511 } else {
3513 /* Standard 2D texture */
3514 TRACE("Standard 2d texture\n");
3515 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3517 /* Load up the texture now */
3518 IWineD3DTexture_PreLoad((IWineD3DTexture *) pTexture);
3521 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3523 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
3524 TRACE("Skipping setting texture as old == new\n");
3525 reapplyStates = FALSE;
3527 } else {
3529 /* Standard 3D (volume) texture */
3530 TRACE("Standard 3d texture\n");
3531 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3533 /* Load up the texture now */
3534 IWineD3DVolumeTexture_PreLoad((IWineD3DVolumeTexture *) pTexture);
3537 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
3539 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
3540 TRACE("Skipping setting texture as old == new\n");
3541 reapplyStates = FALSE;
3543 } else {
3545 /* Standard Cube texture */
3546 TRACE("Standard Cube texture\n");
3547 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
3549 /* Load up the texture now */
3550 IWineD3DCubeTexture_PreLoad((IWineD3DCubeTexture *) pTexture);
3553 } else {
3554 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dresourcetype(textureType));
3557 } else {
3559 TRACE("Setting to no texture (ie default texture)\n");
3560 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3561 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3562 checkGLcall("glBindTexture");
3563 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3566 /* Disable the old texture binding and enable the new one (unless operations are disabled) */
3567 if (oldTextureDimensions != This->updateStateBlock->textureDimensions[Stage]) {
3569 glDisable(oldTextureDimensions);
3570 checkGLcall("Disable oldTextureDimensions");
3572 if (This->stateBlock->textureState[Stage][D3DTSS_COLOROP] != D3DTOP_DISABLE) {
3573 glEnable(This->updateStateBlock->textureDimensions[Stage]);
3574 checkGLcall("glEnable new texture dimensions");
3577 /* If Alpha arg1 is texture then handle the special case when there changes between a
3578 texture and no texture - See comments in set_tex_op */
3579 if ((This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
3580 (((oldTexture == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTexture != NULL))))
3582 reapplyFlags |= REAPPLY_ALPHAOP;
3587 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3588 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3589 if (reapplyStates) {
3590 IWineD3DDeviceImpl_SetupTextureStates(iface, Stage, reapplyFlags);
3593 LEAVE_GL();
3594 TRACE("Texture now fully setup\n");
3596 return D3D_OK;
3599 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
3600 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3601 TRACE("(%p) : returning %p for stage %ld\n", This, This->updateStateBlock->textures[Stage], Stage);
3602 *ppTexture = (IWineD3DBaseTexture *) This->updateStateBlock->textures[Stage];
3603 if (*ppTexture)
3604 IWineD3DBaseTexture_AddRef(*ppTexture);
3605 return D3D_OK;
3608 /*****
3609 * Get Back Buffer
3610 *****/
3611 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type,
3612 IWineD3DSurface** ppBackBuffer) {
3613 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3615 *ppBackBuffer = (IWineD3DSurface *) This->backBuffer;
3616 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
3618 if (BackBuffer > This->presentParms.BackBufferCount - 1) {
3619 FIXME("Only one backBuffer currently supported\n");
3620 return D3DERR_INVALIDCALL;
3623 /* Note inc ref on returned surface */
3624 IWineD3DSurface_AddRef(*ppBackBuffer);
3626 return D3D_OK;
3629 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, D3DCAPS9* pCaps) {
3630 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3631 WARN("(%p) : stub, calling idirect3d for now\n", This);
3632 IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
3633 return D3D_OK;
3636 /** TODO: move to swapchains **/
3637 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
3638 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3639 HDC hdc;
3640 int bpp = 0;
3642 pMode->Width = GetSystemMetrics(SM_CXSCREEN);
3643 pMode->Height = GetSystemMetrics(SM_CYSCREEN);
3644 pMode->RefreshRate = 85; /*FIXME: How to identify? */
3646 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
3647 bpp = GetDeviceCaps(hdc, BITSPIXEL);
3648 DeleteDC(hdc);
3650 switch (bpp) {
3651 case 8: pMode->Format = WINED3DFMT_R8G8B8; break;
3652 case 16: pMode->Format = WINED3DFMT_R5G6B5; break;
3653 case 24: /*pMode->Format = WINED3DFMT_R8G8B8; break; */
3654 case 32: pMode->Format = WINED3DFMT_A8R8G8B8; break;
3655 default:
3656 FIXME("Unrecognized display mode format\n");
3657 pMode->Format = WINED3DFMT_UNKNOWN;
3660 FIXME("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate,
3661 pMode->Format, debug_d3dformat(pMode->Format));
3662 return D3D_OK;
3664 /*****
3665 * Stateblock related functions
3666 *****/
3668 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
3669 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3670 IWineD3DStateBlockImpl *object;
3671 TRACE("(%p)", This);
3672 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
3673 if(NULL == object ){
3674 FIXME("(%p)Error allocating memory for stateblock\n", This);
3675 return E_OUTOFMEMORY;
3677 TRACE("(%p) creted object %p\n", This, object);
3678 object->wineD3DDevice= This;
3679 /** FIXME: object->parent = parent; **/
3680 object->parent = NULL;
3681 object->blockType = D3DSBT_ALL;
3682 object->ref = 1;
3683 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
3685 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
3686 This->updateStateBlock = object;
3687 This->isRecordingState = TRUE;
3689 TRACE("(%p) recording stateblock %p\n",This , object);
3690 return D3D_OK;
3693 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
3694 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3696 if (!This->isRecordingState) {
3697 FIXME("(%p) not recording! returning error\n", This);
3698 *ppStateBlock = NULL;
3699 return D3DERR_INVALIDCALL;
3702 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
3703 This->isRecordingState = FALSE;
3704 This->updateStateBlock = This->stateBlock;
3705 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
3706 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
3707 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
3708 return D3D_OK;
3711 /*****
3712 * Scene related functions
3713 *****/
3714 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
3715 /* At the moment we have no need for any functionality at the beginning
3716 of a scene */
3717 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3718 TRACE("(%p) : stub\n", This);
3719 return D3D_OK;
3722 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
3723 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3724 TRACE("(%p)\n", This);
3725 ENTER_GL();
3726 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
3727 glFlush();
3728 checkGLcall("glFlush");
3730 TRACE("End Scene\n");
3731 if(This->renderTarget != NULL){
3733 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
3734 IUnknown *targetContainer = NULL;
3735 if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)) {
3736 TRACE("RenderTarget is either standalone of a texture.\n");
3737 /** always dirtify for now. we must find a better way to see that surface have been modified
3738 (Modifications should will only occur via draw-primitive, but we do need better locking
3739 switching to render-to-texture should remove the overhead though.
3741 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
3742 IWineD3DBaseTexture_SetDirty((IWineD3DBaseTexture *)targetContainer, TRUE);
3743 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *)targetContainer);
3744 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
3745 IUnknown_Release(targetContainer);
3750 LEAVE_GL();
3751 return D3D_OK;
3754 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
3755 CONST RECT* pSourceRect, CONST RECT* pDestRect,
3756 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
3757 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3758 TRACE("(%p) Presenting the frame\n", This);
3760 ENTER_GL();
3762 if (pSourceRect || pDestRect) FIXME("Unhandled present options %p/%p\n", pSourceRect, pDestRect);
3764 glXSwapBuffers(This->display, This->drawable);
3765 /* Don't call checkGLcall, as glGetError is not applicable here */
3767 TRACE("glXSwapBuffers called, Starting new frame\n");
3769 /* FPS support */
3770 if (TRACE_ON(d3d_fps))
3772 static long prev_time, frames;
3774 DWORD time = GetTickCount();
3775 frames++;
3776 /* every 1.5 seconds */
3777 if (time - prev_time > 1500) {
3778 TRACE_(d3d_fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time));
3779 prev_time = time;
3780 frames = 0;
3784 #if defined(FRAME_DEBUGGING)
3786 if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
3787 if (!isOn) {
3788 isOn = TRUE;
3789 FIXME("Enabling D3D Trace\n");
3790 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1);
3791 #if defined(SHOW_FRAME_MAKEUP)
3792 FIXME("Singe Frame snapshots Starting\n");
3793 isDumpingFrames = TRUE;
3794 glClear(GL_COLOR_BUFFER_BIT);
3795 #endif
3797 #if defined(SINGLE_FRAME_DEBUGGING)
3798 } else {
3799 #if defined(SHOW_FRAME_MAKEUP)
3800 FIXME("Singe Frame snapshots Finishing\n");
3801 isDumpingFrames = FALSE;
3802 #endif
3803 FIXME("Singe Frame trace complete\n");
3804 DeleteFileA("C:\\D3DTRACE");
3805 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
3806 #endif
3808 } else {
3809 if (isOn) {
3810 isOn = FALSE;
3811 #if defined(SHOW_FRAME_MAKEUP)
3812 FIXME("Singe Frame snapshots Finishing\n");
3813 isDumpingFrames = FALSE;
3814 #endif
3815 FIXME("Disabling D3D Trace\n");
3816 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
3820 #endif
3822 LEAVE_GL();
3823 /* Although this is not strictly required, a simple demo showed this does occur
3824 on (at least non-debug) d3d */
3825 if (This->presentParms.SwapEffect == D3DSWAPEFFECT_DISCARD) {
3826 IWineD3DDevice_Clear(iface, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
3829 return D3D_OK;
3832 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
3833 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
3834 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3836 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
3837 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
3838 when the depth-buffer format does not contain stencil buffer information, this method fails. */
3839 GLbitfield glMask = 0;
3840 GLboolean old_ztest;
3841 GLfloat old_z_clear_value;
3842 GLint old_stencil_clear_value;
3843 GLfloat old_color_clear_value[4];
3844 unsigned int i;
3845 CONST D3DRECT* curRect;
3847 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
3848 Count, pRects, Flags, Z, Stencil);
3850 ENTER_GL();
3852 glEnable(GL_SCISSOR_TEST);
3853 checkGLcall("glEnable GL_SCISSOR_TEST");
3855 if (Count > 0 && pRects) {
3856 curRect = pRects;
3857 } else {
3858 curRect = NULL;
3861 /* Only set the values up once, as they are not changing */
3862 if (Flags & D3DCLEAR_STENCIL) {
3863 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
3864 glClearStencil(Stencil);
3865 checkGLcall("glClearStencil");
3866 glMask = glMask | GL_STENCIL_BUFFER_BIT;
3867 glStencilMask(0xFFFFFFFF);
3870 if (Flags & D3DCLEAR_ZBUFFER) {
3871 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
3872 glDepthMask(GL_TRUE);
3873 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
3874 glClearDepth(Z);
3875 checkGLcall("glClearDepth");
3876 glMask = glMask | GL_DEPTH_BUFFER_BIT;
3879 if (Flags & D3DCLEAR_TARGET) {
3880 TRACE("Clearing screen with glClear to color %lx\n", Color);
3881 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
3882 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
3883 ((Color >> 8) & 0xFF) / 255.0f,
3884 ((Color >> 0) & 0xFF) / 255.0f,
3885 ((Color >> 24) & 0xFF) / 255.0f);
3886 checkGLcall("glClearColor");
3888 /* Clear ALL colors! */
3889 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3890 glMask = glMask | GL_COLOR_BUFFER_BIT;
3893 /* Now process each rect in turn */
3894 for (i = 0; i < Count || i == 0; i++) {
3896 if (curRect) {
3897 /* Note gl uses lower left, width/height */
3898 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
3899 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
3900 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
3901 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
3902 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
3903 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
3904 checkGLcall("glScissor");
3905 } else {
3906 glScissor(This->stateBlock->viewport.X,
3907 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
3908 This->stateBlock->viewport.Width,
3909 This->stateBlock->viewport.Height);
3910 checkGLcall("glScissor");
3913 /* Clear the selected rectangle (or full screen) */
3914 glClear(glMask);
3915 checkGLcall("glClear");
3917 /* Step to the next rectangle */
3918 if (curRect) curRect = curRect + sizeof(D3DRECT);
3921 /* Restore the old values (why..?) */
3922 if (Flags & D3DCLEAR_STENCIL) {
3923 glClearStencil(old_stencil_clear_value);
3924 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
3926 if (Flags & D3DCLEAR_ZBUFFER) {
3927 glDepthMask(old_ztest);
3928 glClearDepth(old_z_clear_value);
3930 if (Flags & D3DCLEAR_TARGET) {
3931 glClearColor(old_color_clear_value[0],
3932 old_color_clear_value[1],
3933 old_color_clear_value[2],
3934 old_color_clear_value[3]);
3935 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3936 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3937 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3938 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3941 glDisable(GL_SCISSOR_TEST);
3942 checkGLcall("glDisable");
3943 LEAVE_GL();
3945 return D3D_OK;
3948 /*****
3949 * Drawing functions
3950 *****/
3951 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
3952 UINT PrimitiveCount) {
3954 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3955 This->stateBlock->streamIsUP = FALSE;
3957 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
3958 debug_d3dprimitivetype(PrimitiveType),
3959 StartVertex, PrimitiveCount);
3960 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
3962 return D3D_OK;
3965 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
3966 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
3967 D3DPRIMITIVETYPE PrimitiveType,
3968 INT baseVIndex, UINT minIndex,
3969 UINT NumVertices,UINT startIndex,UINT primCount) {
3971 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3972 UINT idxStride = 2;
3973 IWineD3DIndexBuffer *pIB;
3974 D3DINDEXBUFFER_DESC IdxBufDsc;
3976 pIB = This->stateBlock->pIndexData;
3977 This->stateBlock->streamIsUP = FALSE;
3979 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d \n", This,
3980 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3981 minIndex, NumVertices, startIndex, baseVIndex, primCount);
3983 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
3984 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
3985 idxStride = 2;
3986 } else {
3987 idxStride = 4;
3990 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex,
3991 startIndex, idxStride,
3992 ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory,
3993 minIndex);
3995 return D3D_OK;
3998 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
3999 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4000 UINT VertexStreamZeroStride) {
4001 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4003 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4004 debug_d3dprimitivetype(PrimitiveType),
4005 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4007 if (This->stateBlock->stream_source[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->stream_source[0]);
4009 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4010 This->stateBlock->stream_source[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4011 This->stateBlock->stream_stride[0] = VertexStreamZeroStride;
4012 This->stateBlock->streamIsUP = TRUE;
4013 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
4014 This->stateBlock->stream_stride[0] = 0;
4015 This->stateBlock->stream_source[0] = NULL;
4017 /*stream zero settings set to null at end, as per the msdn */
4018 return D3D_OK;
4021 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4022 UINT MinVertexIndex,
4023 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
4024 WINED3DFORMAT IndexDataFormat, CONST void* pVertexStreamZeroData,
4025 UINT VertexStreamZeroStride) {
4026 int idxStride;
4027 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4029 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4030 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4031 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData,
4032 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4034 if (This->stateBlock->stream_source[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->stream_source[0]);
4036 if (IndexDataFormat == WINED3DFMT_INDEX16) {
4037 idxStride = 2;
4038 } else {
4039 idxStride = 4;
4042 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4043 This->stateBlock->stream_source[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4044 This->stateBlock->streamIsUP = TRUE;
4045 This->stateBlock->stream_stride[0] = VertexStreamZeroStride;
4047 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, idxStride, pIndexData, MinVertexIndex);
4049 /* stream zero settings set to null at end as per the msdn */
4050 This->stateBlock->stream_source[0] = NULL;
4051 This->stateBlock->stream_stride[0] = 0;
4052 IWineD3DDevice_SetIndices(iface, NULL, 0);
4054 return D3D_OK;
4057 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
4058 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4060 TRACE("(%p) : stub\n", This);
4061 return D3D_OK;
4064 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
4065 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
4066 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
4067 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4069 TRACE("(%p) : stub\n", This);
4070 return D3D_OK;
4072 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface){
4073 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4075 TRACE("(%p) : stub\n", This);
4076 return D3D_OK;
4079 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface){
4080 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4082 TRACE("(%p) : stub\n", This);
4083 return D3D_OK;
4086 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4087 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4088 /* return a sensible default */
4089 *pNumPasses = 1;
4090 FIXME("(%p) : stub\n", This);
4091 return D3D_OK;
4094 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4095 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4096 FIXME("(%p) : stub\n", This);
4097 return D3D_OK;
4100 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4101 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4102 FIXME("(%p) : stub\n", This);
4103 return D3D_OK;
4106 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4107 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4108 FIXME("(%p) : stub\n", This);
4109 return D3D_OK;
4112 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4113 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4114 FIXME("(%p) : stub\n", This);
4115 return D3D_OK;
4118 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4119 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4120 FIXME("(%p) : stub\n", This);
4121 return D3D_OK;
4125 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4126 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4127 FIXME("(%p) : stub\n", This);
4128 return FALSE;
4132 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
4133 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4135 pRasterStatus->InVBlank = TRUE;
4136 pRasterStatus->ScanLine = 0;
4137 FIXME("(%p) : stub\n", This);
4138 return D3D_OK;
4142 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4143 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4144 static BOOL showfixmes = TRUE;
4145 if(nSegments != 0.0f){
4146 if( showfixmes){
4147 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4148 showfixmes = FALSE;
4151 return D3D_OK;
4154 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4155 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4156 static BOOL showfixmes = TRUE;
4157 if( showfixmes){
4158 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4159 showfixmes = FALSE;
4161 return 0.0f;
4165 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4166 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4167 FIXME("(%p) : stub\n", This);
4168 return D3D_OK;
4172 /* Implementation details at http://developer.nvidia.com/attach/6494
4174 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
4175 hmm.. no longer supported use
4176 OpenGL evaluators or tessellate surfaces within your application.
4179 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
4180 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo){
4181 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4182 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p) \n", This, Handle, pNumSegs, pRectPatchInfo);
4183 FIXME("(%p) : Stub\n", This);
4184 return D3D_OK;
4188 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
4189 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo){
4190 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4191 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p) \n", This, Handle, pNumSegs, pTriPatchInfo);
4192 FIXME("(%p) : Stub\n", This);
4193 return D3D_OK;
4196 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle){
4197 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4198 TRACE("(%p) Handle(%d)\n", This, Handle);
4199 FIXME("(%p) : Stub\n", This);
4200 return D3D_OK;
4203 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color){
4204 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4206 FIXME("(%p) : stub\n", This);
4207 return D3D_OK;
4210 /* rendertarget and deptth stencil functions */
4211 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget){
4212 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4214 /* FIXME: Implelent RenderTargetIndex >0 */
4215 if(RenderTargetIndex > 0)
4216 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
4218 *ppRenderTarget = (IWineD3DSurface *)This->renderTarget;
4219 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
4220 /* Note inc ref on returned surface */
4221 if(*ppRenderTarget != NULL)
4222 IWineD3DSurface_AddRef(*ppRenderTarget);
4223 return D3D_OK;
4226 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface){
4227 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4228 *ppZStencilSurface = (IWineD3DSurface *)This->depthStencilBuffer;
4229 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
4231 if(*ppZStencilSurface != NULL){
4232 /* Note inc ref on returned surface */
4233 IWineD3DSurface_AddRef(*ppZStencilSurface);
4235 return D3D_OK;
4238 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget){
4239 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4241 FIXME("(%p) : stub\n", This);
4242 return D3D_OK;
4245 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil){
4246 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4248 FIXME("(%p) : stub\n", This);
4249 return D3D_OK;
4252 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
4253 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
4254 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4255 /* TODO: the use of Impl is deprecated. */
4256 /* some basic validation checks */
4257 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
4259 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
4261 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
4262 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
4263 return D3DERR_INVALIDCALL;
4265 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
4266 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
4267 return D3DERR_INVALIDCALL;
4269 /* TODO: make the cursor 'real' */
4271 This->xHotSpot = XHotSpot;
4272 This->yHotSpot = YHotSpot;
4274 return D3D_OK;
4277 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
4278 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4279 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
4281 This->xScreenSpace = XScreenSpace;
4282 This->yScreenSpace = YScreenSpace;
4284 return;
4288 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
4289 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4290 TRACE("(%p) : visible(%d)\n", This, bShow);
4292 This->bCursorVisible = bShow;
4294 return D3D_OK;
4297 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
4298 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4299 FIXME("(%p) : stub\n", This); /* No way of notifying yet! */
4300 return D3D_OK;
4304 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
4305 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4306 /** FIXME: Resource tracking needs to be done,
4307 * The closes we can do to this is set the priorities of all managed textures low
4308 * and then reset them.
4309 ***********************************************************/
4310 FIXME("(%p) : stub\n", This);
4311 return D3D_OK;
4314 HRESULT WINAPI IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
4315 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4316 /** FIXME: Resource trascking needs to be done.
4317 * in effect this pulls all non only default
4318 * textures out of video memory and deletes all glTextures (glDeleteTextures)
4319 * and should clear down the context and set it up according to pPresentationParameters
4320 ***********************************************************/
4321 FIXME("(%p) : stub\n", This);
4322 return D3D_OK;
4325 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs){
4326 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4327 /** FIXME: always true at the moment **/
4328 if(bEnableDialogs == FALSE){
4329 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
4331 return D3D_OK;
4335 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
4336 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4338 FIXME("(%p) : stub\n", This);
4339 /* Setup some reasonable defaults */
4340 pParameters->AdapterOrdinal = 0; /* always for now */
4341 pParameters->DeviceType = D3DDEVTYPE_HAL; /* always for now */
4342 pParameters->hFocusWindow = 0;
4343 pParameters->BehaviorFlags =0;
4344 return D3D_OK;
4347 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
4348 HDC hDC;
4349 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4351 FIXME("(%p) : pRamp@%p\n", This, pRamp);
4352 hDC = GetDC(This->win_handle);
4353 SetDeviceGammaRamp(hDC, (LPVOID) pRamp);
4354 ReleaseDC(This->win_handle, hDC);
4355 return;
4358 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
4359 HDC hDC;
4360 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4362 FIXME("(%p) : pRamp@%p\n", This, pRamp);
4363 hDC = GetDC(This->win_handle);
4364 GetDeviceGammaRamp(hDC, pRamp);
4365 ReleaseDC(This->win_handle, hDC);
4366 return;
4369 /**********************************************************
4370 * IWineD3DDevice VTbl follows
4371 **********************************************************/
4373 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
4375 /*** IUnknown methods ***/
4376 IWineD3DDeviceImpl_QueryInterface,
4377 IWineD3DDeviceImpl_AddRef,
4378 IWineD3DDeviceImpl_Release,
4379 /*** IWineD3DDevice methods ***/
4380 IWineD3DDeviceImpl_GetParent,
4381 /*** Creation methods**/
4382 IWineD3DDeviceImpl_CreateVertexBuffer,
4383 IWineD3DDeviceImpl_CreateIndexBuffer,
4384 IWineD3DDeviceImpl_CreateStateBlock,
4385 IWineD3DDeviceImpl_CreateSurface,
4386 IWineD3DDeviceImpl_CreateTexture,
4387 IWineD3DDeviceImpl_CreateVolumeTexture,
4388 IWineD3DDeviceImpl_CreateVolume,
4389 IWineD3DDeviceImpl_CreateCubeTexture,
4390 IWineD3DDeviceImpl_CreateQuery,
4391 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
4392 IWineD3DDeviceImpl_CreateVertexDeclaration,
4393 IWineD3DDeviceImpl_CreateVertexShader,
4394 IWineD3DDeviceImpl_CreatePixelShader,
4396 /*** Odd functions **/
4397 IWineD3DDeviceImpl_EvictManagedResources,
4398 IWineD3DDeviceImpl_GetAvailableTextureMem,
4399 IWineD3DDeviceImpl_GetBackBuffer,
4400 IWineD3DDeviceImpl_GetCreationParameters,
4401 IWineD3DDeviceImpl_GetDeviceCaps,
4402 IWineD3DDeviceImpl_GetDirect3D,
4403 IWineD3DDeviceImpl_GetDisplayMode,
4404 IWineD3DDeviceImpl_GetNumberOfSwapChains,
4405 IWineD3DDeviceImpl_GetRasterStatus,
4406 IWineD3DDeviceImpl_GetSwapChain,
4407 IWineD3DDeviceImpl_Reset,
4408 IWineD3DDeviceImpl_SetDialogBoxMode,
4409 IWineD3DDeviceImpl_SetCursorProperties,
4410 IWineD3DDeviceImpl_SetCursorPosition,
4411 IWineD3DDeviceImpl_ShowCursor,
4412 IWineD3DDeviceImpl_TestCooperativeLevel,
4413 /*** Getters and setters **/
4414 IWineD3DDeviceImpl_SetClipPlane,
4415 IWineD3DDeviceImpl_GetClipPlane,
4416 IWineD3DDeviceImpl_SetClipStatus,
4417 IWineD3DDeviceImpl_GetClipStatus,
4418 IWineD3DDeviceImpl_SetCurrentTexturePalette,
4419 IWineD3DDeviceImpl_GetCurrentTexturePalette,
4420 IWineD3DDeviceImpl_SetDepthStencilSurface,
4421 IWineD3DDeviceImpl_GetDepthStencilSurface,
4422 IWineD3DDeviceImpl_SetFVF,
4423 IWineD3DDeviceImpl_GetFVF,
4424 IWineD3DDeviceImpl_SetGammaRamp,
4425 IWineD3DDeviceImpl_GetGammaRamp,
4426 IWineD3DDeviceImpl_SetIndices,
4427 IWineD3DDeviceImpl_GetIndices,
4428 IWineD3DDeviceImpl_SetLight,
4429 IWineD3DDeviceImpl_GetLight,
4430 IWineD3DDeviceImpl_SetLightEnable,
4431 IWineD3DDeviceImpl_GetLightEnable,
4432 IWineD3DDeviceImpl_SetMaterial,
4433 IWineD3DDeviceImpl_GetMaterial,
4434 IWineD3DDeviceImpl_SetNPatchMode,
4435 IWineD3DDeviceImpl_GetNPatchMode,
4436 IWineD3DDeviceImpl_SetPaletteEntries,
4437 IWineD3DDeviceImpl_GetPaletteEntries,
4438 IWineD3DDeviceImpl_SetPixelShader,
4439 IWineD3DDeviceImpl_GetPixelShader,
4440 IWineD3DDeviceImpl_SetPixelShaderConstantB,
4441 IWineD3DDeviceImpl_GetPixelShaderConstantB,
4442 IWineD3DDeviceImpl_SetPixelShaderConstantI,
4443 IWineD3DDeviceImpl_GetPixelShaderConstantI,
4444 IWineD3DDeviceImpl_SetPixelShaderConstantF,
4445 IWineD3DDeviceImpl_GetPixelShaderConstantF,
4446 IWineD3DDeviceImpl_SetRenderState,
4447 IWineD3DDeviceImpl_GetRenderState,
4448 IWineD3DDeviceImpl_SetRenderTarget,
4449 IWineD3DDeviceImpl_GetRenderTarget,
4450 IWineD3DDeviceImpl_SetSamplerState,
4451 IWineD3DDeviceImpl_GetSamplerState,
4452 IWineD3DDeviceImpl_SetScissorRect,
4453 IWineD3DDeviceImpl_GetScissorRect,
4454 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
4455 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
4456 IWineD3DDeviceImpl_SetStreamSource,
4457 IWineD3DDeviceImpl_GetStreamSource,
4458 IWineD3DDeviceImpl_SetStreamSourceFreq,
4459 IWineD3DDeviceImpl_GetStreamSourceFreq,
4460 IWineD3DDeviceImpl_SetTexture,
4461 IWineD3DDeviceImpl_GetTexture,
4462 IWineD3DDeviceImpl_SetTextureStageState,
4463 IWineD3DDeviceImpl_GetTextureStageState,
4464 IWineD3DDeviceImpl_SetTransform,
4465 IWineD3DDeviceImpl_GetTransform,
4466 IWineD3DDeviceImpl_SetVertexDeclaration,
4467 IWineD3DDeviceImpl_GetVertexDeclaration,
4468 IWineD3DDeviceImpl_SetVertexShader,
4469 IWineD3DDeviceImpl_GetVertexShader,
4470 IWineD3DDeviceImpl_SetVertexShaderConstantB,
4471 IWineD3DDeviceImpl_GetVertexShaderConstantB,
4472 IWineD3DDeviceImpl_SetVertexShaderConstantI,
4473 IWineD3DDeviceImpl_GetVertexShaderConstantI,
4474 IWineD3DDeviceImpl_SetVertexShaderConstantF,
4475 IWineD3DDeviceImpl_GetVertexShaderConstantF,
4476 IWineD3DDeviceImpl_SetViewport,
4477 IWineD3DDeviceImpl_GetViewport,
4478 IWineD3DDeviceImpl_MultiplyTransform,
4479 IWineD3DDeviceImpl_ValidateDevice,
4480 IWineD3DDeviceImpl_ProcessVertices,
4481 /*** State block ***/
4482 IWineD3DDeviceImpl_BeginStateBlock,
4483 IWineD3DDeviceImpl_EndStateBlock,
4484 /*** Scene management ***/
4485 IWineD3DDeviceImpl_BeginScene,
4486 IWineD3DDeviceImpl_EndScene,
4487 IWineD3DDeviceImpl_Present,
4488 IWineD3DDeviceImpl_Clear,
4489 /*** Drawing ***/
4490 IWineD3DDeviceImpl_DrawPrimitive,
4491 IWineD3DDeviceImpl_DrawIndexedPrimitive,
4492 IWineD3DDeviceImpl_DrawPrimitiveUP,
4493 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
4494 IWineD3DDeviceImpl_DrawRectPatch,
4495 IWineD3DDeviceImpl_DrawTriPatch,
4496 IWineD3DDeviceImpl_DeletePatch,
4497 IWineD3DDeviceImpl_ColorFill,
4498 IWineD3DDeviceImpl_UpdateTexture,
4499 IWineD3DDeviceImpl_UpdateSurface,
4500 IWineD3DDeviceImpl_StretchRect,
4501 IWineD3DDeviceImpl_GetRenderTargetData,
4502 IWineD3DDeviceImpl_GetFrontBufferData,
4503 /*** Internal use IWineD3DDevice methods ***/
4504 IWineD3DDeviceImpl_SetupTextureStates