Added YUV routines needed for v4l driver, and in the future possibly
[wine/gsoc-2012-control.git] / dlls / wined3d / device.c
blobc1f92a99e68aebe5ac9f4b3d4407b79e04d751f7
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 /* TODO: support for non-power 2 textures */
416 if(pow2Width > Width || pow2Height > Height){
417 /** TODO: add support for non power two compressed textures (OpenGL provices support for * non-power-two textures gratis) **/
418 return D3DERR_NOTAVAILABLE;
422 /** TODO: Check against the maximum texture sizes supported by the video card **/
424 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,D3DRTYPE_SURFACE)
425 object->container = (IUnknown*) This;
427 object->currentDesc.Width = Width;
428 object->currentDesc.Height = Height;
429 object->currentDesc.Level = Level;
430 object->currentDesc.MultiSampleType = MultiSample;
431 object->currentDesc.MultiSampleQuality = MultisampleQuality;
432 object->discard = Discard;
433 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
435 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
436 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
437 * space!
438 *********************************/
439 if (Format == WINED3DFMT_DXT1) {
440 /* DXT1 is half byte per pixel */
441 object->resource.size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4)) / 2;
443 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
444 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
445 object->resource.size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4));
446 } else {
447 object->resource.size = (Width * object->bytesPerPixel) * Height;
450 TRACE("Pool %d %d %d %d",Pool, D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM);
452 #if 0
453 /* TODO: Check that we have enough video ram left */
454 if(Pool == D3DPOOL_DEFAULT && IWineD3DDevice_GetAvailableTextureMem(iface) <= object->currentDesc.Size){
455 TRACE("Out of 'bogus' video memory\n");
456 HeapFree(GetProcessHeap(),0,object);
457 *ppSurface = NULL;
458 return D3DERR_OUTOFVIDEOMEMORY;
460 #endif
462 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
463 * this function is too deap to need to care about things like this.
464 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
465 * ****************************************/
466 switch(Pool) {
467 case D3DPOOL_SCRATCH:
468 if(Lockable == FALSE)
469 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
470 which are mutually exclusive, setting lockable to true\n");
471 Lockable = TRUE;
472 break;
473 case D3DPOOL_SYSTEMMEM:
474 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
475 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
476 case D3DPOOL_MANAGED:
477 if(Usage == D3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
478 Usage of DYNAMIC which are mutually exclusive, not doing \
479 anything just telling you.\n");
480 break;
481 case D3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
482 if(!(Usage & D3DUSAGE_DYNAMIC) && !(Usage & D3DUSAGE_RENDERTARGET)
483 && !(Usage && D3DUSAGE_DEPTHSTENCIL ) && Lockable == TRUE)
484 FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
485 break;
486 default:
487 FIXME("(%p) Unknown pool %d\n", This, Pool);
488 break;
491 if (Usage & D3DUSAGE_RENDERTARGET && Pool != D3DPOOL_DEFAULT){
492 FIXME("Trying to create a render target that isn't in the default pool\n");
496 object->locked = FALSE;
497 object->lockable = (WINED3DFMT_D16_LOCKABLE == Format) ? TRUE : Lockable;
498 /* TODO: memory management */
499 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
500 if(object->resource.allocatedMemory == NULL ) {
501 FIXME("Out of memory!\n");
502 HeapFree(GetProcessHeap(),0,object);
503 *ppSurface = NULL;
504 return D3DERR_OUTOFVIDEOMEMORY;
508 IWineD3DSurface_CleanDirtyRect(*ppSurface);
509 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
510 This, Width, Height, Format, debug_d3dformat(Format),
511 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
512 return D3D_OK;
516 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
517 DWORD Usage, WINED3DFORMAT Format, D3DPOOL Pool,
518 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
519 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
521 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
522 IWineD3DTextureImpl *object;
523 unsigned int i;
524 UINT tmpW;
525 UINT tmpH;
526 HRESULT hr;
528 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) .... \n", This, Width, Height, Levels, Usage);
530 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, D3DRTYPE_TEXTURE);
531 D3DINITILIZEBASETEXTURE(object->baseTexture);
532 object->width = Width;
533 object->height = Height;
535 /* Calculate levels for mip mapping */
536 if (Levels == 0) {
537 TRACE("calculating levels %d\n", object->baseTexture.levels);
538 object->baseTexture.levels++;
539 tmpW = Width;
540 tmpH = Height;
541 while (tmpW > 1 && tmpH > 1) {
542 tmpW = max(1, tmpW >> 1);
543 tmpH = max(1, tmpH >> 1);
544 object->baseTexture.levels++;
546 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
549 /* Generate all the surfaces */
550 tmpW = Width;
551 tmpH = Height;
552 for (i = 0; i < object->baseTexture.levels; i++)
554 /* use the callback to create the texture surface */
555 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
556 if(hr!= D3D_OK){
557 int j;
558 FIXME("Failed to create surface %p \n",object);
559 /* clean up */
560 for(j=0;j<i;j++){
561 IWineD3DSurface_Release(object->surfaces[j]);
563 /* heap free object */
564 HeapFree(GetProcessHeap(),0,object);
566 *ppTexture = NULL;
567 return hr;
570 IWineD3DSurface_SetContainer(object->surfaces[i], (IUnknown *)object);
571 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
572 /* calculate the next mipmap level */
573 tmpW = max(1, tmpW >> 1);
574 tmpH = max(1, tmpH >> 1);
577 TRACE("(%p) : Created texture %p\n", This, object);
578 return D3D_OK;
581 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
582 UINT Width, UINT Height, UINT Depth,
583 UINT Levels, DWORD Usage,
584 WINED3DFORMAT Format, D3DPOOL Pool,
585 IWineD3DVolumeTexture** ppVolumeTexture,
586 HANDLE* pSharedHandle, IUnknown *parent,
587 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
589 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
590 IWineD3DVolumeTextureImpl *object;
591 unsigned int i;
592 UINT tmpW;
593 UINT tmpH;
594 UINT tmpD;
596 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, D3DRTYPE_VOLUMETEXTURE);
597 D3DINITILIZEBASETEXTURE(object->baseTexture);
599 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
600 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
602 object->width = Width;
603 object->height = Height;
604 object->depth = Depth;
606 /* Calculate levels for mip mapping */
607 if (Levels == 0) {
608 object->baseTexture.levels++;
609 tmpW = Width;
610 tmpH = Height;
611 tmpD = Depth;
612 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
613 tmpW = max(1, tmpW >> 1);
614 tmpH = max(1, tmpH >> 1);
615 tmpD = max(1, tmpD >> 1);
616 object->baseTexture.levels++;
618 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
621 /* Generate all the surfaces */
622 tmpW = Width;
623 tmpH = Height;
624 tmpD = Depth;
626 for (i = 0; i < object->baseTexture.levels; i++)
628 /* Create the volume */
629 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
630 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
631 IWineD3DVolume_SetContainer(object->volumes[i], (IUnknown *)object);
633 tmpW = max(1, tmpW >> 1);
634 tmpH = max(1, tmpH >> 1);
635 tmpD = max(1, tmpD >> 1);
638 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
639 TRACE("(%p) : Created volume texture %p\n", This, object);
640 return D3D_OK;
643 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
644 UINT Width, UINT Height, UINT Depth,
645 DWORD Usage,
646 WINED3DFORMAT Format, D3DPOOL Pool,
647 IWineD3DVolume** ppVolume,
648 HANDLE* pSharedHandle, IUnknown *parent) {
650 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
651 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
653 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, D3DRTYPE_VOLUME)
655 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
656 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
658 object->currentDesc.Width = Width;
659 object->currentDesc.Height = Height;
660 object->currentDesc.Depth = Depth;
661 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
663 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
664 object->resource.size = (Width * object->bytesPerPixel) * Height * Depth;
665 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
666 object->lockable = TRUE;
667 object->locked = FALSE;
668 memset(&object->lockedBox, 0, sizeof(D3DBOX));
669 object->dirty = FALSE;
670 return IWineD3DVolume_CleanDirtyBox((IWineD3DVolume *) object);
673 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
674 UINT Levels, DWORD Usage,
675 WINED3DFORMAT Format, D3DPOOL Pool,
676 IWineD3DCubeTexture** ppCubeTexture,
677 HANDLE* pSharedHandle, IUnknown *parent,
678 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
680 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
681 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
682 unsigned int i,j;
683 UINT tmpW;
684 HRESULT hr;
686 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, D3DRTYPE_CUBETEXTURE);
687 D3DINITILIZEBASETEXTURE(object->baseTexture);
689 TRACE("(%p) Create Cube Texture \n", This);
691 object->edgeLength = EdgeLength;
693 /* Calculate levels for mip mapping */
694 if (Levels == 0) {
695 object->baseTexture.levels++;
696 tmpW = EdgeLength;
697 while (tmpW > 1) {
698 tmpW = max(1, tmpW / 2);
699 object->baseTexture.levels++;
701 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
704 /* Generate all the surfaces */
705 tmpW = EdgeLength;
706 for (i = 0; i < object->baseTexture.levels; i++) {
708 /* Create the 6 faces */
709 for (j = 0; j < 6; j++) {
711 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
712 i /* Level */, &object->surfaces[j][i],pSharedHandle);
714 if(hr!= D3D_OK){
715 /* clean up */
716 int k;
717 int l;
718 for (l=0;l<j;l++) {
719 IWineD3DSurface_Release(object->surfaces[j][i]);
721 for (k=0;k<i;k++) {
722 for (l=0;l<6;l++) {
723 IWineD3DSurface_Release(object->surfaces[l][j]);
727 FIXME("(%p) Failed to create surface\n",object);
728 HeapFree(GetProcessHeap(),0,object);
729 *ppCubeTexture = NULL;
730 return hr;
732 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IUnknown *)object);
733 TRACE("Created surface level %d @ %p, \n", i, object->surfaces[j][i]);
735 tmpW = max(1, tmpW >> 1);
738 TRACE("(%p) : Created Cube Texture %p\n", This, object);
739 *ppCubeTexture = (IWineD3DCubeTexture *) object;
740 return D3D_OK;
743 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent){
744 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
745 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
747 if(NULL == ppQuery){
748 /* Just a check to see if we support this type of query */
749 HRESULT hr = D3DERR_NOTAVAILABLE;
750 /* Lie and say everything is good (we can return ok fake data from a stub) */
751 switch(Type){
752 case WINED3DQUERYTYPE_VCACHE:
753 case WINED3DQUERYTYPE_RESOURCEMANAGER:
754 case WINED3DQUERYTYPE_VERTEXSTATS:
755 case WINED3DQUERYTYPE_EVENT:
756 case WINED3DQUERYTYPE_OCCLUSION:
757 case WINED3DQUERYTYPE_TIMESTAMP:
758 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
759 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
760 case WINED3DQUERYTYPE_PIPELINETIMINGS:
761 case WINED3DQUERYTYPE_INTERFACETIMINGS:
762 case WINED3DQUERYTYPE_VERTEXTIMINGS:
763 case WINED3DQUERYTYPE_PIXELTIMINGS:
764 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
765 case WINED3DQUERYTYPE_CACHEUTILIZATION:
766 hr = D3D_OK;
767 break;
768 default:
769 FIXME("(%p) Unhandled query type %d\n",This , Type);
771 FIXME("(%p) : Stub request for query type %d returned %ld\n", This, Type, hr);
772 return hr;
775 D3DCREATEOBJECTINSTANCE(object, Query)
776 object->type = Type;
777 object->extendedData = 0;
778 TRACE("(%p) : Created Query %p\n", This, object);
779 return D3D_OK;
782 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
783 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, void** ppSwapChain,
784 IUnknown* parent,
785 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
786 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil){
787 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
788 *ppSwapChain = NULL;
789 FIXME("(%p) : Stub\n",This);
790 return D3D_OK;
793 /** NOTE: These are ahead of the other getters and setters to save using a forward declartion **/
794 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
795 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
797 FIXME("(%p) : Stub\n",This);
798 return 1;
801 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, void** pSwapChain) {
802 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
804 FIXME("(%p) : Stub\n",This);
805 return D3D_OK;
808 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters){
809 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
811 FIXME("(%p) : Stub\n",This);
812 return D3D_OK;
816 /*****
817 * Vertex Declaration
818 *****/
819 /* TODO: Get ridd of thease and put the functions in the IWineD3DVertexDeclaration interface */
820 #if 1
821 extern HRESULT IWineD3DVertexDeclarationImpl_ParseDeclaration8(IWineD3DDeviceImpl * This, const DWORD* pDecl, IWineD3DVertexDeclarationImpl * object);
822 extern HRESULT IWineD3DVertexDeclarationImpl_ParseDeclaration9(IWineD3DDeviceImpl * This, const D3DVERTEXELEMENT9* pDecl, IWineD3DVertexDeclarationImpl * object);
825 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
826 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
827 IWineD3DVertexDeclarationImpl *object = NULL;
828 HRESULT hr = D3D_OK;
830 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
831 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
832 object->allFVF = 0;
834 if (8 == ((IWineD3DImpl *)This->wineD3D)->dxVersion) {
835 /** @TODO */
836 hr = IWineD3DVertexDeclarationImpl_ParseDeclaration8(This, (const DWORD*) pDeclaration, object);
837 } else {
838 hr = IWineD3DVertexDeclarationImpl_ParseDeclaration9(This, (const D3DVERTEXELEMENT9*) pDeclaration, object);
841 return hr;
845 #else
846 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration8(IWineD3DDevice* iface, const DWORD* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent){
847 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
848 IWineD3DVertexDeclarationImpl *object = NULL; /* NOTE: impl allowed, this is a create */
849 HRESULT hr = D3D_OK;
850 /* TODO: replace impl usage with a call to Version*/
851 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
852 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
853 object->allFVF = 0;
854 /* TODO: get ridd of the impl usage, we should only be using interfaces */
855 hr = IWineD3DVertexDeclarationImpl_ParseDeclaration8(This, pDeclaration, object);
857 return hr;
860 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration9(IWineD3DDevice* iface, const D3DVERTEXELEMENT9* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent){
861 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
862 IWineD3DVertexDeclarationImpl *object = NULL; /* NOTE: impl allowed, this is a create */
863 HRESULT hr = D3D_OK;
864 /* TODO: replace impl usage with a call to Version*/
865 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
866 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
867 object->allFVF = 0;
868 /* TODO: get ridd of the impl usage, we should only be using interfaces */
869 hr = IWineD3DVertexDeclarationImpl_ParseDeclaration9(This, pDeclaration, object);
871 return hr;
873 #endif
875 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
876 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DVertexShader** ppVertexShader, IUnknown *parent){
877 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
878 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
879 D3DCREATEOBJECTINSTANCE(object, VertexShader)
880 object->function = pFunction;
881 FIXME("(%p) : STUB: Created Vertex shader %p\n", This, ppVertexShader);
882 return D3D_OK;
886 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DPixelShader** ppPixelShader, IUnknown *parent){
887 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
888 FIXME("(%p) : Stub\n", This);
889 return D3D_OK;
892 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice* iface, IWineD3D** ppD3D){
893 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
894 *ppD3D= This->wineD3D;
895 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
896 IWineD3D_AddRef(*ppD3D);
897 return D3D_OK;
901 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
902 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
903 FIXME("Stub :(%p) returning 64Mib\n", This);
904 return 64*1024*1024;
908 /*****
909 * Get / Set FVF
910 *****/
911 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
912 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
914 /* Update the current state block */
915 This->updateStateBlock->fvf = fvf;
916 This->updateStateBlock->changed.fvf = TRUE;
917 This->updateStateBlock->set.fvf = TRUE;
919 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
921 /* No difference if recording or not */
922 return D3D_OK;
924 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
925 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
926 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
927 *pfvf = This->stateBlock->fvf;
928 return D3D_OK;
931 /*****
932 * Get / Set Stream Source
933 *****/
934 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
935 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
936 IWineD3DVertexBuffer *oldSrc;
938 oldSrc = This->stateBlock->stream_source[StreamNumber];
939 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
941 This->updateStateBlock->changed.stream_source[StreamNumber] = TRUE;
942 This->updateStateBlock->set.stream_source[StreamNumber] = TRUE;
943 This->updateStateBlock->stream_stride[StreamNumber] = Stride;
944 This->updateStateBlock->stream_source[StreamNumber] = pStreamData;
945 This->updateStateBlock->stream_offset[StreamNumber] = OffsetInBytes;
947 /* Handle recording of state blocks */
948 if (This->isRecordingState) {
949 TRACE("Recording... not performing anything\n");
950 return D3D_OK;
953 /* Not recording... */
954 if (oldSrc != NULL) IWineD3DVertexBuffer_Release(oldSrc);
955 if (pStreamData != NULL) IWineD3DVertexBuffer_AddRef(pStreamData);
957 return D3D_OK;
960 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
961 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
963 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->stateBlock->stream_source[StreamNumber], This->stateBlock->stream_stride[StreamNumber]);
964 *pStream = This->stateBlock->stream_source[StreamNumber];
965 *pStride = This->stateBlock->stream_stride[StreamNumber];
966 *pOffset = This->stateBlock->stream_offset[StreamNumber];
967 if (*pStream != NULL) IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
968 return D3D_OK;
971 /*Should be quite easy, just an extension of vertexdata
972 ref...
973 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
975 The divider is a bit odd though
977 VertexOffset = StartVertex / Divider * StreamStride +
978 VertexIndex / Divider * StreamStride + StreamOffset
981 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider){
982 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
984 FIXME("(%p) : stub\n", This);
985 return D3D_OK;
988 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider){
989 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
991 FIXME("(%p) : stub\n", This);
992 return D3D_OK;
996 /*****
997 * Get / Set & Multipy Transform
998 *****/
999 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1000 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1002 /* Most of this routine, comments included copied from ddraw tree initially: */
1003 TRACE("(%p) : Transform State=%d\n", This, d3dts);
1005 /* Handle recording of state blocks */
1006 if (This->isRecordingState) {
1007 TRACE("Recording... not performing anything\n");
1008 This->updateStateBlock->changed.transform[d3dts] = TRUE;
1009 This->updateStateBlock->set.transform[d3dts] = TRUE;
1010 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1011 return D3D_OK;
1015 * If the new matrix is the same as the current one,
1016 * we cut off any further processing. this seems to be a reasonable
1017 * optimization because as was noticed, some apps (warcraft3 for example)
1018 * tend towards setting the same matrix repeatedly for some reason.
1020 * From here on we assume that the new matrix is different, wherever it matters.
1022 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1023 TRACE("The app is setting the same matrix over again\n");
1024 return D3D_OK;
1025 } else {
1026 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1030 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1031 where ViewMat = Camera space, WorldMat = world space.
1033 In OpenGL, camera and world space is combined into GL_MODELVIEW
1034 matrix. The Projection matrix stay projection matrix.
1037 /* Capture the times we can just ignore the change for now */
1038 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1039 This->modelview_valid = FALSE;
1040 return D3D_OK;
1042 } else if (d3dts == D3DTS_PROJECTION) {
1043 This->proj_valid = FALSE;
1044 return D3D_OK;
1046 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1047 /* Indexed Vertex Blending Matrices 256 -> 511 */
1048 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1049 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1050 return D3D_OK;
1053 /* Now we really are going to have to change a matrix */
1054 ENTER_GL();
1056 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1057 if (d3dts < GL_LIMITS(textures)) {
1058 int tex = d3dts - D3DTS_TEXTURE0;
1059 GLACTIVETEXTURE(tex);
1060 set_texture_matrix((float *)lpmatrix,
1061 This->updateStateBlock->textureState[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
1064 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1065 unsigned int k;
1067 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1068 * NOTE: We have to reset the positions even if the light/plane is not currently
1069 * enabled, since the call to enable it will not reset the position.
1070 * NOTE2: Apparently texture transforms do NOT need reapplying
1073 PLIGHTINFOEL *lightChain = NULL;
1074 This->modelview_valid = FALSE;
1075 This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
1077 glMatrixMode(GL_MODELVIEW);
1078 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1079 glPushMatrix();
1080 glLoadMatrixf((float *)lpmatrix);
1081 checkGLcall("glLoadMatrixf(...)");
1083 /* Reset lights */
1084 lightChain = This->stateBlock->lights;
1085 while (lightChain && lightChain->glIndex != -1) {
1086 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1087 checkGLcall("glLightfv posn");
1088 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1089 checkGLcall("glLightfv dirn");
1090 lightChain = lightChain->next;
1093 /* Reset Clipping Planes if clipping is enabled */
1094 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1095 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1096 checkGLcall("glClipPlane");
1098 glPopMatrix();
1100 } else { /* What was requested!?? */
1101 WARN("invalid matrix specified: %i\n", d3dts);
1104 /* Release lock, all done */
1105 LEAVE_GL();
1106 return D3D_OK;
1109 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1110 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1111 TRACE("(%p) : for Transform State %d\n", This, State);
1112 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1113 return D3D_OK;
1116 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1117 D3DMATRIX *mat = NULL;
1118 D3DMATRIX temp;
1120 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1121 * below means it will be recorded in a state block change, but it
1122 * works regardless where it is recorded.
1123 * If this is found to be wrong, change to StateBlock.
1125 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1126 TRACE("(%p) : For state %u\n", This, State);
1128 if (State < HIGHEST_TRANSFORMSTATE)
1130 mat = &This->updateStateBlock->transforms[State];
1131 } else {
1132 FIXME("Unhandled transform state!!\n");
1135 /* Copied from ddraw code: */
1136 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);
1137 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);
1138 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);
1139 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);
1141 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);
1142 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);
1143 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);
1144 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);
1146 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);
1147 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);
1148 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);
1149 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);
1151 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);
1152 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);
1153 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);
1154 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);
1156 /* Apply change via set transform - will reapply to eg. lights this way */
1157 IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
1158 return D3D_OK;
1161 /*****
1162 * Get / Set Light
1163 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
1164 *****/
1165 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1166 you can reference any indexes you want as long as that number max are enabled at any
1167 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1168 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1169 but when recording, just build a chain pretty much of commands to be replayed. */
1171 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
1172 float rho;
1173 PLIGHTINFOEL *object, *temp;
1175 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1176 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1178 /* If recording state block, just add to end of lights chain */
1179 if (This->isRecordingState) {
1180 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1181 if (NULL == object) {
1182 return D3DERR_OUTOFVIDEOMEMORY;
1184 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1185 object->OriginalIndex = Index;
1186 object->glIndex = -1;
1187 object->changed = TRUE;
1189 /* Add to the END of the chain of lights changes to be replayed */
1190 if (This->updateStateBlock->lights == NULL) {
1191 This->updateStateBlock->lights = object;
1192 } else {
1193 temp = This->updateStateBlock->lights;
1194 while (temp->next != NULL) temp=temp->next;
1195 temp->next = object;
1197 TRACE("Recording... not performing anything more\n");
1198 return D3D_OK;
1201 /* Ok, not recording any longer so do real work */
1202 object = This->stateBlock->lights;
1203 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1205 /* If we didn't find it in the list of lights, time to add it */
1206 if (object == NULL) {
1207 PLIGHTINFOEL *insertAt,*prevPos;
1209 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1210 if (NULL == object) {
1211 return D3DERR_OUTOFVIDEOMEMORY;
1213 object->OriginalIndex = Index;
1214 object->glIndex = -1;
1216 /* Add it to the front of list with the idea that lights will be changed as needed
1217 BUT after any lights currently assigned GL indexes */
1218 insertAt = This->stateBlock->lights;
1219 prevPos = NULL;
1220 while (insertAt != NULL && insertAt->glIndex != -1) {
1221 prevPos = insertAt;
1222 insertAt = insertAt->next;
1225 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1226 This->stateBlock->lights = object;
1227 } else if (insertAt == NULL) { /* End of list */
1228 prevPos->next = object;
1229 object->prev = prevPos;
1230 } else { /* Middle of chain */
1231 if (prevPos == NULL) {
1232 This->stateBlock->lights = object;
1233 } else {
1234 prevPos->next = object;
1236 object->prev = prevPos;
1237 object->next = insertAt;
1238 insertAt->prev = object;
1242 /* Initialze the object */
1243 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,
1244 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1245 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1246 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1247 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1248 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1249 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1251 /* Save away the information */
1252 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1254 switch (pLight->Type) {
1255 case D3DLIGHT_POINT:
1256 /* Position */
1257 object->lightPosn[0] = pLight->Position.x;
1258 object->lightPosn[1] = pLight->Position.y;
1259 object->lightPosn[2] = pLight->Position.z;
1260 object->lightPosn[3] = 1.0f;
1261 object->cutoff = 180.0f;
1262 /* FIXME: Range */
1263 break;
1265 case D3DLIGHT_DIRECTIONAL:
1266 /* Direction */
1267 object->lightPosn[0] = -pLight->Direction.x;
1268 object->lightPosn[1] = -pLight->Direction.y;
1269 object->lightPosn[2] = -pLight->Direction.z;
1270 object->lightPosn[3] = 0.0;
1271 object->exponent = 0.0f;
1272 object->cutoff = 180.0f;
1273 break;
1275 case D3DLIGHT_SPOT:
1276 /* Position */
1277 object->lightPosn[0] = pLight->Position.x;
1278 object->lightPosn[1] = pLight->Position.y;
1279 object->lightPosn[2] = pLight->Position.z;
1280 object->lightPosn[3] = 1.0;
1282 /* Direction */
1283 object->lightDirn[0] = pLight->Direction.x;
1284 object->lightDirn[1] = pLight->Direction.y;
1285 object->lightDirn[2] = pLight->Direction.z;
1286 object->lightDirn[3] = 1.0;
1289 * opengl-ish and d3d-ish spot lights use too different models for the
1290 * light "intensity" as a function of the angle towards the main light direction,
1291 * so we only can approximate very roughly.
1292 * however spot lights are rather rarely used in games (if ever used at all).
1293 * furthermore if still used, probably nobody pays attention to such details.
1295 if (pLight->Falloff == 0) {
1296 rho = 6.28f;
1297 } else {
1298 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1300 if (rho < 0.0001) rho = 0.0001f;
1301 object->exponent = -0.3/log(cos(rho/2));
1302 object->cutoff = pLight->Phi*90/M_PI;
1304 /* FIXME: Range */
1305 break;
1307 default:
1308 FIXME("Unrecognized light type %d\n", pLight->Type);
1311 /* Update the live definitions if the light is currently assigned a glIndex */
1312 if (object->glIndex != -1) {
1313 setup_light(iface, object->glIndex, object);
1315 return D3D_OK;
1318 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
1319 PLIGHTINFOEL *lightInfo = NULL;
1320 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1321 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1323 /* Locate the light in the live lights */
1324 lightInfo = This->stateBlock->lights;
1325 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1327 if (lightInfo == NULL) {
1328 TRACE("Light information requested but light not defined\n");
1329 return D3DERR_INVALIDCALL;
1332 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
1333 return D3D_OK;
1336 /*****
1337 * Get / Set Light Enable
1338 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
1339 *****/
1340 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
1341 PLIGHTINFOEL *lightInfo = NULL;
1342 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1343 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1345 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1346 if (This->isRecordingState) {
1347 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1348 if (NULL == lightInfo) {
1349 return D3DERR_OUTOFVIDEOMEMORY;
1351 lightInfo->OriginalIndex = Index;
1352 lightInfo->glIndex = -1;
1353 lightInfo->enabledChanged = TRUE;
1355 /* Add to the END of the chain of lights changes to be replayed */
1356 if (This->updateStateBlock->lights == NULL) {
1357 This->updateStateBlock->lights = lightInfo;
1358 } else {
1359 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
1360 while (temp->next != NULL) temp=temp->next;
1361 temp->next = lightInfo;
1363 TRACE("Recording... not performing anything more\n");
1364 return D3D_OK;
1367 /* Not recording... So, locate the light in the live lights */
1368 lightInfo = This->stateBlock->lights;
1369 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1371 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1372 if (lightInfo == NULL) {
1373 D3DLIGHT9 lightParms;
1374 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1375 wait until someone confirms it seems to work! */
1376 TRACE("Light enabled requested but light not defined, so defining one!\n");
1377 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1378 lightParms.Diffuse.r = 1.0;
1379 lightParms.Diffuse.g = 1.0;
1380 lightParms.Diffuse.b = 1.0;
1381 lightParms.Diffuse.a = 0.0;
1382 lightParms.Specular.r = 0.0;
1383 lightParms.Specular.g = 0.0;
1384 lightParms.Specular.b = 0.0;
1385 lightParms.Specular.a = 0.0;
1386 lightParms.Ambient.r = 0.0;
1387 lightParms.Ambient.g = 0.0;
1388 lightParms.Ambient.b = 0.0;
1389 lightParms.Ambient.a = 0.0;
1390 lightParms.Position.x = 0.0;
1391 lightParms.Position.y = 0.0;
1392 lightParms.Position.z = 0.0;
1393 lightParms.Direction.x = 0.0;
1394 lightParms.Direction.y = 0.0;
1395 lightParms.Direction.z = 1.0;
1396 lightParms.Range = 0.0;
1397 lightParms.Falloff = 0.0;
1398 lightParms.Attenuation0 = 0.0;
1399 lightParms.Attenuation1 = 0.0;
1400 lightParms.Attenuation2 = 0.0;
1401 lightParms.Theta = 0.0;
1402 lightParms.Phi = 0.0;
1403 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
1405 /* Search for it again! Should be fairly quick as near head of list */
1406 lightInfo = This->stateBlock->lights;
1407 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1408 if (lightInfo == NULL) {
1409 FIXME("Adding default lights has failed dismally\n");
1410 return D3DERR_INVALIDCALL;
1414 /* OK, we now have a light... */
1415 if (Enable == FALSE) {
1417 /* If we are disabling it, check it was enabled, and
1418 still only do something if it has assigned a glIndex (which it should have!) */
1419 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
1420 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1421 ENTER_GL();
1422 glDisable(GL_LIGHT0 + lightInfo->glIndex);
1423 checkGLcall("glDisable GL_LIGHT0+Index");
1424 LEAVE_GL();
1425 } else {
1426 TRACE("Nothing to do as light was not enabled\n");
1428 lightInfo->lightEnabled = FALSE;
1429 } else {
1431 /* We are enabling it. If it is enabled, it's really simple */
1432 if (lightInfo->lightEnabled) {
1433 /* nop */
1434 TRACE("Nothing to do as light was enabled\n");
1436 /* If it already has a glIndex, it's still simple */
1437 } else if (lightInfo->glIndex != -1) {
1438 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
1439 lightInfo->lightEnabled = TRUE;
1440 ENTER_GL();
1441 glEnable(GL_LIGHT0 + lightInfo->glIndex);
1442 checkGLcall("glEnable GL_LIGHT0+Index already setup");
1443 LEAVE_GL();
1445 /* Otherwise got to find space - lights are ordered gl indexes first */
1446 } else {
1447 PLIGHTINFOEL *bsf = NULL;
1448 PLIGHTINFOEL *pos = This->stateBlock->lights;
1449 PLIGHTINFOEL *prev = NULL;
1450 int Index= 0;
1451 int glIndex = -1;
1453 /* Try to minimize changes as much as possible */
1454 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
1456 /* Try to remember which index can be replaced if necessary */
1457 if (bsf==NULL && pos->lightEnabled == FALSE) {
1458 /* Found a light we can replace, save as best replacement */
1459 bsf = pos;
1462 /* Step to next space */
1463 prev = pos;
1464 pos = pos->next;
1465 Index ++;
1468 /* If we have too many active lights, fail the call */
1469 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
1470 FIXME("Program requests too many concurrent lights\n");
1471 return D3DERR_INVALIDCALL;
1473 /* If we have allocated all lights, but not all are enabled,
1474 reuse one which is not enabled */
1475 } else if (Index == This->maxConcurrentLights) {
1476 /* use bsf - Simply swap the new light and the BSF one */
1477 PLIGHTINFOEL *bsfNext = bsf->next;
1478 PLIGHTINFOEL *bsfPrev = bsf->prev;
1480 /* Sort out ends */
1481 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
1482 if (bsf->prev != NULL) {
1483 bsf->prev->next = lightInfo;
1484 } else {
1485 This->stateBlock->lights = lightInfo;
1488 /* If not side by side, lots of chains to update */
1489 if (bsf->next != lightInfo) {
1490 lightInfo->prev->next = bsf;
1491 bsf->next->prev = lightInfo;
1492 bsf->next = lightInfo->next;
1493 bsf->prev = lightInfo->prev;
1494 lightInfo->next = bsfNext;
1495 lightInfo->prev = bsfPrev;
1497 } else {
1498 /* Simple swaps */
1499 bsf->prev = lightInfo;
1500 bsf->next = lightInfo->next;
1501 lightInfo->next = bsf;
1502 lightInfo->prev = bsfPrev;
1506 /* Update states */
1507 glIndex = bsf->glIndex;
1508 bsf->glIndex = -1;
1509 lightInfo->glIndex = glIndex;
1510 lightInfo->lightEnabled = TRUE;
1512 /* Finally set up the light in gl itself */
1513 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
1514 ENTER_GL();
1515 setup_light(iface, glIndex, lightInfo);
1516 glEnable(GL_LIGHT0 + glIndex);
1517 checkGLcall("glEnable GL_LIGHT0 new setup");
1518 LEAVE_GL();
1520 /* If we reached the end of the allocated lights, with space in the
1521 gl lights, setup a new light */
1522 } else if (pos->glIndex == -1) {
1524 /* We reached the end of the allocated gl lights, so already
1525 know the index of the next one! */
1526 glIndex = Index;
1527 lightInfo->glIndex = glIndex;
1528 lightInfo->lightEnabled = TRUE;
1530 /* In an ideal world, it's already in the right place */
1531 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
1532 /* No need to move it */
1533 } else {
1534 /* Remove this light from the list */
1535 lightInfo->prev->next = lightInfo->next;
1536 if (lightInfo->next != NULL) {
1537 lightInfo->next->prev = lightInfo->prev;
1540 /* Add in at appropriate place (inbetween prev and pos) */
1541 lightInfo->prev = prev;
1542 lightInfo->next = pos;
1543 if (prev == NULL) {
1544 This->stateBlock->lights = lightInfo;
1545 } else {
1546 prev->next = lightInfo;
1548 if (pos != NULL) {
1549 pos->prev = lightInfo;
1553 /* Finally set up the light in gl itself */
1554 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
1555 ENTER_GL();
1556 setup_light(iface, glIndex, lightInfo);
1557 glEnable(GL_LIGHT0 + glIndex);
1558 checkGLcall("glEnable GL_LIGHT0 new setup");
1559 LEAVE_GL();
1564 return D3D_OK;
1567 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
1569 PLIGHTINFOEL *lightInfo = NULL;
1570 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1571 TRACE("(%p) : for idx(%ld)\n", This, Index);
1573 /* Locate the light in the live lights */
1574 lightInfo = This->stateBlock->lights;
1575 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1577 if (lightInfo == NULL) {
1578 TRACE("Light enabled state requested but light not defined\n");
1579 return D3DERR_INVALIDCALL;
1581 *pEnable = lightInfo->lightEnabled;
1582 return D3D_OK;
1585 /*****
1586 * Get / Set Clip Planes
1587 *****/
1588 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
1589 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1590 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
1592 /* Validate Index */
1593 if (Index >= GL_LIMITS(clipplanes)) {
1594 TRACE("Application has requested clipplane this device doesn't support\n");
1595 return D3DERR_INVALIDCALL;
1598 This->updateStateBlock->changed.clipplane[Index] = TRUE;
1599 This->updateStateBlock->set.clipplane[Index] = TRUE;
1600 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
1601 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
1602 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
1603 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
1605 /* Handle recording of state blocks */
1606 if (This->isRecordingState) {
1607 TRACE("Recording... not performing anything\n");
1608 return D3D_OK;
1611 /* Apply it */
1613 ENTER_GL();
1615 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
1616 glMatrixMode(GL_MODELVIEW);
1617 glPushMatrix();
1618 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
1620 TRACE("Clipplane [%f,%f,%f,%f]\n",
1621 This->updateStateBlock->clipplane[Index][0],
1622 This->updateStateBlock->clipplane[Index][1],
1623 This->updateStateBlock->clipplane[Index][2],
1624 This->updateStateBlock->clipplane[Index][3]);
1625 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
1626 checkGLcall("glClipPlane");
1628 glPopMatrix();
1629 LEAVE_GL();
1631 return D3D_OK;
1634 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
1635 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1636 TRACE("(%p) : for idx %ld\n", This, Index);
1638 /* Validate Index */
1639 if (Index >= GL_LIMITS(clipplanes)) {
1640 TRACE("Application has requested clipplane this device doesn't support\n");
1641 return D3DERR_INVALIDCALL;
1644 pPlane[0] = This->stateBlock->clipplane[Index][0];
1645 pPlane[1] = This->stateBlock->clipplane[Index][1];
1646 pPlane[2] = This->stateBlock->clipplane[Index][2];
1647 pPlane[3] = This->stateBlock->clipplane[Index][3];
1648 return D3D_OK;
1651 /*****
1652 * Get / Set Clip Plane Status
1653 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
1654 *****/
1655 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
1656 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1657 FIXME("(%p) : stub\n", This);
1658 if (NULL == pClipStatus) {
1659 return D3DERR_INVALIDCALL;
1661 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
1662 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
1663 return D3D_OK;
1666 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
1667 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1668 FIXME("(%p) : stub\n", This);
1669 if (NULL == pClipStatus) {
1670 return D3DERR_INVALIDCALL;
1672 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
1673 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
1674 return D3D_OK;
1677 /*****
1678 * Get / Set Material
1679 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
1680 *****/
1681 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
1682 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1684 This->updateStateBlock->changed.material = TRUE;
1685 This->updateStateBlock->set.material = TRUE;
1686 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
1688 /* Handle recording of state blocks */
1689 if (This->isRecordingState) {
1690 TRACE("Recording... not performing anything\n");
1691 return D3D_OK;
1694 ENTER_GL();
1695 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1696 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1697 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1698 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1699 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1701 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
1702 checkGLcall("glMaterialfv");
1703 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
1704 checkGLcall("glMaterialfv");
1706 /* Only change material color if specular is enabled, otherwise it is set to black */
1707 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
1708 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
1709 checkGLcall("glMaterialfv");
1710 } else {
1711 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1712 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1713 checkGLcall("glMaterialfv");
1715 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
1716 checkGLcall("glMaterialfv");
1717 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
1718 checkGLcall("glMaterialf");
1720 LEAVE_GL();
1721 return D3D_OK;
1724 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
1725 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1726 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
1727 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1728 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1729 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1730 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1731 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1732 return D3D_OK;
1735 /*****
1736 * Get / Set Indices
1737 *****/
1738 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
1739 UINT BaseVertexIndex) {
1740 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1741 IWineD3DIndexBuffer *oldIdxs;
1743 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
1744 oldIdxs = This->updateStateBlock->pIndexData;
1746 This->updateStateBlock->changed.indices = TRUE;
1747 This->updateStateBlock->set.indices = TRUE;
1748 This->updateStateBlock->pIndexData = pIndexData;
1749 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
1751 /* Handle recording of state blocks */
1752 if (This->isRecordingState) {
1753 TRACE("Recording... not performing anything\n");
1754 return D3D_OK;
1757 if (oldIdxs) IWineD3DIndexBuffer_Release(oldIdxs);
1758 if (pIndexData) IWineD3DIndexBuffer_AddRef(This->stateBlock->pIndexData);
1759 return D3D_OK;
1762 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
1763 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1765 *ppIndexData = This->stateBlock->pIndexData;
1767 /* up ref count on ppindexdata */
1768 if (*ppIndexData) IWineD3DIndexBuffer_AddRef(*ppIndexData);
1769 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
1771 return D3D_OK;
1774 /*****
1775 * Get / Set Viewports
1776 *****/
1777 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
1778 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1780 TRACE("(%p)\n", This);
1781 This->updateStateBlock->changed.viewport = TRUE;
1782 This->updateStateBlock->set.viewport = TRUE;
1783 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
1785 /* Handle recording of state blocks */
1786 if (This->isRecordingState) {
1787 TRACE("Recording... not performing anything\n");
1788 return D3D_OK;
1791 ENTER_GL();
1793 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
1794 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
1796 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
1797 checkGLcall("glDepthRange");
1798 /* Note: GL requires lower left, DirectX supplies upper left */
1799 /* TODO: replace usage of renderTarget with context management */
1800 glViewport(pViewport->X, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
1801 pViewport->Width, pViewport->Height);
1802 checkGLcall("glViewport");
1804 LEAVE_GL();
1806 return D3D_OK;
1810 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
1811 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1812 TRACE("(%p)\n", This);
1813 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
1814 return D3D_OK;
1817 /*****
1818 * Get / Set Render States
1819 * TODO: Verify against dx9 definitions
1820 *****/
1821 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
1823 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1824 DWORD OldValue = This->stateBlock->renderState[State];
1826 /* Simple way of referring to either a DWORD or a 4 byte float */
1827 union {
1828 DWORD d;
1829 float f;
1830 } tmpvalue;
1832 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
1833 This->updateStateBlock->changed.renderState[State] = TRUE;
1834 This->updateStateBlock->set.renderState[State] = TRUE;
1835 This->updateStateBlock->renderState[State] = Value;
1837 /* Handle recording of state blocks */
1838 if (This->isRecordingState) {
1839 TRACE("Recording... not performing anything\n");
1840 return D3D_OK;
1843 ENTER_GL();
1845 switch (State) {
1846 case WINED3DRS_FILLMODE :
1847 switch ((D3DFILLMODE) Value) {
1848 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
1849 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
1850 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
1851 default:
1852 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
1854 checkGLcall("glPolygonMode (fillmode)");
1855 break;
1857 case WINED3DRS_LIGHTING :
1858 if (Value) {
1859 glEnable(GL_LIGHTING);
1860 checkGLcall("glEnable GL_LIGHTING");
1861 } else {
1862 glDisable(GL_LIGHTING);
1863 checkGLcall("glDisable GL_LIGHTING");
1865 break;
1867 case WINED3DRS_ZENABLE :
1868 switch ((D3DZBUFFERTYPE) Value) {
1869 case D3DZB_FALSE:
1870 glDisable(GL_DEPTH_TEST);
1871 checkGLcall("glDisable GL_DEPTH_TEST");
1872 break;
1873 case D3DZB_TRUE:
1874 glEnable(GL_DEPTH_TEST);
1875 checkGLcall("glEnable GL_DEPTH_TEST");
1876 break;
1877 case D3DZB_USEW:
1878 glEnable(GL_DEPTH_TEST);
1879 checkGLcall("glEnable GL_DEPTH_TEST");
1880 FIXME("W buffer is not well handled\n");
1881 break;
1882 default:
1883 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
1885 break;
1887 case WINED3DRS_CULLMODE :
1889 /* If we are culling "back faces with clockwise vertices" then
1890 set front faces to be counter clockwise and enable culling
1891 of back faces */
1892 switch ((D3DCULL) Value) {
1893 case D3DCULL_NONE:
1894 glDisable(GL_CULL_FACE);
1895 checkGLcall("glDisable GL_CULL_FACE");
1896 break;
1897 case D3DCULL_CW:
1898 glEnable(GL_CULL_FACE);
1899 checkGLcall("glEnable GL_CULL_FACE");
1900 if (This->renderUpsideDown) {
1901 glFrontFace(GL_CW);
1902 checkGLcall("glFrontFace GL_CW");
1903 } else {
1904 glFrontFace(GL_CCW);
1905 checkGLcall("glFrontFace GL_CCW");
1907 glCullFace(GL_BACK);
1908 break;
1909 case D3DCULL_CCW:
1910 glEnable(GL_CULL_FACE);
1911 checkGLcall("glEnable GL_CULL_FACE");
1912 if (This->renderUpsideDown) {
1913 glFrontFace(GL_CCW);
1914 checkGLcall("glFrontFace GL_CCW");
1915 } else {
1916 glFrontFace(GL_CW);
1917 checkGLcall("glFrontFace GL_CW");
1919 glCullFace(GL_BACK);
1920 break;
1921 default:
1922 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
1924 break;
1926 case WINED3DRS_SHADEMODE :
1927 switch ((D3DSHADEMODE) Value) {
1928 case D3DSHADE_FLAT:
1929 glShadeModel(GL_FLAT);
1930 checkGLcall("glShadeModel");
1931 break;
1932 case D3DSHADE_GOURAUD:
1933 glShadeModel(GL_SMOOTH);
1934 checkGLcall("glShadeModel");
1935 break;
1936 case D3DSHADE_PHONG:
1937 FIXME("D3DSHADE_PHONG isn't supported?\n");
1939 LEAVE_GL();
1940 return D3DERR_INVALIDCALL;
1941 default:
1942 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
1944 break;
1946 case WINED3DRS_DITHERENABLE :
1947 if (Value) {
1948 glEnable(GL_DITHER);
1949 checkGLcall("glEnable GL_DITHER");
1950 } else {
1951 glDisable(GL_DITHER);
1952 checkGLcall("glDisable GL_DITHER");
1954 break;
1956 case WINED3DRS_ZWRITEENABLE :
1957 if (Value) {
1958 glDepthMask(1);
1959 checkGLcall("glDepthMask");
1960 } else {
1961 glDepthMask(0);
1962 checkGLcall("glDepthMask");
1964 break;
1966 case WINED3DRS_ZFUNC :
1968 int glParm = GL_LESS;
1970 switch ((D3DCMPFUNC) Value) {
1971 case D3DCMP_NEVER: glParm=GL_NEVER; break;
1972 case D3DCMP_LESS: glParm=GL_LESS; break;
1973 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
1974 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
1975 case D3DCMP_GREATER: glParm=GL_GREATER; break;
1976 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
1977 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
1978 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
1979 default:
1980 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
1982 glDepthFunc(glParm);
1983 checkGLcall("glDepthFunc");
1985 break;
1987 case WINED3DRS_AMBIENT :
1989 float col[4];
1990 D3DCOLORTOGLFLOAT4(Value, col);
1991 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
1992 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
1993 checkGLcall("glLightModel for MODEL_AMBIENT");
1996 break;
1998 case WINED3DRS_ALPHABLENDENABLE :
1999 if (Value) {
2000 glEnable(GL_BLEND);
2001 checkGLcall("glEnable GL_BLEND");
2002 } else {
2003 glDisable(GL_BLEND);
2004 checkGLcall("glDisable GL_BLEND");
2006 break;
2008 case WINED3DRS_SRCBLEND :
2009 case WINED3DRS_DESTBLEND :
2011 int newVal = GL_ZERO;
2012 switch (Value) {
2013 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2014 case D3DBLEND_ONE : newVal = GL_ONE; break;
2015 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2016 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2017 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2018 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2019 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2020 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2021 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2022 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2023 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2025 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2026 This->srcBlend = newVal;
2027 This->dstBlend = newVal;
2028 break;
2030 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2031 This->srcBlend = newVal;
2032 This->dstBlend = newVal;
2033 break;
2034 default:
2035 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2038 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2039 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2040 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2041 glBlendFunc(This->srcBlend, This->dstBlend);
2043 checkGLcall("glBlendFunc");
2045 break;
2047 case WINED3DRS_ALPHATESTENABLE :
2048 if (Value) {
2049 glEnable(GL_ALPHA_TEST);
2050 checkGLcall("glEnable GL_ALPHA_TEST");
2051 } else {
2052 glDisable(GL_ALPHA_TEST);
2053 checkGLcall("glDisable GL_ALPHA_TEST");
2055 break;
2057 case WINED3DRS_ALPHAFUNC :
2059 int glParm = GL_LESS;
2060 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2062 switch ((D3DCMPFUNC) Value) {
2063 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2064 case D3DCMP_LESS: glParm = GL_LESS; break;
2065 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2066 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2067 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2068 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2069 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2070 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2071 default:
2072 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2074 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2075 glAlphaFunc(glParm, ref);
2076 This->alphafunc = glParm;
2077 checkGLcall("glAlphaFunc");
2079 break;
2081 case WINED3DRS_ALPHAREF :
2083 int glParm = This->alphafunc;
2084 float ref = 1.0f;
2086 ref = ((float) Value) / 255.0f;
2087 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2088 glAlphaFunc(glParm, ref);
2089 checkGLcall("glAlphaFunc");
2091 break;
2093 case WINED3DRS_CLIPPLANEENABLE :
2094 case WINED3DRS_CLIPPING :
2096 /* Ensure we only do the changed clip planes */
2097 DWORD enable = 0xFFFFFFFF;
2098 DWORD disable = 0x00000000;
2100 /* If enabling / disabling all */
2101 if (State == WINED3DRS_CLIPPING) {
2102 if (Value) {
2103 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2104 disable = 0x00;
2105 } else {
2106 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2107 enable = 0x00;
2109 } else {
2110 enable = Value & ~OldValue;
2111 disable = ~Value & OldValue;
2114 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2115 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2116 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2117 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2118 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2119 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2121 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2122 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2123 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2124 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2125 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2126 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2128 /** update clipping status */
2129 if (enable) {
2130 This->stateBlock->clip_status.ClipUnion = 0;
2131 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
2132 } else {
2133 This->stateBlock->clip_status.ClipUnion = 0;
2134 This->stateBlock->clip_status.ClipIntersection = 0;
2137 break;
2139 case WINED3DRS_BLENDOP :
2141 int glParm = GL_FUNC_ADD;
2143 switch ((D3DBLENDOP) Value) {
2144 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2145 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2146 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2147 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2148 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2149 default:
2150 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2152 TRACE("glBlendEquation(%x)\n", glParm);
2153 glBlendEquation(glParm);
2154 checkGLcall("glBlendEquation");
2156 break;
2158 case WINED3DRS_TEXTUREFACTOR :
2160 unsigned int i;
2162 /* Note the texture color applies to all textures whereas
2163 GL_TEXTURE_ENV_COLOR applies to active only */
2164 float col[4];
2165 D3DCOLORTOGLFLOAT4(Value, col);
2166 /* Set the default alpha blend color */
2167 glBlendColor(col[0], col[1], col[2], col[3]);
2168 checkGLcall("glBlendColor");
2170 /* And now the default texture color as well */
2171 for (i = 0; i < GL_LIMITS(textures); i++) {
2173 /* Note the D3DRS value applies to all textures, but GL has one
2174 per texture, so apply it now ready to be used! */
2175 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2176 GLACTIVETEXTURE(i);
2177 } else if (i>0) {
2178 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2181 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2182 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2185 break;
2187 case WINED3DRS_SPECULARENABLE :
2189 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2190 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2191 specular color. This is wrong:
2192 Separate specular color means the specular colour is maintained separately, whereas
2193 single color means it is merged in. However in both cases they are being used to
2194 some extent.
2195 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2196 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2197 running 1.4 yet!
2199 if (Value) {
2200 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2201 checkGLcall("glMaterialfv");
2202 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2203 glEnable(GL_COLOR_SUM_EXT);
2204 } else {
2205 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2207 checkGLcall("glEnable(GL_COLOR_SUM)");
2208 } else {
2209 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2211 /* for the case of enabled lighting: */
2212 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2213 checkGLcall("glMaterialfv");
2215 /* for the case of disabled lighting: */
2216 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2217 glDisable(GL_COLOR_SUM_EXT);
2218 } else {
2219 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2221 checkGLcall("glDisable(GL_COLOR_SUM)");
2224 break;
2226 case WINED3DRS_STENCILENABLE :
2227 if (Value) {
2228 glEnable(GL_STENCIL_TEST);
2229 checkGLcall("glEnable GL_STENCIL_TEST");
2230 } else {
2231 glDisable(GL_STENCIL_TEST);
2232 checkGLcall("glDisable GL_STENCIL_TEST");
2234 break;
2236 case WINED3DRS_STENCILFUNC :
2238 int glParm = GL_ALWAYS;
2239 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2240 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2242 switch ((D3DCMPFUNC) Value) {
2243 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2244 case D3DCMP_LESS: glParm=GL_LESS; break;
2245 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2246 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2247 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2248 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2249 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2250 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2251 default:
2252 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2254 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2255 This->stencilfunc = glParm;
2256 glStencilFunc(glParm, ref, mask);
2257 checkGLcall("glStencilFunc");
2259 break;
2261 case WINED3DRS_STENCILREF :
2263 int glParm = This->stencilfunc;
2264 int ref = 0;
2265 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2267 ref = Value;
2268 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2269 glStencilFunc(glParm, ref, mask);
2270 checkGLcall("glStencilFunc");
2272 break;
2274 case WINED3DRS_STENCILMASK :
2276 int glParm = This->stencilfunc;
2277 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2278 GLuint mask = Value;
2280 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2281 glStencilFunc(glParm, ref, mask);
2282 checkGLcall("glStencilFunc");
2284 break;
2286 case WINED3DRS_STENCILFAIL :
2288 GLenum fail ;
2289 GLenum zpass ;
2290 GLenum zfail ;
2292 fail = StencilOp(Value);
2293 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2294 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2295 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2296 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2298 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2299 glStencilOp(fail, zfail, zpass);
2300 checkGLcall("glStencilOp(fail, zfail, zpass);");
2302 break;
2303 case WINED3DRS_STENCILZFAIL :
2305 GLenum fail ;
2306 GLenum zpass ;
2307 GLenum zfail ;
2309 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2310 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2311 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2312 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2313 zfail = StencilOp(Value);
2315 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2316 glStencilOp(fail, zfail, zpass);
2317 checkGLcall("glStencilOp(fail, zfail, zpass);");
2319 break;
2320 case WINED3DRS_STENCILPASS :
2322 GLenum fail ;
2323 GLenum zpass ;
2324 GLenum zfail ;
2326 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2327 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2328 zpass = StencilOp(Value);
2329 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2330 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2332 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2333 glStencilOp(fail, zfail, zpass);
2334 checkGLcall("glStencilOp(fail, zfail, zpass);");
2336 break;
2338 case WINED3DRS_STENCILWRITEMASK :
2340 glStencilMask(Value);
2341 TRACE("glStencilMask(%lu)\n", Value);
2342 checkGLcall("glStencilMask");
2344 break;
2346 case WINED3DRS_FOGENABLE :
2348 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2349 glEnable(GL_FOG);
2350 checkGLcall("glEnable GL_FOG");
2351 } else {
2352 glDisable(GL_FOG);
2353 checkGLcall("glDisable GL_FOG");
2356 break;
2358 case WINED3DRS_RANGEFOGENABLE :
2360 if (Value) {
2361 TRACE("Enabled RANGEFOG");
2362 } else {
2363 TRACE("Disabled RANGEFOG");
2366 break;
2368 case WINED3DRS_FOGCOLOR :
2370 float col[4];
2371 D3DCOLORTOGLFLOAT4(Value, col);
2372 /* Set the default alpha blend color */
2373 glFogfv(GL_FOG_COLOR, &col[0]);
2374 checkGLcall("glFog GL_FOG_COLOR");
2376 break;
2378 case WINED3DRS_FOGTABLEMODE :
2380 glHint(GL_FOG_HINT, GL_NICEST);
2381 switch (Value) {
2382 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2383 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2384 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2385 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2386 default:
2387 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
2389 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2390 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
2393 break;
2395 case WINED3DRS_FOGVERTEXMODE :
2397 glHint(GL_FOG_HINT, GL_FASTEST);
2398 switch (Value) {
2399 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2400 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2401 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2402 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2403 default:
2404 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
2406 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2407 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
2410 break;
2412 case WINED3DRS_FOGSTART :
2414 tmpvalue.d = Value;
2415 glFogfv(GL_FOG_START, &tmpvalue.f);
2416 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2417 TRACE("Fog Start == %f\n", tmpvalue.f);
2419 break;
2421 case WINED3DRS_FOGEND :
2423 tmpvalue.d = Value;
2424 glFogfv(GL_FOG_END, &tmpvalue.f);
2425 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2426 TRACE("Fog End == %f\n", tmpvalue.f);
2428 break;
2430 case WINED3DRS_FOGDENSITY :
2432 tmpvalue.d = Value;
2433 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
2434 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2436 break;
2438 case WINED3DRS_VERTEXBLEND :
2440 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2441 TRACE("Vertex Blending state to %ld\n", Value);
2443 break;
2445 case WINED3DRS_TWEENFACTOR :
2447 tmpvalue.d = Value;
2448 This->updateStateBlock->tween_factor = tmpvalue.f;
2449 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
2451 break;
2453 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
2455 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2457 break;
2459 case WINED3DRS_COLORVERTEX :
2460 case WINED3DRS_DIFFUSEMATERIALSOURCE :
2461 case WINED3DRS_SPECULARMATERIALSOURCE :
2462 case WINED3DRS_AMBIENTMATERIALSOURCE :
2463 case WINED3DRS_EMISSIVEMATERIALSOURCE :
2465 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2467 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
2468 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2469 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
2470 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
2471 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
2472 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
2474 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2475 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2476 Parm = GL_AMBIENT_AND_DIFFUSE;
2477 } else {
2478 Parm = GL_DIFFUSE;
2480 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2481 Parm = GL_AMBIENT;
2482 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2483 Parm = GL_EMISSION;
2484 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2485 Parm = GL_SPECULAR;
2486 } else {
2487 Parm = -1;
2490 if (Parm == -1) {
2491 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2492 } else {
2493 This->tracking_color = NEEDS_TRACKING;
2494 This->tracking_parm = Parm;
2497 } else {
2498 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2501 break;
2503 case WINED3DRS_LINEPATTERN :
2505 union {
2506 DWORD d;
2507 D3DLINEPATTERN lp;
2508 } tmppattern;
2509 tmppattern.d = Value;
2511 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2513 if (tmppattern.lp.wRepeatFactor) {
2514 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2515 checkGLcall("glLineStipple(repeat, linepattern)");
2516 glEnable(GL_LINE_STIPPLE);
2517 checkGLcall("glEnable(GL_LINE_STIPPLE);");
2518 } else {
2519 glDisable(GL_LINE_STIPPLE);
2520 checkGLcall("glDisable(GL_LINE_STIPPLE);");
2523 break;
2525 case WINED3DRS_ZBIAS :
2527 if (Value) {
2528 tmpvalue.d = Value;
2529 TRACE("ZBias value %f\n", tmpvalue.f);
2530 glPolygonOffset(0, -tmpvalue.f);
2531 checkGLcall("glPolygonOffset(0, -Value)");
2532 glEnable(GL_POLYGON_OFFSET_FILL);
2533 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
2534 glEnable(GL_POLYGON_OFFSET_LINE);
2535 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
2536 glEnable(GL_POLYGON_OFFSET_POINT);
2537 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
2538 } else {
2539 glDisable(GL_POLYGON_OFFSET_FILL);
2540 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
2541 glDisable(GL_POLYGON_OFFSET_LINE);
2542 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
2543 glDisable(GL_POLYGON_OFFSET_POINT);
2544 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
2547 break;
2549 case WINED3DRS_NORMALIZENORMALS :
2550 if (Value) {
2551 glEnable(GL_NORMALIZE);
2552 checkGLcall("glEnable(GL_NORMALIZE);");
2553 } else {
2554 glDisable(GL_NORMALIZE);
2555 checkGLcall("glDisable(GL_NORMALIZE);");
2557 break;
2559 case WINED3DRS_POINTSIZE :
2560 tmpvalue.d = Value;
2561 TRACE("Set point size to %f\n", tmpvalue.f);
2562 glPointSize(tmpvalue.f);
2563 checkGLcall("glPointSize(...);");
2564 break;
2566 case WINED3DRS_POINTSIZE_MIN :
2567 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2568 tmpvalue.d = Value;
2569 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
2570 checkGLcall("glPointParameterfEXT(...);");
2571 } else {
2572 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
2574 break;
2576 case WINED3DRS_POINTSIZE_MAX :
2577 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2578 tmpvalue.d = Value;
2579 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
2580 checkGLcall("glPointParameterfEXT(...);");
2581 } else {
2582 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
2584 break;
2586 case WINED3DRS_POINTSCALE_A :
2587 case WINED3DRS_POINTSCALE_B :
2588 case WINED3DRS_POINTSCALE_C :
2589 case WINED3DRS_POINTSCALEENABLE :
2591 /* If enabled, supply the parameters, otherwise fall back to defaults */
2592 if (This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
2593 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2594 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]);
2595 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]);
2596 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]);
2598 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2599 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2600 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2601 } else {
2602 TRACE("WINED3DRS_POINTSCALEENABLE not supported on this opengl\n");
2604 } else {
2605 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2606 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2607 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2608 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2609 } else {
2610 TRACE("WINED3DRS_POINTSCALEENABLE not supported, but not on either\n");
2613 break;
2616 case WINED3DRS_COLORWRITEENABLE :
2618 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
2619 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
2620 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
2621 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
2622 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
2623 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
2624 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
2625 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
2626 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
2627 checkGLcall("glColorMask(...)");
2629 break;
2631 case WINED3DRS_LOCALVIEWER :
2633 GLint state = (Value) ? 1 : 0;
2634 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
2635 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
2637 break;
2639 case WINED3DRS_LASTPIXEL :
2641 if (Value) {
2642 TRACE("Last Pixel Drawing Enabled\n");
2643 } else {
2644 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
2647 break;
2649 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
2651 if (Value) {
2652 TRACE("Software Processing Enabled\n");
2653 } else {
2654 TRACE("Software Processing Disabled\n");
2657 break;
2659 /** not supported */
2660 case WINED3DRS_ZVISIBLE :
2662 LEAVE_GL();
2663 return D3DERR_INVALIDCALL;
2666 /* Unhandled yet...! */
2667 case WINED3DRS_EDGEANTIALIAS :
2668 case WINED3DRS_WRAP0 :
2669 case WINED3DRS_WRAP1 :
2670 case WINED3DRS_WRAP2 :
2671 case WINED3DRS_WRAP3 :
2672 case WINED3DRS_WRAP4 :
2673 case WINED3DRS_WRAP5 :
2674 case WINED3DRS_WRAP6 :
2675 case WINED3DRS_WRAP7 :
2676 case WINED3DRS_POINTSPRITEENABLE :
2677 case WINED3DRS_MULTISAMPLEANTIALIAS :
2678 case WINED3DRS_MULTISAMPLEMASK :
2679 case WINED3DRS_PATCHEDGESTYLE :
2680 case WINED3DRS_PATCHSEGMENTS :
2681 case WINED3DRS_DEBUGMONITORTOKEN :
2682 case WINED3DRS_POSITIONORDER :
2683 case WINED3DRS_NORMALORDER :
2684 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
2685 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
2686 break;
2687 default:
2688 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
2691 LEAVE_GL();
2693 return D3D_OK;
2696 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
2697 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2698 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
2699 *pValue = This->stateBlock->renderState[State];
2700 return D3D_OK;
2703 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value){
2704 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2706 FIXME("(%p) : stub\n", This);
2707 return D3D_OK;
2710 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value){
2711 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2713 FIXME("(%p) : stub\n", This);
2714 return D3D_OK;
2718 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect){
2719 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2720 ENTER_GL();
2722 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
2723 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
2724 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
2725 LEAVE_GL();
2726 return D3D_OK;
2729 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect){
2730 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2731 GLint scissorBox[4];
2733 ENTER_GL();
2734 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
2735 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
2736 pRect->left = scissorBox[1];
2737 pRect->top = scissorBox[2];
2738 pRect->right = scissorBox[1] + scissorBox[3];
2739 pRect->bottom = scissorBox[2] + scissorBox[4];
2740 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
2741 LEAVE_GL();
2742 return D3D_OK;
2745 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
2746 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2748 TRACE("(%p) : pDecl=%p\n", This, pDecl);
2750 IWineD3DVertexDeclaration_AddRef(pDecl);
2751 if (NULL != This->updateStateBlock->vertexDecl) {
2752 IWineD3DVertexDeclaration_Release(This->updateStateBlock->vertexDecl);
2754 This->updateStateBlock->vertexDecl = pDecl;
2755 This->updateStateBlock->changed.vertexDecl = TRUE;
2756 This->updateStateBlock->set.vertexDecl = TRUE;
2757 return D3D_OK;
2760 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
2761 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2763 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
2765 *ppDecl = This->updateStateBlock->vertexDecl;
2766 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
2767 return D3D_OK;
2770 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader){
2771 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2773 static BOOL showFixmes = TRUE;
2775 This->updateStateBlock->vertexShader = pShader;
2776 This->updateStateBlock->changed.vertexShader = TRUE;
2777 This->updateStateBlock->set.vertexShader = TRUE;
2779 if(pShader == NULL){
2780 /* clear down the shader */
2781 TRACE("Clear down the shader\n");
2782 }else{
2783 if(showFixmes){
2784 FIXME("(%p) : stub pShader(%p)\n", This, pShader);
2785 showFixmes = FALSE;
2789 return D3D_OK;
2791 /** FIXME: refernece counting? **/
2792 if (pShader == NULL) { /* only valid with non FVF shaders */
2793 TRACE_(d3d_shader)("(%p) : FVF Shader, pShader=%p\n", This, pShader);
2794 This->updateStateBlock->vertexShader = NULL;
2795 } else {
2796 TRACE_(d3d_shader)("(%p) : Created shader, pShader=%p\n", This, pShader);
2797 This->updateStateBlock->vertexShader = pShader;
2800 This->updateStateBlock->changed.vertexShader = TRUE;
2801 This->updateStateBlock->set.vertexShader = TRUE;
2803 /* Handle recording of state blocks */
2804 if (This->isRecordingState) {
2805 TRACE("Recording... not performing anything\n");
2806 return D3D_OK;
2809 * TODO: merge HAL shaders context switching from prototype
2811 return D3D_OK;
2815 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader){
2816 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2817 *ppShader = This->stateBlock->vertexShader;
2818 if(*ppShader != NULL)
2819 IWineD3DVertexShader_AddRef(*ppShader);
2820 TRACE("(%p) : returning %p\n", This, *ppShader);
2821 return D3D_OK;
2824 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
2825 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2827 TRACE("(%p) : stub\n", This);
2828 return D3D_OK;
2831 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
2832 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2833 TRACE("(%p) : stub\n", This);
2834 return D3D_OK;
2837 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
2838 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2839 TRACE("(%p) : stub\n", This);
2840 return D3D_OK;
2843 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
2844 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2845 TRACE("(%p) : stub\n", This);
2846 return D3D_OK;
2849 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
2850 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2851 TRACE("(%p) : stub\n", This);
2852 return D3D_OK;
2855 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
2856 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2857 TRACE("(%p) : stub\n", This);
2858 return D3D_OK;
2861 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader){
2862 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2863 TRACE("(%p) : stub\n", This);
2864 return D3D_OK;
2867 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader){
2868 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2869 TRACE("(%p) : stub\n", This);
2870 return D3D_OK;
2874 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
2875 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2876 TRACE("(%p) : stub\n", This);
2877 return D3D_OK;
2880 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
2881 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2882 TRACE("(%p) : stub\n", This);
2883 return D3D_OK;
2886 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
2887 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2888 TRACE("(%p) : stub\n", This);
2889 return D3D_OK;
2892 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
2893 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2894 TRACE("(%p) : stub\n", This);
2895 return D3D_OK;
2898 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
2899 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2900 TRACE("(%p) : stub\n", This);
2901 return D3D_OK;
2904 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
2905 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2906 TRACE("(%p) : stub\n", This);
2907 return D3D_OK;
2910 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags){
2911 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2912 FIXME("(%p) : stub\n", This);
2913 return D3D_OK;
2916 /*****
2917 * Get / Set Texture Stage States
2918 * TODO: Verify against dx9 definitions
2919 *****/
2920 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
2921 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2922 union {
2923 float f;
2924 DWORD d;
2925 } tmpvalue;
2927 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
2929 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
2931 /* Reject invalid texture units */
2932 if (Stage >= GL_LIMITS(textures)) {
2933 TRACE("Attempt to access invalid texture rejected\n");
2934 return D3DERR_INVALIDCALL;
2937 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
2938 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
2939 This->updateStateBlock->textureState[Stage][Type] = Value;
2941 /* Handle recording of state blocks */
2942 if (This->isRecordingState) {
2943 TRACE("Recording... not performing anything\n");
2944 return D3D_OK;
2947 ENTER_GL();
2949 /* Make appropriate texture active */
2950 VTRACE(("Activating appropriate texture state %ld\n", Stage));
2951 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2952 GLACTIVETEXTURE(Stage);
2953 } else if (Stage > 0) {
2954 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2957 switch (Type) {
2959 case D3DTSS_MINFILTER :
2960 case D3DTSS_MIPFILTER :
2962 DWORD ValueMIN = This->stateBlock->textureState[Stage][D3DTSS_MINFILTER];
2963 DWORD ValueMIP = This->stateBlock->textureState[Stage][D3DTSS_MIPFILTER];
2964 GLint realVal = GL_LINEAR;
2966 if (ValueMIN == D3DTEXF_NONE) {
2967 /* Doesn't really make sense - Windows just seems to disable
2968 mipmapping when this occurs */
2969 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
2970 realVal = GL_LINEAR;
2971 } else if (ValueMIN == D3DTEXF_POINT) {
2972 /* GL_NEAREST_* */
2973 if (ValueMIP == D3DTEXF_NONE) {
2974 realVal = GL_NEAREST;
2975 } else if (ValueMIP == D3DTEXF_POINT) {
2976 realVal = GL_NEAREST_MIPMAP_NEAREST;
2977 } else if (ValueMIP == D3DTEXF_LINEAR) {
2978 realVal = GL_NEAREST_MIPMAP_LINEAR;
2979 } else {
2980 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
2981 realVal = GL_NEAREST;
2983 } else if (ValueMIN == D3DTEXF_LINEAR) {
2984 /* GL_LINEAR_* */
2985 if (ValueMIP == D3DTEXF_NONE) {
2986 realVal = GL_LINEAR;
2987 } else if (ValueMIP == D3DTEXF_POINT) {
2988 realVal = GL_LINEAR_MIPMAP_NEAREST;
2989 } else if (ValueMIP == D3DTEXF_LINEAR) {
2990 realVal = GL_LINEAR_MIPMAP_LINEAR;
2991 } else {
2992 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
2993 realVal = GL_LINEAR;
2995 } else if (ValueMIN == D3DTEXF_ANISOTROPIC) {
2996 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2997 if (ValueMIP == D3DTEXF_NONE) {
2998 realVal = GL_LINEAR_MIPMAP_LINEAR;
2999 } else if (ValueMIP == D3DTEXF_POINT) {
3000 realVal = GL_LINEAR_MIPMAP_NEAREST;
3001 } else if (ValueMIP == D3DTEXF_LINEAR) {
3002 realVal = GL_LINEAR_MIPMAP_LINEAR;
3003 } else {
3004 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3005 realVal = GL_LINEAR;
3007 } else {
3008 WARN("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MINFILTER. But not supported by OpenGL driver\n");
3009 realVal = GL_LINEAR;
3011 } else {
3012 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3013 realVal = GL_LINEAR_MIPMAP_LINEAR;
3016 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3017 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3018 checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
3020 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3022 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMIN) {
3023 glTexParameteri(This->stateBlock->textureDimensions[Stage],
3024 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3025 This->stateBlock->textureState[Stage][D3DTSS_MAXANISOTROPY]);
3026 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3029 break;
3031 case D3DTSS_MAGFILTER :
3033 DWORD ValueMAG = This->stateBlock->textureState[Stage][D3DTSS_MAGFILTER];
3034 GLint realVal = GL_NEAREST;
3036 if (ValueMAG == D3DTEXF_POINT) {
3037 realVal = GL_NEAREST;
3038 } else if (ValueMAG == D3DTEXF_LINEAR) {
3039 realVal = GL_LINEAR;
3040 } else if (ValueMAG == D3DTEXF_ANISOTROPIC) {
3041 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3042 realVal = GL_LINEAR;
3043 } else {
3044 FIXME("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MAGFILTER. But not supported by current OpenGL driver\n");
3045 realVal = GL_NEAREST;
3047 } else {
3048 FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", ValueMAG);
3049 realVal = GL_NEAREST;
3051 TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", ValueMAG, realVal);
3052 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, realVal);
3053 checkGLcall("glTexParameter GL_TEXTURE_MAG_FILTER, ...");
3055 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3057 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMAG) {
3058 glTexParameteri(This->stateBlock->textureDimensions[Stage],
3059 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3060 This->stateBlock->textureState[Stage][D3DTSS_MAXANISOTROPY]);
3061 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3064 break;
3066 case D3DTSS_MAXMIPLEVEL :
3069 * Not really the same, but the more apprioprate than nothing
3071 glTexParameteri(This->stateBlock->textureDimensions[Stage],
3072 GL_TEXTURE_BASE_LEVEL,
3073 This->stateBlock->textureState[Stage][D3DTSS_MAXMIPLEVEL]);
3074 checkGLcall("glTexParameteri GL_TEXTURE_BASE_LEVEL ...");
3076 break;
3078 case D3DTSS_MAXANISOTROPY :
3080 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3081 glTexParameteri(This->stateBlock->textureDimensions[Stage],
3082 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3083 This->stateBlock->textureState[Stage][D3DTSS_MAXANISOTROPY]);
3084 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3087 break;
3089 case D3DTSS_MIPMAPLODBIAS :
3091 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3092 tmpvalue.d = Value;
3093 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3094 GL_TEXTURE_LOD_BIAS_EXT,
3095 tmpvalue.f);
3096 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
3099 break;
3101 case D3DTSS_ALPHAOP :
3102 case D3DTSS_COLOROP :
3105 if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
3106 /* TODO: Disable by making this and all later levels disabled */
3107 glDisable(GL_TEXTURE_1D);
3108 checkGLcall("Disable GL_TEXTURE_1D");
3109 glDisable(GL_TEXTURE_2D);
3110 checkGLcall("Disable GL_TEXTURE_2D");
3111 glDisable(GL_TEXTURE_3D);
3112 checkGLcall("Disable GL_TEXTURE_3D");
3113 break; /* Don't bother setting the texture operations */
3114 } else {
3115 /* Enable only the appropriate texture dimension */
3116 if (Type == D3DTSS_COLOROP) {
3117 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3118 glEnable(GL_TEXTURE_1D);
3119 checkGLcall("Enable GL_TEXTURE_1D");
3120 } else {
3121 glDisable(GL_TEXTURE_1D);
3122 checkGLcall("Disable GL_TEXTURE_1D");
3124 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3125 if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
3126 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
3127 checkGLcall("Enable GL_TEXTURE_2D");
3128 } else {
3129 glEnable(GL_TEXTURE_2D);
3130 checkGLcall("Enable GL_TEXTURE_2D");
3132 } else {
3133 glDisable(GL_TEXTURE_2D);
3134 checkGLcall("Disable GL_TEXTURE_2D");
3136 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3137 glEnable(GL_TEXTURE_3D);
3138 checkGLcall("Enable GL_TEXTURE_3D");
3139 } else {
3140 glDisable(GL_TEXTURE_3D);
3141 checkGLcall("Disable GL_TEXTURE_3D");
3143 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3144 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3145 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3146 } else {
3147 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3148 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3152 /* Drop through... (Except disable case) */
3153 case D3DTSS_COLORARG0 :
3154 case D3DTSS_COLORARG1 :
3155 case D3DTSS_COLORARG2 :
3156 case D3DTSS_ALPHAARG0 :
3157 case D3DTSS_ALPHAARG1 :
3158 case D3DTSS_ALPHAARG2 :
3160 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 ||
3161 Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3162 if (isAlphaArg) {
3163 set_tex_op(iface, TRUE, Stage, This->stateBlock->textureState[Stage][D3DTSS_ALPHAOP],
3164 This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG1],
3165 This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG2],
3166 This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG0]);
3167 } else {
3168 set_tex_op(iface, FALSE, Stage, This->stateBlock->textureState[Stage][D3DTSS_COLOROP],
3169 This->stateBlock->textureState[Stage][D3DTSS_COLORARG1],
3170 This->stateBlock->textureState[Stage][D3DTSS_COLORARG2],
3171 This->stateBlock->textureState[Stage][D3DTSS_COLORARG0]);
3174 break;
3177 case D3DTSS_ADDRESSU :
3178 case D3DTSS_ADDRESSV :
3179 case D3DTSS_ADDRESSW :
3181 GLint wrapParm = GL_REPEAT;
3183 switch (Value) {
3184 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3185 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3186 case D3DTADDRESS_BORDER:
3188 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3189 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3190 } else {
3191 /* FIXME: Not right, but better */
3192 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3193 wrapParm = GL_REPEAT;
3196 break;
3197 case D3DTADDRESS_MIRROR:
3199 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3200 wrapParm = GL_MIRRORED_REPEAT_ARB;
3201 } else {
3202 /* Unsupported in OpenGL pre-1.4 */
3203 FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3204 wrapParm = GL_REPEAT;
3207 break;
3208 case D3DTADDRESS_MIRRORONCE:
3210 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3211 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3212 } else {
3213 FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3214 wrapParm = GL_REPEAT;
3217 break;
3219 default:
3220 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3221 wrapParm = GL_REPEAT;
3224 switch (Type) {
3225 case D3DTSS_ADDRESSU:
3226 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
3227 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3228 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3229 break;
3230 case D3DTSS_ADDRESSV:
3231 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
3232 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3233 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3234 break;
3235 case D3DTSS_ADDRESSW:
3236 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
3237 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3238 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3239 break;
3240 default: /* nop */
3241 break; /** stupic compilator */
3244 break;
3246 case D3DTSS_BORDERCOLOR :
3248 float col[4];
3249 D3DCOLORTOGLFLOAT4(Value, col);
3250 TRACE("Setting border color for %x to %lx\n", This->stateBlock->textureDimensions[Stage], Value);
3251 glTexParameterfv(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3252 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3254 break;
3256 case D3DTSS_TEXCOORDINDEX :
3258 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3260 /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include
3261 one flag, you can still specify an index value, which the system uses to
3262 determine the texture wrapping mode.
3263 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3264 means use the vertex position (camera-space) as the input texture coordinates
3265 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
3266 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3267 to the TEXCOORDINDEX value */
3269 /**
3270 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3272 switch (Value & 0xFFFF0000) {
3273 case D3DTSS_TCI_PASSTHRU:
3274 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3275 glDisable(GL_TEXTURE_GEN_S);
3276 glDisable(GL_TEXTURE_GEN_T);
3277 glDisable(GL_TEXTURE_GEN_R);
3278 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3279 break;
3281 case D3DTSS_TCI_CAMERASPACEPOSITION:
3282 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3283 as the input texture coordinates for this stage's texture transformation. This
3284 equates roughly to EYE_LINEAR */
3286 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3287 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3288 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3289 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3290 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3292 glMatrixMode(GL_MODELVIEW);
3293 glPushMatrix();
3294 glLoadIdentity();
3295 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3296 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3297 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3298 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3299 glPopMatrix();
3301 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3302 glEnable(GL_TEXTURE_GEN_S);
3303 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3304 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3305 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3306 glEnable(GL_TEXTURE_GEN_T);
3307 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3308 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3309 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3310 glEnable(GL_TEXTURE_GEN_R);
3311 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3312 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3313 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3315 break;
3317 case D3DTSS_TCI_CAMERASPACENORMAL:
3319 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3320 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3321 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3322 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3323 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3324 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3326 glMatrixMode(GL_MODELVIEW);
3327 glPushMatrix();
3328 glLoadIdentity();
3329 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3330 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3331 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3332 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3333 glPopMatrix();
3335 glEnable(GL_TEXTURE_GEN_S);
3336 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3337 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3338 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3339 glEnable(GL_TEXTURE_GEN_T);
3340 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3341 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3342 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3343 glEnable(GL_TEXTURE_GEN_R);
3344 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3345 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3346 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3349 break;
3351 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3353 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3354 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3355 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3356 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3357 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3358 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3360 glMatrixMode(GL_MODELVIEW);
3361 glPushMatrix();
3362 glLoadIdentity();
3363 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3364 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3365 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3366 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3367 glPopMatrix();
3369 glEnable(GL_TEXTURE_GEN_S);
3370 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3371 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3372 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3373 glEnable(GL_TEXTURE_GEN_T);
3374 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3375 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3376 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3377 glEnable(GL_TEXTURE_GEN_R);
3378 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3379 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3380 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3383 break;
3385 /* Unhandled types: */
3386 default:
3387 /* Todo: */
3388 /* ? disable GL_TEXTURE_GEN_n ? */
3389 glDisable(GL_TEXTURE_GEN_S);
3390 glDisable(GL_TEXTURE_GEN_T);
3391 glDisable(GL_TEXTURE_GEN_R);
3392 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
3393 break;
3396 break;
3398 /* Unhandled */
3399 case D3DTSS_TEXTURETRANSFORMFLAGS :
3400 set_texture_matrix((float *)&This->stateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
3401 break;
3403 case D3DTSS_BUMPENVMAT00 :
3404 case D3DTSS_BUMPENVMAT01 :
3405 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
3406 break;
3407 case D3DTSS_BUMPENVMAT10 :
3408 case D3DTSS_BUMPENVMAT11 :
3409 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
3410 break;
3412 case D3DTSS_BUMPENVLSCALE :
3413 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3414 break;
3416 case D3DTSS_BUMPENVLOFFSET :
3417 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3418 break;
3420 case D3DTSS_RESULTARG :
3421 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3422 break;
3424 default:
3425 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3426 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3429 LEAVE_GL();
3431 return D3D_OK;
3434 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
3435 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3436 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
3437 *pValue = This->updateStateBlock->textureState[Stage][Type];
3438 return D3D_OK;
3441 /*****
3442 * Get / Set Texture
3443 *****/
3444 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
3446 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3447 IWineD3DBaseTexture *oldTexture;
3448 BOOL reapplyStates = TRUE;
3449 DWORD reapplyFlags = 0;
3450 INT oldTextureDimensions = -1;
3451 D3DRESOURCETYPE textureType;
3453 oldTexture = This->updateStateBlock->textures[Stage];
3454 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3456 /* Reject invalid texture units */
3457 if (Stage >= GL_LIMITS(textures)) {
3458 TRACE("Attempt to access invalid texture rejected\n");
3459 return D3DERR_INVALIDCALL;
3462 This->updateStateBlock->set.textures[Stage] = TRUE;
3463 This->updateStateBlock->changed.textures[Stage] = TRUE;
3464 This->updateStateBlock->textures[Stage] = pTexture;
3466 /* Handle recording of state blocks */
3467 if (This->isRecordingState) {
3468 TRACE("Recording... not performing anything\n");
3469 return D3D_OK;
3472 oldTextureDimensions = This->updateStateBlock->textureDimensions[Stage];
3474 ENTER_GL();
3476 /* Make appropriate texture active */
3477 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3478 GLACTIVETEXTURE(Stage);
3480 } else if (Stage>0) {
3481 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3484 /** NOTE: MSDN says that setTexture increases the reference count,
3485 * and the the application nust set the texture back to null (or have a leaky application),
3486 * This means we should pass the refcount upto the parent
3487 *******************************/
3488 if (NULL != oldTexture) {
3490 IUnknown *textureParent;
3491 IWineD3DBaseTexture_GetParent(oldTexture, (IUnknown **)&textureParent);
3492 IUnknown_Release(textureParent);
3493 IUnknown_Release(textureParent); /** NOTE: Twice because GetParent adds a ref **/
3494 oldTexture = NULL;
3498 if (NULL != pTexture) {
3499 IUnknown *textureParent;
3500 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[Stage], (IUnknown **)&textureParent);
3501 /** NOTE: GetParent will increase the ref count for me, I won't clean up untill the texture is set to NULL **/
3503 /* Now setup the texture appropraitly */
3504 textureType = IWineD3DBaseTexture_GetType(pTexture);
3506 if (textureType == D3DRTYPE_TEXTURE) {
3508 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
3509 TRACE("Skipping setting texture as old == new\n");
3510 reapplyStates = FALSE;
3512 } else {
3514 /* Standard 2D texture */
3515 TRACE("Standard 2d texture\n");
3516 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3518 /* Load up the texture now */
3519 IWineD3DTexture_PreLoad((IWineD3DTexture *) pTexture);
3522 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3524 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
3525 TRACE("Skipping setting texture as old == new\n");
3526 reapplyStates = FALSE;
3528 } else {
3530 /* Standard 3D (volume) texture */
3531 TRACE("Standard 3d texture\n");
3532 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3534 /* Load up the texture now */
3535 IWineD3DVolumeTexture_PreLoad((IWineD3DVolumeTexture *) pTexture);
3538 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
3540 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
3541 TRACE("Skipping setting texture as old == new\n");
3542 reapplyStates = FALSE;
3544 } else {
3546 /* Standard Cube texture */
3547 TRACE("Standard Cube texture\n");
3548 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
3550 /* Load up the texture now */
3551 IWineD3DCubeTexture_PreLoad((IWineD3DCubeTexture *) pTexture);
3554 } else {
3555 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dresourcetype(textureType));
3558 } else {
3560 TRACE("Setting to no texture (ie default texture)\n");
3561 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3562 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3563 checkGLcall("glBindTexture");
3564 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3567 /* Disable the old texture binding and enable the new one (unless operations are disabled) */
3568 if (oldTextureDimensions != This->updateStateBlock->textureDimensions[Stage]) {
3570 glDisable(oldTextureDimensions);
3571 checkGLcall("Disable oldTextureDimensions");
3573 if (This->stateBlock->textureState[Stage][D3DTSS_COLOROP] != D3DTOP_DISABLE) {
3574 glEnable(This->updateStateBlock->textureDimensions[Stage]);
3575 checkGLcall("glEnable new texture dimensions");
3578 /* If Alpha arg1 is texture then handle the special case when there changes between a
3579 texture and no texture - See comments in set_tex_op */
3580 if ((This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
3581 (((oldTexture == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTexture != NULL))))
3583 reapplyFlags |= REAPPLY_ALPHAOP;
3588 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3589 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3590 if (reapplyStates) {
3591 IWineD3DDeviceImpl_SetupTextureStates(iface, Stage, reapplyFlags);
3594 LEAVE_GL();
3595 TRACE("Texture now fully setup\n");
3597 return D3D_OK;
3600 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
3601 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3602 TRACE("(%p) : returning %p for stage %ld\n", This, This->updateStateBlock->textures[Stage], Stage);
3603 *ppTexture = (IWineD3DBaseTexture *) This->updateStateBlock->textures[Stage];
3604 if (*ppTexture)
3605 IWineD3DBaseTexture_AddRef(*ppTexture);
3606 return D3D_OK;
3609 /*****
3610 * Get Back Buffer
3611 *****/
3612 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type,
3613 IWineD3DSurface** ppBackBuffer) {
3614 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3616 *ppBackBuffer = (IWineD3DSurface *) This->backBuffer;
3617 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
3619 if (BackBuffer > This->presentParms.BackBufferCount - 1) {
3620 FIXME("Only one backBuffer currently supported\n");
3621 return D3DERR_INVALIDCALL;
3624 /* Note inc ref on returned surface */
3625 IWineD3DSurface_AddRef(*ppBackBuffer);
3627 return D3D_OK;
3630 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, D3DCAPS9* pCaps) {
3631 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3632 WARN("(%p) : stub, calling idirect3d for now\n", This);
3633 IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
3634 return D3D_OK;
3637 /** TODO: move to swapchains **/
3638 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
3639 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3640 HDC hdc;
3641 int bpp = 0;
3643 pMode->Width = GetSystemMetrics(SM_CXSCREEN);
3644 pMode->Height = GetSystemMetrics(SM_CYSCREEN);
3645 pMode->RefreshRate = 85; /*FIXME: How to identify? */
3647 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
3648 bpp = GetDeviceCaps(hdc, BITSPIXEL);
3649 DeleteDC(hdc);
3651 switch (bpp) {
3652 case 8: pMode->Format = WINED3DFMT_R8G8B8; break;
3653 case 16: pMode->Format = WINED3DFMT_R5G6B5; break;
3654 case 24: /*pMode->Format = WINED3DFMT_R8G8B8; break; */
3655 case 32: pMode->Format = WINED3DFMT_A8R8G8B8; break;
3656 default:
3657 FIXME("Unrecognized display mode format\n");
3658 pMode->Format = WINED3DFMT_UNKNOWN;
3661 FIXME("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate,
3662 pMode->Format, debug_d3dformat(pMode->Format));
3663 return D3D_OK;
3665 /*****
3666 * Stateblock related functions
3667 *****/
3669 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
3670 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3671 IWineD3DStateBlockImpl *object;
3672 TRACE("(%p)", This);
3673 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
3674 if(NULL == object ){
3675 FIXME("(%p)Error allocating memory for stateblock\n", This);
3676 return E_OUTOFMEMORY;
3678 TRACE("(%p) creted object %p\n", This, object);
3679 object->wineD3DDevice= This;
3680 /** FIXME: object->parent = parent; **/
3681 object->parent = NULL;
3682 object->blockType = D3DSBT_ALL;
3683 object->ref = 1;
3684 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
3686 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
3687 This->updateStateBlock = object;
3688 This->isRecordingState = TRUE;
3690 TRACE("(%p) recording stateblock %p\n",This , object);
3691 return D3D_OK;
3694 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
3695 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3697 if (!This->isRecordingState) {
3698 FIXME("(%p) not recording! returning error\n", This);
3699 *ppStateBlock = NULL;
3700 return D3DERR_INVALIDCALL;
3703 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
3704 This->isRecordingState = FALSE;
3705 This->updateStateBlock = This->stateBlock;
3706 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
3707 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
3708 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
3709 return D3D_OK;
3712 /*****
3713 * Scene related functions
3714 *****/
3715 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
3716 /* At the moment we have no need for any functionality at the beginning
3717 of a scene */
3718 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3719 TRACE("(%p) : stub\n", This);
3720 return D3D_OK;
3723 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
3724 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3725 TRACE("(%p)\n", This);
3726 ENTER_GL();
3727 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
3728 glFlush();
3729 checkGLcall("glFlush");
3731 TRACE("End Scene\n");
3732 if(This->renderTarget != NULL){
3734 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
3735 IUnknown *targetContainer = NULL;
3736 if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)) {
3737 TRACE("RenderTarget is either standalone of a texture.\n");
3738 /** always dirtify for now. we must find a better way to see that surface have been modified
3739 (Modifications should will only occur via draw-primitive, but we do need better locking
3740 switching to render-to-texture should remove the overhead though.
3742 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
3743 IWineD3DBaseTexture_SetDirty((IWineD3DBaseTexture *)targetContainer, TRUE);
3744 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *)targetContainer);
3745 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
3746 IUnknown_Release(targetContainer);
3751 LEAVE_GL();
3752 return D3D_OK;
3755 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
3756 CONST RECT* pSourceRect, CONST RECT* pDestRect,
3757 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
3758 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3759 TRACE("(%p) Presenting the frame\n", This);
3761 ENTER_GL();
3763 if (pSourceRect || pDestRect) FIXME("Unhandled present options %p/%p\n", pSourceRect, pDestRect);
3765 glXSwapBuffers(This->display, This->drawable);
3766 /* Don't call checkGLcall, as glGetError is not applicable here */
3768 TRACE("glXSwapBuffers called, Starting new frame\n");
3770 /* FPS support */
3771 if (TRACE_ON(d3d_fps))
3773 static long prev_time, frames;
3775 DWORD time = GetTickCount();
3776 frames++;
3777 /* every 1.5 seconds */
3778 if (time - prev_time > 1500) {
3779 TRACE_(d3d_fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time));
3780 prev_time = time;
3781 frames = 0;
3785 #if defined(FRAME_DEBUGGING)
3787 if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
3788 if (!isOn) {
3789 isOn = TRUE;
3790 FIXME("Enabling D3D Trace\n");
3791 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1);
3792 #if defined(SHOW_FRAME_MAKEUP)
3793 FIXME("Singe Frame snapshots Starting\n");
3794 isDumpingFrames = TRUE;
3795 glClear(GL_COLOR_BUFFER_BIT);
3796 #endif
3798 #if defined(SINGLE_FRAME_DEBUGGING)
3799 } else {
3800 #if defined(SHOW_FRAME_MAKEUP)
3801 FIXME("Singe Frame snapshots Finishing\n");
3802 isDumpingFrames = FALSE;
3803 #endif
3804 FIXME("Singe Frame trace complete\n");
3805 DeleteFileA("C:\\D3DTRACE");
3806 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
3807 #endif
3809 } else {
3810 if (isOn) {
3811 isOn = FALSE;
3812 #if defined(SHOW_FRAME_MAKEUP)
3813 FIXME("Singe Frame snapshots Finishing\n");
3814 isDumpingFrames = FALSE;
3815 #endif
3816 FIXME("Disabling D3D Trace\n");
3817 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
3821 #endif
3823 LEAVE_GL();
3824 /* Although this is not strictly required, a simple demo showed this does occur
3825 on (at least non-debug) d3d */
3826 if (This->presentParms.SwapEffect == D3DSWAPEFFECT_DISCARD) {
3827 IWineD3DDevice_Clear(iface, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
3830 return D3D_OK;
3833 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
3834 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
3835 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3837 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
3838 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
3839 when the depth-buffer format does not contain stencil buffer information, this method fails. */
3840 GLbitfield glMask = 0;
3841 GLboolean old_ztest;
3842 GLfloat old_z_clear_value;
3843 GLint old_stencil_clear_value;
3844 GLfloat old_color_clear_value[4];
3845 unsigned int i;
3846 CONST D3DRECT* curRect;
3848 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
3849 Count, pRects, Flags, Z, Stencil);
3851 ENTER_GL();
3853 glEnable(GL_SCISSOR_TEST);
3854 checkGLcall("glEnable GL_SCISSOR_TEST");
3856 if (Count > 0 && pRects) {
3857 curRect = pRects;
3858 } else {
3859 curRect = NULL;
3862 /* Only set the values up once, as they are not changing */
3863 if (Flags & D3DCLEAR_STENCIL) {
3864 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
3865 glClearStencil(Stencil);
3866 checkGLcall("glClearStencil");
3867 glMask = glMask | GL_STENCIL_BUFFER_BIT;
3868 glStencilMask(0xFFFFFFFF);
3871 if (Flags & D3DCLEAR_ZBUFFER) {
3872 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
3873 glDepthMask(GL_TRUE);
3874 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
3875 glClearDepth(Z);
3876 checkGLcall("glClearDepth");
3877 glMask = glMask | GL_DEPTH_BUFFER_BIT;
3880 if (Flags & D3DCLEAR_TARGET) {
3881 TRACE("Clearing screen with glClear to color %lx\n", Color);
3882 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
3883 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
3884 ((Color >> 8) & 0xFF) / 255.0f,
3885 ((Color >> 0) & 0xFF) / 255.0f,
3886 ((Color >> 24) & 0xFF) / 255.0f);
3887 checkGLcall("glClearColor");
3889 /* Clear ALL colors! */
3890 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3891 glMask = glMask | GL_COLOR_BUFFER_BIT;
3894 /* Now process each rect in turn */
3895 for (i = 0; i < Count || i == 0; i++) {
3897 if (curRect) {
3898 /* Note gl uses lower left, width/height */
3899 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
3900 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
3901 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
3902 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
3903 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
3904 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
3905 checkGLcall("glScissor");
3906 } else {
3907 glScissor(This->stateBlock->viewport.X,
3908 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
3909 This->stateBlock->viewport.Width,
3910 This->stateBlock->viewport.Height);
3911 checkGLcall("glScissor");
3914 /* Clear the selected rectangle (or full screen) */
3915 glClear(glMask);
3916 checkGLcall("glClear");
3918 /* Step to the next rectangle */
3919 if (curRect) curRect = curRect + sizeof(D3DRECT);
3922 /* Restore the old values (why..?) */
3923 if (Flags & D3DCLEAR_STENCIL) {
3924 glClearStencil(old_stencil_clear_value);
3925 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
3927 if (Flags & D3DCLEAR_ZBUFFER) {
3928 glDepthMask(old_ztest);
3929 glClearDepth(old_z_clear_value);
3931 if (Flags & D3DCLEAR_TARGET) {
3932 glClearColor(old_color_clear_value[0],
3933 old_color_clear_value[1],
3934 old_color_clear_value[2],
3935 old_color_clear_value[3]);
3936 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3937 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3938 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3939 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3942 glDisable(GL_SCISSOR_TEST);
3943 checkGLcall("glDisable");
3944 LEAVE_GL();
3946 return D3D_OK;
3949 /*****
3950 * Drawing functions
3951 *****/
3952 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
3953 UINT PrimitiveCount) {
3955 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3956 This->stateBlock->streamIsUP = FALSE;
3958 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
3959 debug_d3dprimitivetype(PrimitiveType),
3960 StartVertex, PrimitiveCount);
3961 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
3963 return D3D_OK;
3966 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
3967 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
3968 D3DPRIMITIVETYPE PrimitiveType,
3969 INT baseVIndex, UINT minIndex,
3970 UINT NumVertices,UINT startIndex,UINT primCount) {
3972 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3973 UINT idxStride = 2;
3974 IWineD3DIndexBuffer *pIB;
3975 D3DINDEXBUFFER_DESC IdxBufDsc;
3977 pIB = This->stateBlock->pIndexData;
3978 This->stateBlock->streamIsUP = FALSE;
3980 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d \n", This,
3981 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3982 minIndex, NumVertices, startIndex, baseVIndex, primCount);
3984 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
3985 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
3986 idxStride = 2;
3987 } else {
3988 idxStride = 4;
3991 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex,
3992 startIndex, idxStride,
3993 ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory,
3994 minIndex);
3996 return D3D_OK;
3999 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4000 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4001 UINT VertexStreamZeroStride) {
4002 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4004 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4005 debug_d3dprimitivetype(PrimitiveType),
4006 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4008 if (This->stateBlock->stream_source[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->stream_source[0]);
4010 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4011 This->stateBlock->stream_source[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4012 This->stateBlock->stream_stride[0] = VertexStreamZeroStride;
4013 This->stateBlock->streamIsUP = TRUE;
4014 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
4015 This->stateBlock->stream_stride[0] = 0;
4016 This->stateBlock->stream_source[0] = NULL;
4018 /*stream zero settings set to null at end, as per the msdn */
4019 return D3D_OK;
4022 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4023 UINT MinVertexIndex,
4024 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
4025 WINED3DFORMAT IndexDataFormat, CONST void* pVertexStreamZeroData,
4026 UINT VertexStreamZeroStride) {
4027 int idxStride;
4028 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4030 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4031 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4032 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData,
4033 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4035 if (This->stateBlock->stream_source[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->stream_source[0]);
4037 if (IndexDataFormat == WINED3DFMT_INDEX16) {
4038 idxStride = 2;
4039 } else {
4040 idxStride = 4;
4043 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4044 This->stateBlock->stream_source[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4045 This->stateBlock->streamIsUP = TRUE;
4046 This->stateBlock->stream_stride[0] = VertexStreamZeroStride;
4048 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, idxStride, pIndexData, MinVertexIndex);
4050 /* stream zero settings set to null at end as per the msdn */
4051 This->stateBlock->stream_source[0] = NULL;
4052 This->stateBlock->stream_stride[0] = 0;
4053 IWineD3DDevice_SetIndices(iface, NULL, 0);
4055 return D3D_OK;
4058 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
4059 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4061 TRACE("(%p) : stub\n", This);
4062 return D3D_OK;
4065 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
4066 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
4067 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
4068 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4070 TRACE("(%p) : stub\n", This);
4071 return D3D_OK;
4073 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface){
4074 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4076 TRACE("(%p) : stub\n", This);
4077 return D3D_OK;
4080 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface){
4081 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4083 TRACE("(%p) : stub\n", This);
4084 return D3D_OK;
4087 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4088 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4089 /* return a sensible default */
4090 *pNumPasses = 1;
4091 FIXME("(%p) : stub\n", This);
4092 return D3D_OK;
4095 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4096 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4097 FIXME("(%p) : stub\n", This);
4098 return D3D_OK;
4101 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4102 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4103 FIXME("(%p) : stub\n", This);
4104 return D3D_OK;
4107 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4108 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4109 FIXME("(%p) : stub\n", This);
4110 return D3D_OK;
4113 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4114 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4115 FIXME("(%p) : stub\n", This);
4116 return D3D_OK;
4119 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4120 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4121 FIXME("(%p) : stub\n", This);
4122 return D3D_OK;
4126 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4127 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4128 FIXME("(%p) : stub\n", This);
4129 return FALSE;
4133 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
4134 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4136 pRasterStatus->InVBlank = TRUE;
4137 pRasterStatus->ScanLine = 0;
4138 FIXME("(%p) : stub\n", This);
4139 return D3D_OK;
4143 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4144 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4145 static BOOL showfixmes = TRUE;
4146 if(nSegments != 0.0f){
4147 if( showfixmes){
4148 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4149 showfixmes = FALSE;
4152 return D3D_OK;
4155 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4156 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4157 static BOOL showfixmes = TRUE;
4158 if( showfixmes){
4159 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4160 showfixmes = FALSE;
4162 return 0.0f;
4166 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4167 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4168 FIXME("(%p) : stub\n", This);
4169 return D3D_OK;
4173 /* Implementation details at http://developer.nvidia.com/attach/6494
4175 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
4176 hmm.. no longer supported use
4177 OpenGL evaluators or tessellate surfaces within your application.
4180 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
4181 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo){
4182 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4183 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p) \n", This, Handle, pNumSegs, pRectPatchInfo);
4184 FIXME("(%p) : Stub\n", This);
4185 return D3D_OK;
4189 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
4190 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo){
4191 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4192 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p) \n", This, Handle, pNumSegs, pTriPatchInfo);
4193 FIXME("(%p) : Stub\n", This);
4194 return D3D_OK;
4197 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle){
4198 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4199 TRACE("(%p) Handle(%d)\n", This, Handle);
4200 FIXME("(%p) : Stub\n", This);
4201 return D3D_OK;
4204 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color){
4205 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4207 FIXME("(%p) : stub\n", This);
4208 return D3D_OK;
4211 /* rendertarget and deptth stencil functions */
4212 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget){
4213 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4215 /* FIXME: Implelent RenderTargetIndex >0 */
4216 if(RenderTargetIndex > 0)
4217 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
4219 *ppRenderTarget = (IWineD3DSurface *)This->renderTarget;
4220 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
4221 /* Note inc ref on returned surface */
4222 if(*ppRenderTarget != NULL)
4223 IWineD3DSurface_AddRef(*ppRenderTarget);
4224 return D3D_OK;
4227 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface){
4228 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4229 *ppZStencilSurface = (IWineD3DSurface *)This->depthStencilBuffer;
4230 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
4232 if(*ppZStencilSurface != NULL){
4233 /* Note inc ref on returned surface */
4234 IWineD3DSurface_AddRef(*ppZStencilSurface);
4236 return D3D_OK;
4239 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget){
4240 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4242 FIXME("(%p) : stub\n", This);
4243 return D3D_OK;
4246 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil){
4247 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4249 FIXME("(%p) : stub\n", This);
4250 return D3D_OK;
4253 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
4254 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
4255 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4256 /* TODO: the use of Impl is deprecated. */
4257 /* some basic validation checks */
4258 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
4260 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
4262 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
4263 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
4264 return D3DERR_INVALIDCALL;
4266 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
4267 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
4268 return D3DERR_INVALIDCALL;
4270 /* TODO: make the cursor 'real' */
4272 This->xHotSpot = XHotSpot;
4273 This->yHotSpot = YHotSpot;
4275 return D3D_OK;
4278 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
4279 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4280 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
4282 This->xScreenSpace = XScreenSpace;
4283 This->yScreenSpace = YScreenSpace;
4285 return;
4289 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
4290 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4291 TRACE("(%p) : visible(%d)\n", This, bShow);
4293 This->bCursorVisible = bShow;
4295 return D3D_OK;
4298 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
4299 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4300 FIXME("(%p) : stub\n", This); /* No way of notifying yet! */
4301 return D3D_OK;
4305 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
4306 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4307 /** FIXME: Resource tracking needs to be done,
4308 * The closes we can do to this is set the priorities of all managed textures low
4309 * and then reset them.
4310 ***********************************************************/
4311 FIXME("(%p) : stub\n", This);
4312 return D3D_OK;
4315 HRESULT WINAPI IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
4316 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4317 /** FIXME: Resource trascking needs to be done.
4318 * in effect this pulls all non only default
4319 * textures out of video memory and deletes all glTextures (glDeleteTextures)
4320 * and should clear down the context and set it up according to pPresentationParameters
4321 ***********************************************************/
4322 FIXME("(%p) : stub\n", This);
4323 return D3D_OK;
4326 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs){
4327 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4328 /** FIXME: always true at the moment **/
4329 if(bEnableDialogs == FALSE){
4330 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
4332 return D3D_OK;
4336 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
4337 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4339 FIXME("(%p) : stub\n", This);
4340 /* Setup some reasonable defaults */
4341 pParameters->AdapterOrdinal = 0; /* always for now */
4342 pParameters->DeviceType = D3DDEVTYPE_HAL; /* always for now */
4343 pParameters->hFocusWindow = 0;
4344 pParameters->BehaviorFlags =0;
4345 return D3D_OK;
4348 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
4349 HDC hDC;
4350 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4352 FIXME("(%p) : pRamp@%p\n", This, pRamp);
4353 hDC = GetDC(This->win_handle);
4354 SetDeviceGammaRamp(hDC, (LPVOID) pRamp);
4355 ReleaseDC(This->win_handle, hDC);
4356 return;
4359 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
4360 HDC hDC;
4361 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4363 FIXME("(%p) : pRamp@%p\n", This, pRamp);
4364 hDC = GetDC(This->win_handle);
4365 GetDeviceGammaRamp(hDC, pRamp);
4366 ReleaseDC(This->win_handle, hDC);
4367 return;
4370 /**********************************************************
4371 * IWineD3DDevice VTbl follows
4372 **********************************************************/
4374 IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
4376 /*** IUnknown methods ***/
4377 IWineD3DDeviceImpl_QueryInterface,
4378 IWineD3DDeviceImpl_AddRef,
4379 IWineD3DDeviceImpl_Release,
4380 /*** IWineD3DDevice methods ***/
4381 IWineD3DDeviceImpl_GetParent,
4382 /*** Creation methods**/
4383 IWineD3DDeviceImpl_CreateVertexBuffer,
4384 IWineD3DDeviceImpl_CreateIndexBuffer,
4385 IWineD3DDeviceImpl_CreateStateBlock,
4386 IWineD3DDeviceImpl_CreateSurface,
4387 IWineD3DDeviceImpl_CreateTexture,
4388 IWineD3DDeviceImpl_CreateVolumeTexture,
4389 IWineD3DDeviceImpl_CreateVolume,
4390 IWineD3DDeviceImpl_CreateCubeTexture,
4391 IWineD3DDeviceImpl_CreateQuery,
4392 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
4393 IWineD3DDeviceImpl_CreateVertexDeclaration,
4394 IWineD3DDeviceImpl_CreateVertexShader,
4395 IWineD3DDeviceImpl_CreatePixelShader,
4397 /*** Odd functions **/
4398 IWineD3DDeviceImpl_EvictManagedResources,
4399 IWineD3DDeviceImpl_GetAvailableTextureMem,
4400 IWineD3DDeviceImpl_GetBackBuffer,
4401 IWineD3DDeviceImpl_GetCreationParameters,
4402 IWineD3DDeviceImpl_GetDeviceCaps,
4403 IWineD3DDeviceImpl_GetDirect3D,
4404 IWineD3DDeviceImpl_GetDisplayMode,
4405 IWineD3DDeviceImpl_GetNumberOfSwapChains,
4406 IWineD3DDeviceImpl_GetRasterStatus,
4407 IWineD3DDeviceImpl_GetSwapChain,
4408 IWineD3DDeviceImpl_Reset,
4409 IWineD3DDeviceImpl_SetDialogBoxMode,
4410 IWineD3DDeviceImpl_SetCursorProperties,
4411 IWineD3DDeviceImpl_SetCursorPosition,
4412 IWineD3DDeviceImpl_ShowCursor,
4413 IWineD3DDeviceImpl_TestCooperativeLevel,
4414 /*** Getters and setters **/
4415 IWineD3DDeviceImpl_SetClipPlane,
4416 IWineD3DDeviceImpl_GetClipPlane,
4417 IWineD3DDeviceImpl_SetClipStatus,
4418 IWineD3DDeviceImpl_GetClipStatus,
4419 IWineD3DDeviceImpl_SetCurrentTexturePalette,
4420 IWineD3DDeviceImpl_GetCurrentTexturePalette,
4421 IWineD3DDeviceImpl_SetDepthStencilSurface,
4422 IWineD3DDeviceImpl_GetDepthStencilSurface,
4423 IWineD3DDeviceImpl_SetFVF,
4424 IWineD3DDeviceImpl_GetFVF,
4425 IWineD3DDeviceImpl_SetGammaRamp,
4426 IWineD3DDeviceImpl_GetGammaRamp,
4427 IWineD3DDeviceImpl_SetIndices,
4428 IWineD3DDeviceImpl_GetIndices,
4429 IWineD3DDeviceImpl_SetLight,
4430 IWineD3DDeviceImpl_GetLight,
4431 IWineD3DDeviceImpl_SetLightEnable,
4432 IWineD3DDeviceImpl_GetLightEnable,
4433 IWineD3DDeviceImpl_SetMaterial,
4434 IWineD3DDeviceImpl_GetMaterial,
4435 IWineD3DDeviceImpl_SetNPatchMode,
4436 IWineD3DDeviceImpl_GetNPatchMode,
4437 IWineD3DDeviceImpl_SetPaletteEntries,
4438 IWineD3DDeviceImpl_GetPaletteEntries,
4439 IWineD3DDeviceImpl_SetPixelShader,
4440 IWineD3DDeviceImpl_GetPixelShader,
4441 IWineD3DDeviceImpl_SetPixelShaderConstantB,
4442 IWineD3DDeviceImpl_GetPixelShaderConstantB,
4443 IWineD3DDeviceImpl_SetPixelShaderConstantI,
4444 IWineD3DDeviceImpl_GetPixelShaderConstantI,
4445 IWineD3DDeviceImpl_SetPixelShaderConstantF,
4446 IWineD3DDeviceImpl_GetPixelShaderConstantF,
4447 IWineD3DDeviceImpl_SetRenderState,
4448 IWineD3DDeviceImpl_GetRenderState,
4449 IWineD3DDeviceImpl_SetRenderTarget,
4450 IWineD3DDeviceImpl_GetRenderTarget,
4451 IWineD3DDeviceImpl_SetSamplerState,
4452 IWineD3DDeviceImpl_GetSamplerState,
4453 IWineD3DDeviceImpl_SetScissorRect,
4454 IWineD3DDeviceImpl_GetScissorRect,
4455 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
4456 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
4457 IWineD3DDeviceImpl_SetStreamSource,
4458 IWineD3DDeviceImpl_GetStreamSource,
4459 IWineD3DDeviceImpl_SetStreamSourceFreq,
4460 IWineD3DDeviceImpl_GetStreamSourceFreq,
4461 IWineD3DDeviceImpl_SetTexture,
4462 IWineD3DDeviceImpl_GetTexture,
4463 IWineD3DDeviceImpl_SetTextureStageState,
4464 IWineD3DDeviceImpl_GetTextureStageState,
4465 IWineD3DDeviceImpl_SetTransform,
4466 IWineD3DDeviceImpl_GetTransform,
4467 IWineD3DDeviceImpl_SetVertexDeclaration,
4468 IWineD3DDeviceImpl_GetVertexDeclaration,
4469 IWineD3DDeviceImpl_SetVertexShader,
4470 IWineD3DDeviceImpl_GetVertexShader,
4471 IWineD3DDeviceImpl_SetVertexShaderConstantB,
4472 IWineD3DDeviceImpl_GetVertexShaderConstantB,
4473 IWineD3DDeviceImpl_SetVertexShaderConstantI,
4474 IWineD3DDeviceImpl_GetVertexShaderConstantI,
4475 IWineD3DDeviceImpl_SetVertexShaderConstantF,
4476 IWineD3DDeviceImpl_GetVertexShaderConstantF,
4477 IWineD3DDeviceImpl_SetViewport,
4478 IWineD3DDeviceImpl_GetViewport,
4479 IWineD3DDeviceImpl_MultiplyTransform,
4480 IWineD3DDeviceImpl_ValidateDevice,
4481 IWineD3DDeviceImpl_ProcessVertices,
4482 /*** State block ***/
4483 IWineD3DDeviceImpl_BeginStateBlock,
4484 IWineD3DDeviceImpl_EndStateBlock,
4485 /*** Scene management ***/
4486 IWineD3DDeviceImpl_BeginScene,
4487 IWineD3DDeviceImpl_EndScene,
4488 IWineD3DDeviceImpl_Present,
4489 IWineD3DDeviceImpl_Clear,
4490 /*** Drawing ***/
4491 IWineD3DDeviceImpl_DrawPrimitive,
4492 IWineD3DDeviceImpl_DrawIndexedPrimitive,
4493 IWineD3DDeviceImpl_DrawPrimitiveUP,
4494 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
4495 IWineD3DDeviceImpl_DrawRectPatch,
4496 IWineD3DDeviceImpl_DrawTriPatch,
4497 IWineD3DDeviceImpl_DeletePatch,
4498 IWineD3DDeviceImpl_ColorFill,
4499 IWineD3DDeviceImpl_UpdateTexture,
4500 IWineD3DDeviceImpl_UpdateSurface,
4501 IWineD3DDeviceImpl_StretchRect,
4502 IWineD3DDeviceImpl_GetRenderTargetData,
4503 IWineD3DDeviceImpl_GetFrontBufferData,
4504 /*** Internal use IWineD3DDevice methods ***/
4505 IWineD3DDeviceImpl_SetupTextureStates