Change the way caps are sent between d3d9/d3d8 and wined3d to make it
[wine/multimedia.git] / dlls / wined3d / device.c
blob7e5967025929ca340f16a530a0588045840d9114
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, WINED3DCAPS* pCaps) {
3630 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3631 WARN("(%p) : stub, calling idirect3d for now\n", This);
3632 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
3635 /** TODO: move to swapchains **/
3636 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
3637 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3638 HDC hdc;
3639 int bpp = 0;
3641 pMode->Width = GetSystemMetrics(SM_CXSCREEN);
3642 pMode->Height = GetSystemMetrics(SM_CYSCREEN);
3643 pMode->RefreshRate = 85; /*FIXME: How to identify? */
3645 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
3646 bpp = GetDeviceCaps(hdc, BITSPIXEL);
3647 DeleteDC(hdc);
3649 switch (bpp) {
3650 case 8: pMode->Format = WINED3DFMT_R8G8B8; break;
3651 case 16: pMode->Format = WINED3DFMT_R5G6B5; break;
3652 case 24: /*pMode->Format = WINED3DFMT_R8G8B8; break; */
3653 case 32: pMode->Format = WINED3DFMT_A8R8G8B8; break;
3654 default:
3655 FIXME("Unrecognized display mode format\n");
3656 pMode->Format = WINED3DFMT_UNKNOWN;
3659 FIXME("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate,
3660 pMode->Format, debug_d3dformat(pMode->Format));
3661 return D3D_OK;
3663 /*****
3664 * Stateblock related functions
3665 *****/
3667 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
3668 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3669 IWineD3DStateBlockImpl *object;
3670 TRACE("(%p)", This);
3671 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
3672 if(NULL == object ){
3673 FIXME("(%p)Error allocating memory for stateblock\n", This);
3674 return E_OUTOFMEMORY;
3676 TRACE("(%p) creted object %p\n", This, object);
3677 object->wineD3DDevice= This;
3678 /** FIXME: object->parent = parent; **/
3679 object->parent = NULL;
3680 object->blockType = D3DSBT_ALL;
3681 object->ref = 1;
3682 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
3684 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
3685 This->updateStateBlock = object;
3686 This->isRecordingState = TRUE;
3688 TRACE("(%p) recording stateblock %p\n",This , object);
3689 return D3D_OK;
3692 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
3693 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3695 if (!This->isRecordingState) {
3696 FIXME("(%p) not recording! returning error\n", This);
3697 *ppStateBlock = NULL;
3698 return D3DERR_INVALIDCALL;
3701 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
3702 This->isRecordingState = FALSE;
3703 This->updateStateBlock = This->stateBlock;
3704 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
3705 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
3706 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
3707 return D3D_OK;
3710 /*****
3711 * Scene related functions
3712 *****/
3713 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
3714 /* At the moment we have no need for any functionality at the beginning
3715 of a scene */
3716 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3717 TRACE("(%p) : stub\n", This);
3718 return D3D_OK;
3721 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
3722 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3723 TRACE("(%p)\n", This);
3724 ENTER_GL();
3725 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
3726 glFlush();
3727 checkGLcall("glFlush");
3729 TRACE("End Scene\n");
3730 if(This->renderTarget != NULL){
3732 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
3733 IUnknown *targetContainer = NULL;
3734 if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)) {
3735 TRACE("RenderTarget is either standalone of a texture.\n");
3736 /** always dirtify for now. we must find a better way to see that surface have been modified
3737 (Modifications should will only occur via draw-primitive, but we do need better locking
3738 switching to render-to-texture should remove the overhead though.
3740 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
3741 IWineD3DBaseTexture_SetDirty((IWineD3DBaseTexture *)targetContainer, TRUE);
3742 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *)targetContainer);
3743 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
3744 IUnknown_Release(targetContainer);
3749 LEAVE_GL();
3750 return D3D_OK;
3753 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
3754 CONST RECT* pSourceRect, CONST RECT* pDestRect,
3755 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
3756 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3757 TRACE("(%p) Presenting the frame\n", This);
3759 ENTER_GL();
3761 if (pSourceRect || pDestRect) FIXME("Unhandled present options %p/%p\n", pSourceRect, pDestRect);
3763 glXSwapBuffers(This->display, This->drawable);
3764 /* Don't call checkGLcall, as glGetError is not applicable here */
3766 TRACE("glXSwapBuffers called, Starting new frame\n");
3768 /* FPS support */
3769 if (TRACE_ON(d3d_fps))
3771 static long prev_time, frames;
3773 DWORD time = GetTickCount();
3774 frames++;
3775 /* every 1.5 seconds */
3776 if (time - prev_time > 1500) {
3777 TRACE_(d3d_fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time));
3778 prev_time = time;
3779 frames = 0;
3783 #if defined(FRAME_DEBUGGING)
3785 if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
3786 if (!isOn) {
3787 isOn = TRUE;
3788 FIXME("Enabling D3D Trace\n");
3789 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1);
3790 #if defined(SHOW_FRAME_MAKEUP)
3791 FIXME("Singe Frame snapshots Starting\n");
3792 isDumpingFrames = TRUE;
3793 glClear(GL_COLOR_BUFFER_BIT);
3794 #endif
3796 #if defined(SINGLE_FRAME_DEBUGGING)
3797 } else {
3798 #if defined(SHOW_FRAME_MAKEUP)
3799 FIXME("Singe Frame snapshots Finishing\n");
3800 isDumpingFrames = FALSE;
3801 #endif
3802 FIXME("Singe Frame trace complete\n");
3803 DeleteFileA("C:\\D3DTRACE");
3804 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
3805 #endif
3807 } else {
3808 if (isOn) {
3809 isOn = FALSE;
3810 #if defined(SHOW_FRAME_MAKEUP)
3811 FIXME("Singe Frame snapshots Finishing\n");
3812 isDumpingFrames = FALSE;
3813 #endif
3814 FIXME("Disabling D3D Trace\n");
3815 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
3819 #endif
3821 LEAVE_GL();
3822 /* Although this is not strictly required, a simple demo showed this does occur
3823 on (at least non-debug) d3d */
3824 if (This->presentParms.SwapEffect == D3DSWAPEFFECT_DISCARD) {
3825 IWineD3DDevice_Clear(iface, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
3828 return D3D_OK;
3831 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
3832 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
3833 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3835 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
3836 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
3837 when the depth-buffer format does not contain stencil buffer information, this method fails. */
3838 GLbitfield glMask = 0;
3839 GLboolean old_ztest;
3840 GLfloat old_z_clear_value;
3841 GLint old_stencil_clear_value;
3842 GLfloat old_color_clear_value[4];
3843 unsigned int i;
3844 CONST D3DRECT* curRect;
3846 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
3847 Count, pRects, Flags, Z, Stencil);
3849 ENTER_GL();
3851 glEnable(GL_SCISSOR_TEST);
3852 checkGLcall("glEnable GL_SCISSOR_TEST");
3854 if (Count > 0 && pRects) {
3855 curRect = pRects;
3856 } else {
3857 curRect = NULL;
3860 /* Only set the values up once, as they are not changing */
3861 if (Flags & D3DCLEAR_STENCIL) {
3862 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
3863 glClearStencil(Stencil);
3864 checkGLcall("glClearStencil");
3865 glMask = glMask | GL_STENCIL_BUFFER_BIT;
3866 glStencilMask(0xFFFFFFFF);
3869 if (Flags & D3DCLEAR_ZBUFFER) {
3870 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
3871 glDepthMask(GL_TRUE);
3872 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
3873 glClearDepth(Z);
3874 checkGLcall("glClearDepth");
3875 glMask = glMask | GL_DEPTH_BUFFER_BIT;
3878 if (Flags & D3DCLEAR_TARGET) {
3879 TRACE("Clearing screen with glClear to color %lx\n", Color);
3880 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
3881 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
3882 ((Color >> 8) & 0xFF) / 255.0f,
3883 ((Color >> 0) & 0xFF) / 255.0f,
3884 ((Color >> 24) & 0xFF) / 255.0f);
3885 checkGLcall("glClearColor");
3887 /* Clear ALL colors! */
3888 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3889 glMask = glMask | GL_COLOR_BUFFER_BIT;
3892 /* Now process each rect in turn */
3893 for (i = 0; i < Count || i == 0; i++) {
3895 if (curRect) {
3896 /* Note gl uses lower left, width/height */
3897 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
3898 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
3899 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
3900 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
3901 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
3902 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
3903 checkGLcall("glScissor");
3904 } else {
3905 glScissor(This->stateBlock->viewport.X,
3906 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
3907 This->stateBlock->viewport.Width,
3908 This->stateBlock->viewport.Height);
3909 checkGLcall("glScissor");
3912 /* Clear the selected rectangle (or full screen) */
3913 glClear(glMask);
3914 checkGLcall("glClear");
3916 /* Step to the next rectangle */
3917 if (curRect) curRect = curRect + sizeof(D3DRECT);
3920 /* Restore the old values (why..?) */
3921 if (Flags & D3DCLEAR_STENCIL) {
3922 glClearStencil(old_stencil_clear_value);
3923 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
3925 if (Flags & D3DCLEAR_ZBUFFER) {
3926 glDepthMask(old_ztest);
3927 glClearDepth(old_z_clear_value);
3929 if (Flags & D3DCLEAR_TARGET) {
3930 glClearColor(old_color_clear_value[0],
3931 old_color_clear_value[1],
3932 old_color_clear_value[2],
3933 old_color_clear_value[3]);
3934 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3935 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3936 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3937 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3940 glDisable(GL_SCISSOR_TEST);
3941 checkGLcall("glDisable");
3942 LEAVE_GL();
3944 return D3D_OK;
3947 /*****
3948 * Drawing functions
3949 *****/
3950 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
3951 UINT PrimitiveCount) {
3953 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3954 This->stateBlock->streamIsUP = FALSE;
3956 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
3957 debug_d3dprimitivetype(PrimitiveType),
3958 StartVertex, PrimitiveCount);
3959 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
3961 return D3D_OK;
3964 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
3965 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
3966 D3DPRIMITIVETYPE PrimitiveType,
3967 INT baseVIndex, UINT minIndex,
3968 UINT NumVertices,UINT startIndex,UINT primCount) {
3970 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3971 UINT idxStride = 2;
3972 IWineD3DIndexBuffer *pIB;
3973 D3DINDEXBUFFER_DESC IdxBufDsc;
3975 pIB = This->stateBlock->pIndexData;
3976 This->stateBlock->streamIsUP = FALSE;
3978 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d \n", This,
3979 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3980 minIndex, NumVertices, startIndex, baseVIndex, primCount);
3982 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
3983 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
3984 idxStride = 2;
3985 } else {
3986 idxStride = 4;
3989 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex,
3990 startIndex, idxStride,
3991 ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory,
3992 minIndex);
3994 return D3D_OK;
3997 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
3998 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
3999 UINT VertexStreamZeroStride) {
4000 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4002 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4003 debug_d3dprimitivetype(PrimitiveType),
4004 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4006 if (This->stateBlock->stream_source[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->stream_source[0]);
4008 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4009 This->stateBlock->stream_source[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4010 This->stateBlock->stream_stride[0] = VertexStreamZeroStride;
4011 This->stateBlock->streamIsUP = TRUE;
4012 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
4013 This->stateBlock->stream_stride[0] = 0;
4014 This->stateBlock->stream_source[0] = NULL;
4016 /*stream zero settings set to null at end, as per the msdn */
4017 return D3D_OK;
4020 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4021 UINT MinVertexIndex,
4022 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
4023 WINED3DFORMAT IndexDataFormat, CONST void* pVertexStreamZeroData,
4024 UINT VertexStreamZeroStride) {
4025 int idxStride;
4026 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4028 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4029 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4030 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData,
4031 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4033 if (This->stateBlock->stream_source[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->stream_source[0]);
4035 if (IndexDataFormat == WINED3DFMT_INDEX16) {
4036 idxStride = 2;
4037 } else {
4038 idxStride = 4;
4041 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4042 This->stateBlock->stream_source[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4043 This->stateBlock->streamIsUP = TRUE;
4044 This->stateBlock->stream_stride[0] = VertexStreamZeroStride;
4046 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, idxStride, pIndexData, MinVertexIndex);
4048 /* stream zero settings set to null at end as per the msdn */
4049 This->stateBlock->stream_source[0] = NULL;
4050 This->stateBlock->stream_stride[0] = 0;
4051 IWineD3DDevice_SetIndices(iface, NULL, 0);
4053 return D3D_OK;
4056 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
4057 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4059 TRACE("(%p) : stub\n", This);
4060 return D3D_OK;
4063 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
4064 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
4065 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
4066 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4068 TRACE("(%p) : stub\n", This);
4069 return D3D_OK;
4071 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface){
4072 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4074 TRACE("(%p) : stub\n", This);
4075 return D3D_OK;
4078 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface){
4079 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4081 TRACE("(%p) : stub\n", This);
4082 return D3D_OK;
4085 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4086 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4087 /* return a sensible default */
4088 *pNumPasses = 1;
4089 FIXME("(%p) : stub\n", This);
4090 return D3D_OK;
4093 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4094 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4095 FIXME("(%p) : stub\n", This);
4096 return D3D_OK;
4099 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4100 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4101 FIXME("(%p) : stub\n", This);
4102 return D3D_OK;
4105 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4106 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4107 FIXME("(%p) : stub\n", This);
4108 return D3D_OK;
4111 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4112 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4113 FIXME("(%p) : stub\n", This);
4114 return D3D_OK;
4117 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4118 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4119 FIXME("(%p) : stub\n", This);
4120 return D3D_OK;
4124 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4125 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4126 FIXME("(%p) : stub\n", This);
4127 return FALSE;
4131 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
4132 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4134 pRasterStatus->InVBlank = TRUE;
4135 pRasterStatus->ScanLine = 0;
4136 FIXME("(%p) : stub\n", This);
4137 return D3D_OK;
4141 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4142 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4143 static BOOL showfixmes = TRUE;
4144 if(nSegments != 0.0f){
4145 if( showfixmes){
4146 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4147 showfixmes = FALSE;
4150 return D3D_OK;
4153 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4154 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4155 static BOOL showfixmes = TRUE;
4156 if( showfixmes){
4157 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4158 showfixmes = FALSE;
4160 return 0.0f;
4164 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4165 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4166 FIXME("(%p) : stub\n", This);
4167 return D3D_OK;
4171 /* Implementation details at http://developer.nvidia.com/attach/6494
4173 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
4174 hmm.. no longer supported use
4175 OpenGL evaluators or tessellate surfaces within your application.
4178 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
4179 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo){
4180 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4181 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p) \n", This, Handle, pNumSegs, pRectPatchInfo);
4182 FIXME("(%p) : Stub\n", This);
4183 return D3D_OK;
4187 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
4188 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo){
4189 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4190 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p) \n", This, Handle, pNumSegs, pTriPatchInfo);
4191 FIXME("(%p) : Stub\n", This);
4192 return D3D_OK;
4195 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle){
4196 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4197 TRACE("(%p) Handle(%d)\n", This, Handle);
4198 FIXME("(%p) : Stub\n", This);
4199 return D3D_OK;
4202 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color){
4203 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4205 FIXME("(%p) : stub\n", This);
4206 return D3D_OK;
4209 /* rendertarget and deptth stencil functions */
4210 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget){
4211 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4213 /* FIXME: Implelent RenderTargetIndex >0 */
4214 if(RenderTargetIndex > 0)
4215 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
4217 *ppRenderTarget = (IWineD3DSurface *)This->renderTarget;
4218 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
4219 /* Note inc ref on returned surface */
4220 if(*ppRenderTarget != NULL)
4221 IWineD3DSurface_AddRef(*ppRenderTarget);
4222 return D3D_OK;
4225 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface){
4226 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4227 *ppZStencilSurface = (IWineD3DSurface *)This->depthStencilBuffer;
4228 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
4230 if(*ppZStencilSurface != NULL){
4231 /* Note inc ref on returned surface */
4232 IWineD3DSurface_AddRef(*ppZStencilSurface);
4234 return D3D_OK;
4237 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget){
4238 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4240 FIXME("(%p) : stub\n", This);
4241 return D3D_OK;
4244 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil){
4245 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4247 FIXME("(%p) : stub\n", This);
4248 return D3D_OK;
4251 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
4252 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
4253 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4254 /* TODO: the use of Impl is deprecated. */
4255 /* some basic validation checks */
4256 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
4258 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
4260 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
4261 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
4262 return D3DERR_INVALIDCALL;
4264 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
4265 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
4266 return D3DERR_INVALIDCALL;
4268 /* TODO: make the cursor 'real' */
4270 This->xHotSpot = XHotSpot;
4271 This->yHotSpot = YHotSpot;
4273 return D3D_OK;
4276 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
4277 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4278 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
4280 This->xScreenSpace = XScreenSpace;
4281 This->yScreenSpace = YScreenSpace;
4283 return;
4287 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
4288 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4289 TRACE("(%p) : visible(%d)\n", This, bShow);
4291 This->bCursorVisible = bShow;
4293 return D3D_OK;
4296 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
4297 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4298 FIXME("(%p) : stub\n", This); /* No way of notifying yet! */
4299 return D3D_OK;
4303 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
4304 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4305 /** FIXME: Resource tracking needs to be done,
4306 * The closes we can do to this is set the priorities of all managed textures low
4307 * and then reset them.
4308 ***********************************************************/
4309 FIXME("(%p) : stub\n", This);
4310 return D3D_OK;
4313 HRESULT WINAPI IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
4314 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4315 /** FIXME: Resource trascking needs to be done.
4316 * in effect this pulls all non only default
4317 * textures out of video memory and deletes all glTextures (glDeleteTextures)
4318 * and should clear down the context and set it up according to pPresentationParameters
4319 ***********************************************************/
4320 FIXME("(%p) : stub\n", This);
4321 return D3D_OK;
4324 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs){
4325 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4326 /** FIXME: always true at the moment **/
4327 if(bEnableDialogs == FALSE){
4328 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
4330 return D3D_OK;
4334 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
4335 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4337 FIXME("(%p) : stub\n", This);
4338 /* Setup some reasonable defaults */
4339 pParameters->AdapterOrdinal = 0; /* always for now */
4340 pParameters->DeviceType = D3DDEVTYPE_HAL; /* always for now */
4341 pParameters->hFocusWindow = 0;
4342 pParameters->BehaviorFlags =0;
4343 return D3D_OK;
4346 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
4347 HDC hDC;
4348 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4350 FIXME("(%p) : pRamp@%p\n", This, pRamp);
4351 hDC = GetDC(This->win_handle);
4352 SetDeviceGammaRamp(hDC, (LPVOID) pRamp);
4353 ReleaseDC(This->win_handle, hDC);
4354 return;
4357 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
4358 HDC hDC;
4359 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4361 FIXME("(%p) : pRamp@%p\n", This, pRamp);
4362 hDC = GetDC(This->win_handle);
4363 GetDeviceGammaRamp(hDC, pRamp);
4364 ReleaseDC(This->win_handle, hDC);
4365 return;
4368 /**********************************************************
4369 * IWineD3DDevice VTbl follows
4370 **********************************************************/
4372 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
4374 /*** IUnknown methods ***/
4375 IWineD3DDeviceImpl_QueryInterface,
4376 IWineD3DDeviceImpl_AddRef,
4377 IWineD3DDeviceImpl_Release,
4378 /*** IWineD3DDevice methods ***/
4379 IWineD3DDeviceImpl_GetParent,
4380 /*** Creation methods**/
4381 IWineD3DDeviceImpl_CreateVertexBuffer,
4382 IWineD3DDeviceImpl_CreateIndexBuffer,
4383 IWineD3DDeviceImpl_CreateStateBlock,
4384 IWineD3DDeviceImpl_CreateSurface,
4385 IWineD3DDeviceImpl_CreateTexture,
4386 IWineD3DDeviceImpl_CreateVolumeTexture,
4387 IWineD3DDeviceImpl_CreateVolume,
4388 IWineD3DDeviceImpl_CreateCubeTexture,
4389 IWineD3DDeviceImpl_CreateQuery,
4390 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
4391 IWineD3DDeviceImpl_CreateVertexDeclaration,
4392 IWineD3DDeviceImpl_CreateVertexShader,
4393 IWineD3DDeviceImpl_CreatePixelShader,
4395 /*** Odd functions **/
4396 IWineD3DDeviceImpl_EvictManagedResources,
4397 IWineD3DDeviceImpl_GetAvailableTextureMem,
4398 IWineD3DDeviceImpl_GetBackBuffer,
4399 IWineD3DDeviceImpl_GetCreationParameters,
4400 IWineD3DDeviceImpl_GetDeviceCaps,
4401 IWineD3DDeviceImpl_GetDirect3D,
4402 IWineD3DDeviceImpl_GetDisplayMode,
4403 IWineD3DDeviceImpl_GetNumberOfSwapChains,
4404 IWineD3DDeviceImpl_GetRasterStatus,
4405 IWineD3DDeviceImpl_GetSwapChain,
4406 IWineD3DDeviceImpl_Reset,
4407 IWineD3DDeviceImpl_SetDialogBoxMode,
4408 IWineD3DDeviceImpl_SetCursorProperties,
4409 IWineD3DDeviceImpl_SetCursorPosition,
4410 IWineD3DDeviceImpl_ShowCursor,
4411 IWineD3DDeviceImpl_TestCooperativeLevel,
4412 /*** Getters and setters **/
4413 IWineD3DDeviceImpl_SetClipPlane,
4414 IWineD3DDeviceImpl_GetClipPlane,
4415 IWineD3DDeviceImpl_SetClipStatus,
4416 IWineD3DDeviceImpl_GetClipStatus,
4417 IWineD3DDeviceImpl_SetCurrentTexturePalette,
4418 IWineD3DDeviceImpl_GetCurrentTexturePalette,
4419 IWineD3DDeviceImpl_SetDepthStencilSurface,
4420 IWineD3DDeviceImpl_GetDepthStencilSurface,
4421 IWineD3DDeviceImpl_SetFVF,
4422 IWineD3DDeviceImpl_GetFVF,
4423 IWineD3DDeviceImpl_SetGammaRamp,
4424 IWineD3DDeviceImpl_GetGammaRamp,
4425 IWineD3DDeviceImpl_SetIndices,
4426 IWineD3DDeviceImpl_GetIndices,
4427 IWineD3DDeviceImpl_SetLight,
4428 IWineD3DDeviceImpl_GetLight,
4429 IWineD3DDeviceImpl_SetLightEnable,
4430 IWineD3DDeviceImpl_GetLightEnable,
4431 IWineD3DDeviceImpl_SetMaterial,
4432 IWineD3DDeviceImpl_GetMaterial,
4433 IWineD3DDeviceImpl_SetNPatchMode,
4434 IWineD3DDeviceImpl_GetNPatchMode,
4435 IWineD3DDeviceImpl_SetPaletteEntries,
4436 IWineD3DDeviceImpl_GetPaletteEntries,
4437 IWineD3DDeviceImpl_SetPixelShader,
4438 IWineD3DDeviceImpl_GetPixelShader,
4439 IWineD3DDeviceImpl_SetPixelShaderConstantB,
4440 IWineD3DDeviceImpl_GetPixelShaderConstantB,
4441 IWineD3DDeviceImpl_SetPixelShaderConstantI,
4442 IWineD3DDeviceImpl_GetPixelShaderConstantI,
4443 IWineD3DDeviceImpl_SetPixelShaderConstantF,
4444 IWineD3DDeviceImpl_GetPixelShaderConstantF,
4445 IWineD3DDeviceImpl_SetRenderState,
4446 IWineD3DDeviceImpl_GetRenderState,
4447 IWineD3DDeviceImpl_SetRenderTarget,
4448 IWineD3DDeviceImpl_GetRenderTarget,
4449 IWineD3DDeviceImpl_SetSamplerState,
4450 IWineD3DDeviceImpl_GetSamplerState,
4451 IWineD3DDeviceImpl_SetScissorRect,
4452 IWineD3DDeviceImpl_GetScissorRect,
4453 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
4454 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
4455 IWineD3DDeviceImpl_SetStreamSource,
4456 IWineD3DDeviceImpl_GetStreamSource,
4457 IWineD3DDeviceImpl_SetStreamSourceFreq,
4458 IWineD3DDeviceImpl_GetStreamSourceFreq,
4459 IWineD3DDeviceImpl_SetTexture,
4460 IWineD3DDeviceImpl_GetTexture,
4461 IWineD3DDeviceImpl_SetTextureStageState,
4462 IWineD3DDeviceImpl_GetTextureStageState,
4463 IWineD3DDeviceImpl_SetTransform,
4464 IWineD3DDeviceImpl_GetTransform,
4465 IWineD3DDeviceImpl_SetVertexDeclaration,
4466 IWineD3DDeviceImpl_GetVertexDeclaration,
4467 IWineD3DDeviceImpl_SetVertexShader,
4468 IWineD3DDeviceImpl_GetVertexShader,
4469 IWineD3DDeviceImpl_SetVertexShaderConstantB,
4470 IWineD3DDeviceImpl_GetVertexShaderConstantB,
4471 IWineD3DDeviceImpl_SetVertexShaderConstantI,
4472 IWineD3DDeviceImpl_GetVertexShaderConstantI,
4473 IWineD3DDeviceImpl_SetVertexShaderConstantF,
4474 IWineD3DDeviceImpl_GetVertexShaderConstantF,
4475 IWineD3DDeviceImpl_SetViewport,
4476 IWineD3DDeviceImpl_GetViewport,
4477 IWineD3DDeviceImpl_MultiplyTransform,
4478 IWineD3DDeviceImpl_ValidateDevice,
4479 IWineD3DDeviceImpl_ProcessVertices,
4480 /*** State block ***/
4481 IWineD3DDeviceImpl_BeginStateBlock,
4482 IWineD3DDeviceImpl_EndStateBlock,
4483 /*** Scene management ***/
4484 IWineD3DDeviceImpl_BeginScene,
4485 IWineD3DDeviceImpl_EndScene,
4486 IWineD3DDeviceImpl_Present,
4487 IWineD3DDeviceImpl_Clear,
4488 /*** Drawing ***/
4489 IWineD3DDeviceImpl_DrawPrimitive,
4490 IWineD3DDeviceImpl_DrawIndexedPrimitive,
4491 IWineD3DDeviceImpl_DrawPrimitiveUP,
4492 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
4493 IWineD3DDeviceImpl_DrawRectPatch,
4494 IWineD3DDeviceImpl_DrawTriPatch,
4495 IWineD3DDeviceImpl_DeletePatch,
4496 IWineD3DDeviceImpl_ColorFill,
4497 IWineD3DDeviceImpl_UpdateTexture,
4498 IWineD3DDeviceImpl_UpdateSurface,
4499 IWineD3DDeviceImpl_StretchRect,
4500 IWineD3DDeviceImpl_GetRenderTargetData,
4501 IWineD3DDeviceImpl_GetFrontBufferData,
4502 /*** Internal use IWineD3DDevice methods ***/
4503 IWineD3DDeviceImpl_SetupTextureStates