Add support for samplers.
[wine/multimedia.git] / dlls / wined3d / device.c
blobd30a7fae74ba67f2c6ec46afc47043125e4a4b6a
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 /* x11drv GDI escapes */
34 #define X11DRV_ESCAPE 6789
35 enum x11drv_escape_codes
37 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
38 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
39 X11DRV_GET_FONT, /* get current X font for a DC */
42 /* retrieve the X display to use on a given DC */
43 inline static Display *get_display( HDC hdc )
45 Display *display;
46 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
48 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
49 sizeof(display), (LPSTR)&display )) display = NULL;
50 return display;
53 /* helper macros */
54 #define D3DMEMCHECK(object, ppResult) if(NULL == object){ *ppResult = NULL; WARN("Out of memory\n"); return D3DERR_OUTOFVIDEOMEMORY;}
56 #define D3DCREATEOBJECTINSTANCE(object, type){ \
57 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
58 D3DMEMCHECK(object, pp##type); \
59 object->lpVtbl = &IWineD3D##type##_Vtbl; \
60 object->wineD3DDevice = This; \
61 object->parent = parent; \
62 object->ref = 1; \
63 *pp##type = (IWineD3D##type *) object; \
66 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype){ \
67 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
68 D3DMEMCHECK(object, pp##type); \
69 object->lpVtbl = &IWineD3D##type##_Vtbl; \
70 object->resource.wineD3DDevice = This; \
71 object->resource.parent = parent; \
72 object->resource.resourceType = d3dtype; \
73 object->resource.ref = 1; \
74 object->resource.pool = Pool; \
75 object->resource.format = Format; \
76 object->resource.usage = Usage; \
77 object->resource.size = 0; \
78 object->resource.allocatedMemory = 0; \
79 *pp##type = (IWineD3D##type *) object; \
82 #define D3DINITILIZEBASETEXTURE(_basetexture) { \
83 _basetexture.levels = Levels; \
84 _basetexture.filterType = (Usage & D3DUSAGE_AUTOGENMIPMAP) ? D3DTEXF_LINEAR : D3DTEXF_NONE; \
85 _basetexture.LOD = 0; \
86 _basetexture.dirty = TRUE; \
89 /**********************************************************
90 * Global variable / Constants follow
91 **********************************************************/
92 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
94 /**********************************************************
95 * Utility functions follow
96 **********************************************************/
97 /* Convert the D3DLIGHT properties into equivalent gl lights */
98 void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
100 float quad_att;
101 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
102 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
104 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
105 glMatrixMode(GL_MODELVIEW);
106 glPushMatrix();
107 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
109 /* Diffuse: */
110 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
111 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
112 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
113 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
114 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
115 checkGLcall("glLightfv");
117 /* Specular */
118 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
119 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
120 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
121 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
122 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
123 checkGLcall("glLightfv");
125 /* Ambient */
126 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
127 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
128 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
129 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
130 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
131 checkGLcall("glLightfv");
133 /* Attenuation - Are these right? guessing... */
134 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
135 checkGLcall("glLightf");
136 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
137 checkGLcall("glLightf");
139 quad_att = 1.4/(lightInfo->OriginalParms.Range*lightInfo->OriginalParms.Range);
140 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
141 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
142 checkGLcall("glLightf");
144 switch (lightInfo->OriginalParms.Type) {
145 case D3DLIGHT_POINT:
146 /* Position */
147 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
148 checkGLcall("glLightfv");
149 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
150 checkGLcall("glLightf");
151 /* FIXME: Range */
152 break;
154 case D3DLIGHT_SPOT:
155 /* Position */
156 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
157 checkGLcall("glLightfv");
158 /* Direction */
159 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
160 checkGLcall("glLightfv");
161 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
162 checkGLcall("glLightf");
163 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
164 checkGLcall("glLightf");
165 /* FIXME: Range */
166 break;
168 case D3DLIGHT_DIRECTIONAL:
169 /* Direction */
170 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
171 checkGLcall("glLightfv");
172 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
173 checkGLcall("glLightf");
174 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
175 checkGLcall("glLightf");
176 break;
178 default:
179 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
182 /* Restore the modelview matrix */
183 glPopMatrix();
186 /* Apply the current values to the specified texture stage */
187 void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Stage, DWORD Flags) {
188 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
189 int i = 0;
190 float col[4];
191 BOOL changeTexture = TRUE;
193 TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
194 for (i = 1; i < HIGHEST_TEXTURE_STATE; i++) {
196 BOOL skip = FALSE;
198 switch (i) {
199 /* Performance: For texture states where multiples effect the outcome, only bother
200 applying the last one as it will pick up all the other values */
201 case WINED3DTSS_COLORARG0: /* Will be picked up when setting color op */
202 case WINED3DTSS_COLORARG1: /* Will be picked up when setting color op */
203 case WINED3DTSS_COLORARG2: /* Will be picked up when setting color op */
204 case WINED3DTSS_ALPHAARG0: /* Will be picked up when setting alpha op */
205 case WINED3DTSS_ALPHAARG1: /* Will be picked up when setting alpha op */
206 case WINED3DTSS_ALPHAARG2: /* Will be picked up when setting alpha op */
207 skip = TRUE;
208 break;
210 /* Performance: If the texture states only impact settings for the texture unit
211 (compared to the texture object) then there is no need to reapply them. The
212 only time they need applying is the first time, since we cheat and put the
213 values into the stateblock without applying.
214 Per-texture unit: texture function (eg. combine), ops and args
215 texture env color
216 texture generation settings
217 Note: Due to some special conditions there may be a need to do particular ones
218 of these, which is what the Flags allows */
219 case WINED3DTSS_COLOROP:
220 case WINED3DTSS_TEXCOORDINDEX:
221 if (!(Flags == REAPPLY_ALL)) skip=TRUE;
222 break;
224 case WINED3DTSS_ALPHAOP:
225 if (!(Flags & REAPPLY_ALPHAOP)) skip=TRUE;
226 break;
228 default:
229 skip = FALSE;
232 if (skip == FALSE) {
233 /* Performance: Only change to this texture if we have to */
234 if (changeTexture) {
235 /* Make appropriate texture active */
236 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
237 GLACTIVETEXTURE(Stage);
238 } else if (Stage > 0) {
239 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
241 changeTexture = FALSE;
244 /* Now apply the change */
245 IWineD3DDevice_SetTextureStageState(iface, Stage, i, This->stateBlock->textureState[Stage][i]);
249 /* apply the sampler states to the texture */
250 for (i = 1; i <= HIGHEST_SAMPLER_STATE;i++) {
251 IWineD3DDevice_SetSamplerState(iface, Stage, i, This->stateBlock->samplerState[Stage][i]);
254 /* Note the D3DRS value applies to all textures, but GL has one
255 * per texture, so apply it now ready to be used!
257 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
258 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
259 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
261 TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
264 /**********************************************************
265 * IUnknown parts follows
266 **********************************************************/
268 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
270 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
271 /* FIXME: This needs to extend an IWineD3DBaseObject */
273 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
274 if (IsEqualGUID(riid, &IID_IUnknown)
275 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
276 IUnknown_AddRef(iface);
277 *ppobj = This;
278 return D3D_OK;
281 return E_NOINTERFACE;
284 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
285 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
286 ULONG refCount = InterlockedIncrement(&This->ref);
288 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
289 return refCount;
292 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
293 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
294 ULONG refCount = InterlockedDecrement(&This->ref);
296 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
298 if (!refCount) {
299 /* TODO: Clean up all the surfaces and textures! */
300 /* FIXME: Create targets and state blocks in d3d8 */
301 if (((IWineD3DImpl *)This->wineD3D)->dxVersion > 8) { /*We don't create a state block in d3d8 yet*/
302 /* NOTE: You must release the parent if the objects was created via a callback
303 ** ***************************/
304 int i;
305 IUnknown* swapChainParent;
307 /* Release all of the swapchains, except the implicite swapchain (#0) */
308 for(i = 1; i < This->numberOfSwapChains; i++){
309 /* TODO: don't access swapchains[x] directly! */
310 IWineD3DSwapChain_Release(This->swapchains[i]);
313 if (This->stateBlock != NULL) {
314 IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->stateBlock);
317 if (This->swapchains[0] != NULL) {
318 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release it's parent now */
319 /* TODO: don't access swapchains[x] directly!, check that there are no-more swapchains left for this device! */
320 IWineD3DSwapChain_GetParent(This->swapchains[0], &swapChainParent);
321 IUnknown_Release(swapChainParent); /* once for the get parent */
322 if (IUnknown_Release(swapChainParent) > 0){ /* the second time for when it was created */
323 FIXME("(%p) Something's still holding the implicite swapchain\n",This);
328 IWineD3D_Release(This->wineD3D);
329 HeapFree(GetProcessHeap(), 0, This);
331 return refCount;
334 /**********************************************************
335 * IWineD3DDevice implementation follows
336 **********************************************************/
337 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
338 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
339 *pParent = This->parent;
340 IUnknown_AddRef(This->parent);
341 return D3D_OK;
344 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
345 DWORD FVF, D3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
346 IUnknown *parent) {
347 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
348 IWineD3DVertexBufferImpl *object;
349 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
350 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, D3DRTYPE_VERTEXBUFFER)
352 object->resource.size = Size;
353 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
354 object->FVF = FVF;
356 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
357 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
359 return D3D_OK;
362 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
363 WINED3DFORMAT Format, D3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
364 HANDLE *sharedHandle, IUnknown *parent) {
365 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
366 IWineD3DIndexBufferImpl *object;
367 TRACE("(%p) Creating index buffer\n", This);
369 /* Allocate the storage for the device */
370 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,D3DRTYPE_INDEXBUFFER)
372 object->resource.size = Length;
373 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
375 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
376 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
377 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
379 return D3D_OK;
382 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, D3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
384 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
385 IWineD3DStateBlockImpl *object;
387 D3DCREATEOBJECTINSTANCE(object, StateBlock)
388 object->blockType = Type;
390 /* Special case - Used during initialization to produce a placeholder stateblock
391 so other functions called can update a state block */
392 if (Type == (D3DSTATEBLOCKTYPE) 0) {
393 /* Don't bother increasing the reference count otherwise a device will never
394 be freed due to circular dependencies */
395 return D3D_OK;
398 /* Otherwise, might as well set the whole state block to the appropriate values */
399 IWineD3DDevice_AddRef(iface);
400 memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
401 FIXME("unfinished - needs to set up changed and set attributes\n");
402 return D3D_OK;
406 /* ************************************
407 MSDN:
408 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
410 Discard
411 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
413 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.
415 ******************************** */
417 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) {
418 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
419 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
420 unsigned int pow2Width, pow2Height;
422 TRACE("(%p) Create surface\n",This);
424 /** FIXME: Check ranges on the inputs are valid
425 * MSDN
426 * MultisampleQuality
427 * [in] Quality level. The valid range is between zero and one less than the level
428 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
429 * Passing a larger value returns the error D3DERR_INVALIDCALL. The MultisampleQuality
430 * values of paired render targets, depth stencil surfaces, and the MultiSample type
431 * must all match.
432 *******************************/
436 * TODO: Discard MSDN
437 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
439 * If this flag is set, the contents of the depth stencil buffer will be
440 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
441 * with a different depth surface.
443 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
444 ***************************/
446 if(MultisampleQuality < 0) {
447 FIXME("Invalid multisample level %ld \n", MultisampleQuality);
448 return D3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
451 if(MultisampleQuality > 0){
452 FIXME("MultisampleQuality set to %ld, substituting 0 \n" , MultisampleQuality);
453 MultisampleQuality=0;
456 /* Non-power2 support */
458 /* Find the nearest pow2 match */
459 pow2Width = pow2Height = 1;
460 while (pow2Width < Width) pow2Width <<= 1;
461 while (pow2Height < Height) pow2Height <<= 1;
463 if((pow2Width > Width || pow2Height > Height) && !Usage & D3DUSAGE_RENDERTARGET) {
464 /** TODO: add support for non power two textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
465 FIXME("non-power-two textures unsupported\n");
466 return D3DERR_NOTAVAILABLE;
469 /** TODO: Check against the maximum texture sizes supported by the video card **/
471 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,D3DRTYPE_SURFACE)
472 object->container = (IUnknown*) This;
474 object->currentDesc.Width = Width;
475 object->currentDesc.Height = Height;
476 object->currentDesc.Level = Level;
477 object->currentDesc.MultiSampleType = MultiSample;
478 object->currentDesc.MultiSampleQuality = MultisampleQuality;
479 object->discard = Discard;
480 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
482 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
483 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
484 * space!
485 *********************************/
486 if (Format == WINED3DFMT_DXT1) {
487 /* DXT1 is half byte per pixel */
488 object->resource.size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4)) / 2;
490 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
491 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
492 object->resource.size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4));
493 } else {
494 object->resource.size = (Width * object->bytesPerPixel) * Height;
497 TRACE("Pool %d %d %d %d",Pool, D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM);
499 #if 0
500 /* TODO: Check that we have enough video ram left */
501 if(Pool == D3DPOOL_DEFAULT && IWineD3DDevice_GetAvailableTextureMem(iface) <= object->currentDesc.Size){
502 TRACE("Out of 'bogus' video memory\n");
503 HeapFree(GetProcessHeap(),0,object);
504 *ppSurface = NULL;
505 return D3DERR_OUTOFVIDEOMEMORY;
507 #endif
509 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
510 * this function is too deap to need to care about things like this.
511 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
512 * ****************************************/
513 switch(Pool) {
514 case D3DPOOL_SCRATCH:
515 if(Lockable == FALSE)
516 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
517 which are mutually exclusive, setting lockable to true\n");
518 Lockable = TRUE;
519 break;
520 case D3DPOOL_SYSTEMMEM:
521 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
522 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
523 case D3DPOOL_MANAGED:
524 if(Usage == D3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
525 Usage of DYNAMIC which are mutually exclusive, not doing \
526 anything just telling you.\n");
527 break;
528 case D3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
529 if(!(Usage & D3DUSAGE_DYNAMIC) && !(Usage & D3DUSAGE_RENDERTARGET)
530 && !(Usage && D3DUSAGE_DEPTHSTENCIL ) && Lockable == TRUE)
531 FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
532 break;
533 default:
534 FIXME("(%p) Unknown pool %d\n", This, Pool);
535 break;
538 if (Usage & D3DUSAGE_RENDERTARGET && Pool != D3DPOOL_DEFAULT){
539 FIXME("Trying to create a render target that isn't in the default pool\n");
543 object->locked = FALSE;
544 object->lockable = (WINED3DFMT_D16_LOCKABLE == Format) ? TRUE : Lockable;
545 /* TODO: memory management */
546 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
547 if(object->resource.allocatedMemory == NULL ) {
548 FIXME("Out of memory!\n");
549 HeapFree(GetProcessHeap(),0,object);
550 *ppSurface = NULL;
551 return D3DERR_OUTOFVIDEOMEMORY;
555 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
556 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
557 This, Width, Height, Format, debug_d3dformat(Format),
558 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
559 return D3D_OK;
563 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
564 DWORD Usage, WINED3DFORMAT Format, D3DPOOL Pool,
565 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
566 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
568 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
569 IWineD3DTextureImpl *object;
570 unsigned int i;
571 UINT tmpW;
572 UINT tmpH;
573 HRESULT hr;
575 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) .... \n", This, Width, Height, Levels, Usage);
577 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, D3DRTYPE_TEXTURE);
578 D3DINITILIZEBASETEXTURE(object->baseTexture);
579 object->width = Width;
580 object->height = Height;
582 /* Calculate levels for mip mapping */
583 if (Levels == 0) {
584 TRACE("calculating levels %d\n", object->baseTexture.levels);
585 object->baseTexture.levels++;
586 tmpW = Width;
587 tmpH = Height;
588 while (tmpW > 1 && tmpH > 1) {
589 tmpW = max(1, tmpW >> 1);
590 tmpH = max(1, tmpH >> 1);
591 object->baseTexture.levels++;
593 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
596 /* Generate all the surfaces */
597 tmpW = Width;
598 tmpH = Height;
599 for (i = 0; i < object->baseTexture.levels; i++)
601 /* use the callback to create the texture surface */
602 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
603 if(hr!= D3D_OK){
604 int j;
605 FIXME("Failed to create surface %p \n",object);
606 /* clean up */
607 for(j=0;j<i;j++){
608 IWineD3DSurface_Release(object->surfaces[j]);
610 /* heap free object */
611 HeapFree(GetProcessHeap(),0,object);
613 *ppTexture = NULL;
614 return hr;
617 IWineD3DSurface_SetContainer(object->surfaces[i], (IUnknown *)object);
618 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
619 /* calculate the next mipmap level */
620 tmpW = max(1, tmpW >> 1);
621 tmpH = max(1, tmpH >> 1);
624 TRACE("(%p) : Created texture %p\n", This, object);
625 return D3D_OK;
628 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
629 UINT Width, UINT Height, UINT Depth,
630 UINT Levels, DWORD Usage,
631 WINED3DFORMAT Format, D3DPOOL Pool,
632 IWineD3DVolumeTexture** ppVolumeTexture,
633 HANDLE* pSharedHandle, IUnknown *parent,
634 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
636 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
637 IWineD3DVolumeTextureImpl *object;
638 unsigned int i;
639 UINT tmpW;
640 UINT tmpH;
641 UINT tmpD;
643 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, D3DRTYPE_VOLUMETEXTURE);
644 D3DINITILIZEBASETEXTURE(object->baseTexture);
646 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
647 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
649 object->width = Width;
650 object->height = Height;
651 object->depth = Depth;
653 /* Calculate levels for mip mapping */
654 if (Levels == 0) {
655 object->baseTexture.levels++;
656 tmpW = Width;
657 tmpH = Height;
658 tmpD = Depth;
659 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
660 tmpW = max(1, tmpW >> 1);
661 tmpH = max(1, tmpH >> 1);
662 tmpD = max(1, tmpD >> 1);
663 object->baseTexture.levels++;
665 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
668 /* Generate all the surfaces */
669 tmpW = Width;
670 tmpH = Height;
671 tmpD = Depth;
673 for (i = 0; i < object->baseTexture.levels; i++)
675 /* Create the volume */
676 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
677 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
678 IWineD3DVolume_SetContainer(object->volumes[i], (IUnknown *)object);
680 tmpW = max(1, tmpW >> 1);
681 tmpH = max(1, tmpH >> 1);
682 tmpD = max(1, tmpD >> 1);
685 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
686 TRACE("(%p) : Created volume texture %p\n", This, object);
687 return D3D_OK;
690 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
691 UINT Width, UINT Height, UINT Depth,
692 DWORD Usage,
693 WINED3DFORMAT Format, D3DPOOL Pool,
694 IWineD3DVolume** ppVolume,
695 HANDLE* pSharedHandle, IUnknown *parent) {
697 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
698 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
700 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, D3DRTYPE_VOLUME)
702 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
703 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
705 object->currentDesc.Width = Width;
706 object->currentDesc.Height = Height;
707 object->currentDesc.Depth = Depth;
708 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
710 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
711 object->resource.size = (Width * object->bytesPerPixel) * Height * Depth;
712 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
713 object->lockable = TRUE;
714 object->locked = FALSE;
715 memset(&object->lockedBox, 0, sizeof(D3DBOX));
716 object->dirty = FALSE;
717 return IWineD3DVolume_CleanDirtyBox((IWineD3DVolume *) object);
720 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
721 UINT Levels, DWORD Usage,
722 WINED3DFORMAT Format, D3DPOOL Pool,
723 IWineD3DCubeTexture** ppCubeTexture,
724 HANDLE* pSharedHandle, IUnknown *parent,
725 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
727 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
728 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
729 unsigned int i,j;
730 UINT tmpW;
731 HRESULT hr;
733 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, D3DRTYPE_CUBETEXTURE);
734 D3DINITILIZEBASETEXTURE(object->baseTexture);
736 TRACE("(%p) Create Cube Texture \n", This);
738 object->edgeLength = EdgeLength;
740 /* Calculate levels for mip mapping */
741 if (Levels == 0) {
742 object->baseTexture.levels++;
743 tmpW = EdgeLength;
744 while (tmpW > 1) {
745 tmpW = max(1, tmpW / 2);
746 object->baseTexture.levels++;
748 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
751 /* Generate all the surfaces */
752 tmpW = EdgeLength;
753 for (i = 0; i < object->baseTexture.levels; i++) {
755 /* Create the 6 faces */
756 for (j = 0; j < 6; j++) {
758 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
759 i /* Level */, &object->surfaces[j][i],pSharedHandle);
761 if(hr!= D3D_OK){
762 /* clean up */
763 int k;
764 int l;
765 for (l=0;l<j;l++) {
766 IWineD3DSurface_Release(object->surfaces[j][i]);
768 for (k=0;k<i;k++) {
769 for (l=0;l<6;l++) {
770 IWineD3DSurface_Release(object->surfaces[l][j]);
774 FIXME("(%p) Failed to create surface\n",object);
775 HeapFree(GetProcessHeap(),0,object);
776 *ppCubeTexture = NULL;
777 return hr;
779 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IUnknown *)object);
780 TRACE("Created surface level %d @ %p, \n", i, object->surfaces[j][i]);
782 tmpW = max(1, tmpW >> 1);
785 TRACE("(%p) : Created Cube Texture %p\n", This, object);
786 *ppCubeTexture = (IWineD3DCubeTexture *) object;
787 return D3D_OK;
790 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent){
791 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
792 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
794 if(NULL == ppQuery){
795 /* Just a check to see if we support this type of query */
796 HRESULT hr = D3DERR_NOTAVAILABLE;
797 /* Lie and say everything is good (we can return ok fake data from a stub) */
798 switch(Type){
799 case WINED3DQUERYTYPE_VCACHE:
800 case WINED3DQUERYTYPE_RESOURCEMANAGER:
801 case WINED3DQUERYTYPE_VERTEXSTATS:
802 case WINED3DQUERYTYPE_EVENT:
803 case WINED3DQUERYTYPE_OCCLUSION:
804 case WINED3DQUERYTYPE_TIMESTAMP:
805 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
806 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
807 case WINED3DQUERYTYPE_PIPELINETIMINGS:
808 case WINED3DQUERYTYPE_INTERFACETIMINGS:
809 case WINED3DQUERYTYPE_VERTEXTIMINGS:
810 case WINED3DQUERYTYPE_PIXELTIMINGS:
811 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
812 case WINED3DQUERYTYPE_CACHEUTILIZATION:
813 hr = D3D_OK;
814 break;
815 default:
816 FIXME("(%p) Unhandled query type %d\n",This , Type);
818 FIXME("(%p) : Stub request for query type %d returned %ld\n", This, Type, hr);
819 return hr;
822 D3DCREATEOBJECTINSTANCE(object, Query)
823 object->type = Type;
824 object->extendedData = 0;
825 TRACE("(%p) : Created Query %p\n", This, object);
826 return D3D_OK;
829 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
830 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
831 IUnknown* parent,
832 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
833 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil){
834 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
836 HDC hDc;
837 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
838 int num;
839 XVisualInfo template;
840 GLXContext oldContext;
841 Drawable oldDrawable;
842 HRESULT hr = D3D_OK;
844 TRACE("(%p) : Created Aditional Swap Chain\n", This);
846 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
847 * does a device hold a reference to a swap chain giving them a lifetime of the device
848 * or does the swap chain notify the device of it'd destruction.
849 *******************************/
851 D3DCREATEOBJECTINSTANCE(object, SwapChain)
853 /* Initialize other useful values */
854 object->presentParms.BackBufferCount = 1; /* TODO:? support for gl_aux buffers */
856 /*********************
857 * Lookup the window Handle and the relating X window handle
858 ********************/
860 /* Setup hwnd we are using, plus which display this equates to */
861 object->win_handle = *(pPresentationParameters->hDeviceWindow);
862 if (!object->win_handle) {
863 object->win_handle = This->createParms.hFocusWindow;
866 object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window" );
867 hDc = GetDC(object->win_handle);
868 object->display = get_display(hDc);
869 ReleaseDC(object->win_handle, hDc);
870 TRACE("Using a display of %p %p \n", object->display, hDc);
872 if (NULL == object->display || NULL == hDc) {
873 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
874 return D3DERR_NOTAVAILABLE;
877 if (object->win == 0) {
878 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
879 return D3DERR_NOTAVAILABLE;
882 * Create an opengl context for the display visual
883 * NOTE: the visual is chosen as the window is created and the glcontext cannot
884 * use different properties after that point in time. FIXME: How to handle when requested format
885 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
886 * it chooses is identical to the one already being used!
887 **********************************/
889 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
890 ENTER_GL();
892 /* Create a new context for this swapchain */
893 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
894 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
895 (or the best possible if none is requested) */
896 TRACE("Found x visual ID : %ld\n", template.visualid);
898 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
899 if (NULL == object->visInfo) {
900 ERR("cannot really get XVisual\n");
901 LEAVE_GL();
902 return D3DERR_NOTAVAILABLE;
903 } else {
904 int n, value;
905 /* Write out some debug info about the visual/s */
906 TRACE("Using x visual ID : %ld\n", template.visualid);
907 TRACE(" visual info: %p\n", object->visInfo);
908 TRACE(" num items : %d\n", num);
909 for(n = 0;n < num; n++){
910 TRACE("=====item=====: %d\n", n + 1);
911 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
912 TRACE(" screen : %d\n", object->visInfo[n].screen);
913 TRACE(" depth : %u\n", object->visInfo[n].depth);
914 TRACE(" class : %d\n", object->visInfo[n].class);
915 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
916 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
917 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
918 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
919 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
920 /* log some extra glx info */
921 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
922 TRACE(" gl_aux_buffers : %d\n", value);
923 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
924 TRACE(" gl_buffer_size : %d\n", value);
925 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
926 TRACE(" gl_red_size : %d\n", value);
927 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
928 TRACE(" gl_green_size : %d\n", value);
929 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
930 TRACE(" gl_blue_size : %d\n", value);
931 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
932 TRACE(" gl_alpha_size : %d\n", value);
933 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
934 TRACE(" gl_depth_size : %d\n", value);
935 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
936 TRACE(" gl_stencil_size : %d\n", value);
938 /* Now choose a simila visual ID*/
940 #ifdef USE_CONTEXT_MANAGER
942 /** TODO: use a context mamager **/
943 #endif
946 IWineD3DSwapChain *implSwapChain;
947 if (D3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
948 /* The first time around we create the context that is shared with all other swapchians and render targets */
949 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
950 TRACE("Creating implicite context for vis %p, hwnd %p\n", object->display, object->visInfo);
951 } else {
953 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
954 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
955 /* and create a new context with the implicit swapchains context as the shared context */
956 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
957 IWineD3DSwapChain_Release(implSwapChain);
961 /* Cleanup */
962 XFree(object->visInfo);
963 object->visInfo = NULL;
965 if (NULL == object->glCtx) {
966 ERR("cannot create glxContext\n");
967 LEAVE_GL();
968 return D3DERR_NOTAVAILABLE;
971 LEAVE_GL();
972 if (object->glCtx == NULL) {
973 ERR("Error in context creation !\n");
974 return D3DERR_INVALIDCALL;
975 } else {
976 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
977 object->win_handle, object->glCtx, object->win, object->visInfo);
980 /*********************
981 * Windowed / Fullscreen
982 *******************/
985 * TODO: MSDNsays that we are only allowed one fullscreen swapchain per device,
986 * so we should really check to see if their is a fullscreen swapchain already
987 * I think Windows and X have differnt ideas about fullscreen, does a single head count as full screen?
988 **************************************/
990 if (!*(pPresentationParameters->Windowed)) {
992 DEVMODEW devmode;
993 HDC hdc;
994 int bpp = 0;
996 /* Get info on the current display setup */
997 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
998 bpp = GetDeviceCaps(hdc, BITSPIXEL);
999 DeleteDC(hdc);
1001 /* Change the display settings */
1002 memset(&devmode, 0, sizeof(DEVMODEW));
1003 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1004 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1005 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1006 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1007 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1008 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1010 /* Make popup window */
1011 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1012 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1013 *(pPresentationParameters->BackBufferWidth),
1014 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1020 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1021 * then the corresponding dimension of the client area of the hDeviceWindow
1022 * (or the focus window, if hDeviceWindow is NULL) is taken.
1023 **********************/
1025 if (*(pPresentationParameters->Windowed) &&
1026 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1027 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1029 RECT Rect;
1030 GetClientRect(object->win_handle, &Rect);
1032 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1033 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1034 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1036 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1037 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1038 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1042 /*********************
1043 * finish off parameter initialization
1044 *******************/
1046 /* Put the correct figures in the presentation parameters */
1047 TRACE("Coppying accross presentaion paraneters\n");
1048 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1049 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1050 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1051 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1052 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1053 object->presentParms.MultiSampleQuality = *(pPresentationParameters->MultiSampleQuality);
1054 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1055 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1056 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1057 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1058 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1059 object->presentParms.Flags = *(pPresentationParameters->Flags);
1060 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1061 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1064 /* FIXME: check for any failures */
1065 /*********************
1066 * Create the back, front and stencil buffers
1067 *******************/
1068 TRACE("calling rendertarget CB\n");
1069 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1070 object->presentParms.BackBufferWidth,
1071 object->presentParms.BackBufferHeight,
1072 object->presentParms.BackBufferFormat,
1073 object->presentParms.MultiSampleType,
1074 object->presentParms.MultiSampleQuality,
1075 TRUE /* Lockable */,
1076 &object->frontBuffer,
1077 NULL /* pShared (always null)*/);
1078 if (object->frontBuffer != NULL)
1079 IWineD3DSurface_SetContainer(object->frontBuffer, (IUnknown *)object);
1080 TRACE("calling rendertarget CB\n");
1081 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1082 object->presentParms.BackBufferWidth,
1083 object->presentParms.BackBufferHeight,
1084 object->presentParms.BackBufferFormat,
1085 object->presentParms.MultiSampleType,
1086 object->presentParms.MultiSampleQuality,
1087 TRUE /* Lockable */,
1088 &object->backBuffer,
1089 NULL /* pShared (always null)*/);
1090 if (object->backBuffer != NULL)
1091 IWineD3DSurface_SetContainer(object->backBuffer, (IUnknown *)object);
1093 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1094 if (pPresentationParameters->EnableAutoDepthStencil) {
1095 TRACE("Creating depth stencil buffer\n");
1096 if (This->depthStencilBuffer == NULL ) {
1097 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1098 object->presentParms.BackBufferWidth,
1099 object->presentParms.BackBufferHeight,
1100 object->presentParms.AutoDepthStencilFormat,
1101 object->presentParms.MultiSampleType,
1102 object->presentParms.MultiSampleQuality,
1103 FALSE /* FIXME: Discard */,
1104 &This->depthStencilBuffer,
1105 NULL /* pShared (always null)*/ );
1106 if (This->depthStencilBuffer != NULL)
1107 IWineD3DSurface_SetContainer(This->depthStencilBuffer, (IUnknown *)iface);
1110 /** TODO: A check on width, height and multisample types
1111 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1112 ****************************/
1113 object->wantsDepthStencilBuffer = TRUE;
1114 } else {
1115 object->wantsDepthStencilBuffer = FALSE;
1118 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1121 /*********************
1122 * init the default renderTarget management
1123 *******************/
1124 object->drawable = object->win;
1125 object->render_ctx = object->glCtx;
1127 if(hr == D3D_OK){
1128 /*********************
1129 * Setup some defaults and clear down the buffers
1130 *******************/
1131 ENTER_GL();
1132 /** save current context and drawable **/
1133 oldContext = glXGetCurrentContext();
1134 oldDrawable = glXGetCurrentDrawable();
1136 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1137 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1138 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1140 checkGLcall("glXMakeCurrent");
1142 TRACE("Setting up the screen\n");
1143 /* Clear the screen */
1144 glClearColor(0.0, 0.0, 0.0, 0.0);
1145 checkGLcall("glClearColor");
1146 glClearIndex(0);
1147 glClearDepth(1);
1148 glClearStencil(0xffff);
1150 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1151 checkGLcall("glClear");
1153 glColor3f(1.0, 1.0, 1.0);
1154 checkGLcall("glColor3f");
1156 glEnable(GL_LIGHTING);
1157 checkGLcall("glEnable");
1159 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1160 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1162 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1163 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1165 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1166 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1168 /* switch back to the original context (unless it was zero)*/
1169 if (This->numberOfSwapChains != 0) {
1170 /** TODO: restore the context and drawable **/
1171 glXMakeCurrent(object->display, oldDrawable, oldContext);
1174 LEAVE_GL();
1176 /* TODO: move this off into a linked list implementation! (add swapchain, remove swapchain or something along those lines) */
1177 #if 0
1178 IListOperator *listOperator;
1179 IListStore_CreateListOperator(This->swapchainStore, &listOperator);
1180 IListOperator_Append(listOperator, (void *)object);
1181 IListOperator_Release(listOperator);
1182 #endif
1184 This->swapchains[This->numberOfSwapChains++] = (IWineD3DSwapChain *)object;
1185 TRACE("Set swapchain to %p\n", object);
1186 } else { /* something went wrong so clean up */
1187 IUnknown* bufferParent;
1188 if (object->frontBuffer) {
1189 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1190 IUnknown_Release(bufferParent); /* once for the get parent */
1191 if(IUnknown_Release(bufferParent) > 0){
1192 FIXME("(%p) Something's still holding the front buffer\n",This);
1195 if (object->backBuffer) {
1196 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1197 IUnknown_Release(bufferParent); /* once for the get parent */
1198 if(IUnknown_Release(bufferParent) > 0){
1199 FIXME("(%p) Something's still holding the back buffer\n",This);
1202 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1203 /* Clean up the context */
1204 /* check that we are the current context first (we shouldn't be though!) */
1205 if (object->glCtx != 0) {
1206 if(glXGetCurrentContext() == object->glCtx){
1207 glXMakeCurrent(object->display, None, NULL);
1209 glXDestroyContext(object->display, object->glCtx);
1211 HeapFree(GetProcessHeap(), 0, object);
1214 return hr;
1217 /** NOTE: These are ahead of the other getters and setters to save using a forward declartion **/
1218 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1219 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1221 /* TODO: move over to using a linked list. */
1222 TRACE("(%p) returning %d\n", This, This->numberOfSwapChains);
1223 return This->numberOfSwapChains;
1226 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1227 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1228 TRACE("(%p) : swapchain %d \n", This, iSwapChain);
1230 if(iSwapChain >= IWineD3DDeviceImpl_GetNumberOfSwapChains(iface) || iSwapChain < 0){
1231 *pSwapChain = NULL;
1232 return D3DERR_INVALIDCALL;
1233 }else{
1234 /** TODO: move off to a linked list implementation **/
1235 *pSwapChain = This->swapchains[iSwapChain];
1238 /* TODO: move over to using stores and linked lists. */
1240 IWineD3DSwapChain_AddRef(*pSwapChain);
1241 TRACE("(%p) returning %p\n", This, *pSwapChain);
1242 return D3D_OK;
1245 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters){
1246 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1248 FIXME("(%p) : Stub\n",This);
1249 return D3D_OK;
1253 /*****
1254 * Vertex Declaration
1255 *****/
1256 /* TODO: Get ridd of thease and put the functions in the IWineD3DVertexDeclaration interface */
1257 #if 1
1258 extern HRESULT IWineD3DVertexDeclarationImpl_ParseDeclaration8(IWineD3DDeviceImpl * This, const DWORD* pDecl, IWineD3DVertexDeclarationImpl * object);
1259 extern HRESULT IWineD3DVertexDeclarationImpl_ParseDeclaration9(IWineD3DDeviceImpl * This, const D3DVERTEXELEMENT9* pDecl, IWineD3DVertexDeclarationImpl * object);
1262 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1263 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1264 IWineD3DVertexDeclarationImpl *object = NULL;
1265 HRESULT hr = D3D_OK;
1267 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1268 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1269 object->allFVF = 0;
1271 if (8 == ((IWineD3DImpl *)This->wineD3D)->dxVersion) {
1272 /** @TODO */
1273 hr = IWineD3DVertexDeclarationImpl_ParseDeclaration8(This, (const DWORD*) pDeclaration, object);
1274 } else {
1275 hr = IWineD3DVertexDeclarationImpl_ParseDeclaration9(This, (const D3DVERTEXELEMENT9*) pDeclaration, object);
1278 return hr;
1282 #else
1283 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration8(IWineD3DDevice* iface, const DWORD* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent){
1284 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1285 IWineD3DVertexDeclarationImpl *object = NULL; /* NOTE: impl allowed, this is a create */
1286 HRESULT hr = D3D_OK;
1287 /* TODO: replace impl usage with a call to Version*/
1288 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1289 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1290 object->allFVF = 0;
1291 /* TODO: get ridd of the impl usage, we should only be using interfaces */
1292 hr = IWineD3DVertexDeclarationImpl_ParseDeclaration8(This, pDeclaration, object);
1294 return hr;
1297 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration9(IWineD3DDevice* iface, const D3DVERTEXELEMENT9* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent){
1298 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1299 IWineD3DVertexDeclarationImpl *object = NULL; /* NOTE: impl allowed, this is a create */
1300 HRESULT hr = D3D_OK;
1301 /* TODO: replace impl usage with a call to Version*/
1302 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1303 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1304 object->allFVF = 0;
1305 /* TODO: get ridd of the impl usage, we should only be using interfaces */
1306 hr = IWineD3DVertexDeclarationImpl_ParseDeclaration9(This, pDeclaration, object);
1308 return hr;
1310 #endif
1312 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1313 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DVertexShader** ppVertexShader, IUnknown *parent){
1314 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1315 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1316 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1317 object->function = pFunction;
1318 FIXME("(%p) : STUB: Created Vertex shader %p\n", This, ppVertexShader);
1319 return D3D_OK;
1323 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DPixelShader** ppPixelShader, IUnknown *parent){
1324 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1325 FIXME("(%p) : Stub\n", This);
1326 return D3D_OK;
1329 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice* iface, IWineD3D** ppD3D){
1330 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1331 *ppD3D= This->wineD3D;
1332 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1333 IWineD3D_AddRef(*ppD3D);
1334 return D3D_OK;
1338 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1339 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1340 FIXME("Stub :(%p) returning 64Mib\n", This);
1341 return 64*1024*1024;
1345 /*****
1346 * Get / Set FVF
1347 *****/
1348 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1349 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1351 /* Update the current state block */
1352 This->updateStateBlock->fvf = fvf;
1353 This->updateStateBlock->changed.fvf = TRUE;
1354 This->updateStateBlock->set.fvf = TRUE;
1356 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1358 /* No difference if recording or not */
1359 return D3D_OK;
1361 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1362 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1363 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1364 *pfvf = This->stateBlock->fvf;
1365 return D3D_OK;
1368 /*****
1369 * Get / Set Stream Source
1370 *****/
1371 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1372 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1373 IWineD3DVertexBuffer *oldSrc;
1375 oldSrc = This->stateBlock->stream_source[StreamNumber];
1376 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1378 This->updateStateBlock->changed.stream_source[StreamNumber] = TRUE;
1379 This->updateStateBlock->set.stream_source[StreamNumber] = TRUE;
1380 This->updateStateBlock->stream_stride[StreamNumber] = Stride;
1381 This->updateStateBlock->stream_source[StreamNumber] = pStreamData;
1382 This->updateStateBlock->stream_offset[StreamNumber] = OffsetInBytes;
1384 /* Handle recording of state blocks */
1385 if (This->isRecordingState) {
1386 TRACE("Recording... not performing anything\n");
1387 return D3D_OK;
1390 /* Not recording... */
1391 if (oldSrc != NULL) IWineD3DVertexBuffer_Release(oldSrc);
1392 if (pStreamData != NULL) IWineD3DVertexBuffer_AddRef(pStreamData);
1394 return D3D_OK;
1397 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
1398 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1400 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->stateBlock->stream_source[StreamNumber], This->stateBlock->stream_stride[StreamNumber]);
1401 *pStream = This->stateBlock->stream_source[StreamNumber];
1402 *pStride = This->stateBlock->stream_stride[StreamNumber];
1403 *pOffset = This->stateBlock->stream_offset[StreamNumber];
1404 if (*pStream != NULL) IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
1405 return D3D_OK;
1408 /*Should be quite easy, just an extension of vertexdata
1409 ref...
1410 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1412 The divider is a bit odd though
1414 VertexOffset = StartVertex / Divider * StreamStride +
1415 VertexIndex / Divider * StreamStride + StreamOffset
1418 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider){
1419 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1421 FIXME("(%p) : stub\n", This);
1422 return D3D_OK;
1425 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider){
1426 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1428 FIXME("(%p) : stub\n", This);
1429 return D3D_OK;
1433 /*****
1434 * Get / Set & Multipy Transform
1435 *****/
1436 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1437 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1439 /* Most of this routine, comments included copied from ddraw tree initially: */
1440 TRACE("(%p) : Transform State=%d\n", This, d3dts);
1442 /* Handle recording of state blocks */
1443 if (This->isRecordingState) {
1444 TRACE("Recording... not performing anything\n");
1445 This->updateStateBlock->changed.transform[d3dts] = TRUE;
1446 This->updateStateBlock->set.transform[d3dts] = TRUE;
1447 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1448 return D3D_OK;
1452 * If the new matrix is the same as the current one,
1453 * we cut off any further processing. this seems to be a reasonable
1454 * optimization because as was noticed, some apps (warcraft3 for example)
1455 * tend towards setting the same matrix repeatedly for some reason.
1457 * From here on we assume that the new matrix is different, wherever it matters.
1459 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1460 TRACE("The app is setting the same matrix over again\n");
1461 return D3D_OK;
1462 } else {
1463 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1467 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1468 where ViewMat = Camera space, WorldMat = world space.
1470 In OpenGL, camera and world space is combined into GL_MODELVIEW
1471 matrix. The Projection matrix stay projection matrix.
1474 /* Capture the times we can just ignore the change for now */
1475 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1476 This->modelview_valid = FALSE;
1477 return D3D_OK;
1479 } else if (d3dts == D3DTS_PROJECTION) {
1480 This->proj_valid = FALSE;
1481 return D3D_OK;
1483 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1484 /* Indexed Vertex Blending Matrices 256 -> 511 */
1485 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1486 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1487 return D3D_OK;
1490 /* Now we really are going to have to change a matrix */
1491 ENTER_GL();
1493 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1494 if (d3dts < GL_LIMITS(textures)) {
1495 int tex = d3dts - D3DTS_TEXTURE0;
1496 GLACTIVETEXTURE(tex);
1497 set_texture_matrix((float *)lpmatrix,
1498 This->updateStateBlock->textureState[tex][WINED3DTSS_TEXTURETRANSFORMFLAGS]);
1501 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1502 unsigned int k;
1504 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1505 * NOTE: We have to reset the positions even if the light/plane is not currently
1506 * enabled, since the call to enable it will not reset the position.
1507 * NOTE2: Apparently texture transforms do NOT need reapplying
1510 PLIGHTINFOEL *lightChain = NULL;
1511 This->modelview_valid = FALSE;
1512 This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
1514 glMatrixMode(GL_MODELVIEW);
1515 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1516 glPushMatrix();
1517 glLoadMatrixf((float *)lpmatrix);
1518 checkGLcall("glLoadMatrixf(...)");
1520 /* Reset lights */
1521 lightChain = This->stateBlock->lights;
1522 while (lightChain && lightChain->glIndex != -1) {
1523 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1524 checkGLcall("glLightfv posn");
1525 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1526 checkGLcall("glLightfv dirn");
1527 lightChain = lightChain->next;
1530 /* Reset Clipping Planes if clipping is enabled */
1531 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1532 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1533 checkGLcall("glClipPlane");
1535 glPopMatrix();
1537 } else { /* What was requested!?? */
1538 WARN("invalid matrix specified: %i\n", d3dts);
1541 /* Release lock, all done */
1542 LEAVE_GL();
1543 return D3D_OK;
1546 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1547 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1548 TRACE("(%p) : for Transform State %d\n", This, State);
1549 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1550 return D3D_OK;
1553 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1554 D3DMATRIX *mat = NULL;
1555 D3DMATRIX temp;
1557 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1558 * below means it will be recorded in a state block change, but it
1559 * works regardless where it is recorded.
1560 * If this is found to be wrong, change to StateBlock.
1562 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1563 TRACE("(%p) : For state %u\n", This, State);
1565 if (State < HIGHEST_TRANSFORMSTATE)
1567 mat = &This->updateStateBlock->transforms[State];
1568 } else {
1569 FIXME("Unhandled transform state!!\n");
1572 /* Copied from ddraw code: */
1573 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);
1574 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);
1575 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);
1576 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);
1578 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);
1579 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);
1580 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);
1581 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);
1583 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);
1584 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);
1585 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);
1586 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);
1588 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);
1589 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);
1590 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);
1591 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);
1593 /* Apply change via set transform - will reapply to eg. lights this way */
1594 IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
1595 return D3D_OK;
1598 /*****
1599 * Get / Set Light
1600 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
1601 *****/
1602 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1603 you can reference any indexes you want as long as that number max are enabled at any
1604 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1605 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1606 but when recording, just build a chain pretty much of commands to be replayed. */
1608 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
1609 float rho;
1610 PLIGHTINFOEL *object, *temp;
1612 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1613 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1615 /* If recording state block, just add to end of lights chain */
1616 if (This->isRecordingState) {
1617 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1618 if (NULL == object) {
1619 return D3DERR_OUTOFVIDEOMEMORY;
1621 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1622 object->OriginalIndex = Index;
1623 object->glIndex = -1;
1624 object->changed = TRUE;
1626 /* Add to the END of the chain of lights changes to be replayed */
1627 if (This->updateStateBlock->lights == NULL) {
1628 This->updateStateBlock->lights = object;
1629 } else {
1630 temp = This->updateStateBlock->lights;
1631 while (temp->next != NULL) temp=temp->next;
1632 temp->next = object;
1634 TRACE("Recording... not performing anything more\n");
1635 return D3D_OK;
1638 /* Ok, not recording any longer so do real work */
1639 object = This->stateBlock->lights;
1640 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1642 /* If we didn't find it in the list of lights, time to add it */
1643 if (object == NULL) {
1644 PLIGHTINFOEL *insertAt,*prevPos;
1646 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1647 if (NULL == object) {
1648 return D3DERR_OUTOFVIDEOMEMORY;
1650 object->OriginalIndex = Index;
1651 object->glIndex = -1;
1653 /* Add it to the front of list with the idea that lights will be changed as needed
1654 BUT after any lights currently assigned GL indexes */
1655 insertAt = This->stateBlock->lights;
1656 prevPos = NULL;
1657 while (insertAt != NULL && insertAt->glIndex != -1) {
1658 prevPos = insertAt;
1659 insertAt = insertAt->next;
1662 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1663 This->stateBlock->lights = object;
1664 } else if (insertAt == NULL) { /* End of list */
1665 prevPos->next = object;
1666 object->prev = prevPos;
1667 } else { /* Middle of chain */
1668 if (prevPos == NULL) {
1669 This->stateBlock->lights = object;
1670 } else {
1671 prevPos->next = object;
1673 object->prev = prevPos;
1674 object->next = insertAt;
1675 insertAt->prev = object;
1679 /* Initialze the object */
1680 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,
1681 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1682 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1683 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1684 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1685 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1686 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1688 /* Save away the information */
1689 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1691 switch (pLight->Type) {
1692 case D3DLIGHT_POINT:
1693 /* Position */
1694 object->lightPosn[0] = pLight->Position.x;
1695 object->lightPosn[1] = pLight->Position.y;
1696 object->lightPosn[2] = pLight->Position.z;
1697 object->lightPosn[3] = 1.0f;
1698 object->cutoff = 180.0f;
1699 /* FIXME: Range */
1700 break;
1702 case D3DLIGHT_DIRECTIONAL:
1703 /* Direction */
1704 object->lightPosn[0] = -pLight->Direction.x;
1705 object->lightPosn[1] = -pLight->Direction.y;
1706 object->lightPosn[2] = -pLight->Direction.z;
1707 object->lightPosn[3] = 0.0;
1708 object->exponent = 0.0f;
1709 object->cutoff = 180.0f;
1710 break;
1712 case D3DLIGHT_SPOT:
1713 /* Position */
1714 object->lightPosn[0] = pLight->Position.x;
1715 object->lightPosn[1] = pLight->Position.y;
1716 object->lightPosn[2] = pLight->Position.z;
1717 object->lightPosn[3] = 1.0;
1719 /* Direction */
1720 object->lightDirn[0] = pLight->Direction.x;
1721 object->lightDirn[1] = pLight->Direction.y;
1722 object->lightDirn[2] = pLight->Direction.z;
1723 object->lightDirn[3] = 1.0;
1726 * opengl-ish and d3d-ish spot lights use too different models for the
1727 * light "intensity" as a function of the angle towards the main light direction,
1728 * so we only can approximate very roughly.
1729 * however spot lights are rather rarely used in games (if ever used at all).
1730 * furthermore if still used, probably nobody pays attention to such details.
1732 if (pLight->Falloff == 0) {
1733 rho = 6.28f;
1734 } else {
1735 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1737 if (rho < 0.0001) rho = 0.0001f;
1738 object->exponent = -0.3/log(cos(rho/2));
1739 object->cutoff = pLight->Phi*90/M_PI;
1741 /* FIXME: Range */
1742 break;
1744 default:
1745 FIXME("Unrecognized light type %d\n", pLight->Type);
1748 /* Update the live definitions if the light is currently assigned a glIndex */
1749 if (object->glIndex != -1) {
1750 setup_light(iface, object->glIndex, object);
1752 return D3D_OK;
1755 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
1756 PLIGHTINFOEL *lightInfo = NULL;
1757 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1758 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1760 /* Locate the light in the live lights */
1761 lightInfo = This->stateBlock->lights;
1762 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1764 if (lightInfo == NULL) {
1765 TRACE("Light information requested but light not defined\n");
1766 return D3DERR_INVALIDCALL;
1769 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
1770 return D3D_OK;
1773 /*****
1774 * Get / Set Light Enable
1775 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
1776 *****/
1777 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
1778 PLIGHTINFOEL *lightInfo = NULL;
1779 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1780 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1782 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1783 if (This->isRecordingState) {
1784 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1785 if (NULL == lightInfo) {
1786 return D3DERR_OUTOFVIDEOMEMORY;
1788 lightInfo->OriginalIndex = Index;
1789 lightInfo->glIndex = -1;
1790 lightInfo->enabledChanged = TRUE;
1792 /* Add to the END of the chain of lights changes to be replayed */
1793 if (This->updateStateBlock->lights == NULL) {
1794 This->updateStateBlock->lights = lightInfo;
1795 } else {
1796 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
1797 while (temp->next != NULL) temp=temp->next;
1798 temp->next = lightInfo;
1800 TRACE("Recording... not performing anything more\n");
1801 return D3D_OK;
1804 /* Not recording... So, locate the light in the live lights */
1805 lightInfo = This->stateBlock->lights;
1806 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1808 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1809 if (lightInfo == NULL) {
1810 D3DLIGHT9 lightParms;
1811 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1812 wait until someone confirms it seems to work! */
1813 TRACE("Light enabled requested but light not defined, so defining one!\n");
1814 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1815 lightParms.Diffuse.r = 1.0;
1816 lightParms.Diffuse.g = 1.0;
1817 lightParms.Diffuse.b = 1.0;
1818 lightParms.Diffuse.a = 0.0;
1819 lightParms.Specular.r = 0.0;
1820 lightParms.Specular.g = 0.0;
1821 lightParms.Specular.b = 0.0;
1822 lightParms.Specular.a = 0.0;
1823 lightParms.Ambient.r = 0.0;
1824 lightParms.Ambient.g = 0.0;
1825 lightParms.Ambient.b = 0.0;
1826 lightParms.Ambient.a = 0.0;
1827 lightParms.Position.x = 0.0;
1828 lightParms.Position.y = 0.0;
1829 lightParms.Position.z = 0.0;
1830 lightParms.Direction.x = 0.0;
1831 lightParms.Direction.y = 0.0;
1832 lightParms.Direction.z = 1.0;
1833 lightParms.Range = 0.0;
1834 lightParms.Falloff = 0.0;
1835 lightParms.Attenuation0 = 0.0;
1836 lightParms.Attenuation1 = 0.0;
1837 lightParms.Attenuation2 = 0.0;
1838 lightParms.Theta = 0.0;
1839 lightParms.Phi = 0.0;
1840 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
1842 /* Search for it again! Should be fairly quick as near head of list */
1843 lightInfo = This->stateBlock->lights;
1844 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1845 if (lightInfo == NULL) {
1846 FIXME("Adding default lights has failed dismally\n");
1847 return D3DERR_INVALIDCALL;
1851 /* OK, we now have a light... */
1852 if (Enable == FALSE) {
1854 /* If we are disabling it, check it was enabled, and
1855 still only do something if it has assigned a glIndex (which it should have!) */
1856 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
1857 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1858 ENTER_GL();
1859 glDisable(GL_LIGHT0 + lightInfo->glIndex);
1860 checkGLcall("glDisable GL_LIGHT0+Index");
1861 LEAVE_GL();
1862 } else {
1863 TRACE("Nothing to do as light was not enabled\n");
1865 lightInfo->lightEnabled = FALSE;
1866 } else {
1868 /* We are enabling it. If it is enabled, it's really simple */
1869 if (lightInfo->lightEnabled) {
1870 /* nop */
1871 TRACE("Nothing to do as light was enabled\n");
1873 /* If it already has a glIndex, it's still simple */
1874 } else if (lightInfo->glIndex != -1) {
1875 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
1876 lightInfo->lightEnabled = TRUE;
1877 ENTER_GL();
1878 glEnable(GL_LIGHT0 + lightInfo->glIndex);
1879 checkGLcall("glEnable GL_LIGHT0+Index already setup");
1880 LEAVE_GL();
1882 /* Otherwise got to find space - lights are ordered gl indexes first */
1883 } else {
1884 PLIGHTINFOEL *bsf = NULL;
1885 PLIGHTINFOEL *pos = This->stateBlock->lights;
1886 PLIGHTINFOEL *prev = NULL;
1887 int Index= 0;
1888 int glIndex = -1;
1890 /* Try to minimize changes as much as possible */
1891 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
1893 /* Try to remember which index can be replaced if necessary */
1894 if (bsf==NULL && pos->lightEnabled == FALSE) {
1895 /* Found a light we can replace, save as best replacement */
1896 bsf = pos;
1899 /* Step to next space */
1900 prev = pos;
1901 pos = pos->next;
1902 Index ++;
1905 /* If we have too many active lights, fail the call */
1906 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
1907 FIXME("Program requests too many concurrent lights\n");
1908 return D3DERR_INVALIDCALL;
1910 /* If we have allocated all lights, but not all are enabled,
1911 reuse one which is not enabled */
1912 } else if (Index == This->maxConcurrentLights) {
1913 /* use bsf - Simply swap the new light and the BSF one */
1914 PLIGHTINFOEL *bsfNext = bsf->next;
1915 PLIGHTINFOEL *bsfPrev = bsf->prev;
1917 /* Sort out ends */
1918 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
1919 if (bsf->prev != NULL) {
1920 bsf->prev->next = lightInfo;
1921 } else {
1922 This->stateBlock->lights = lightInfo;
1925 /* If not side by side, lots of chains to update */
1926 if (bsf->next != lightInfo) {
1927 lightInfo->prev->next = bsf;
1928 bsf->next->prev = lightInfo;
1929 bsf->next = lightInfo->next;
1930 bsf->prev = lightInfo->prev;
1931 lightInfo->next = bsfNext;
1932 lightInfo->prev = bsfPrev;
1934 } else {
1935 /* Simple swaps */
1936 bsf->prev = lightInfo;
1937 bsf->next = lightInfo->next;
1938 lightInfo->next = bsf;
1939 lightInfo->prev = bsfPrev;
1943 /* Update states */
1944 glIndex = bsf->glIndex;
1945 bsf->glIndex = -1;
1946 lightInfo->glIndex = glIndex;
1947 lightInfo->lightEnabled = TRUE;
1949 /* Finally set up the light in gl itself */
1950 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
1951 ENTER_GL();
1952 setup_light(iface, glIndex, lightInfo);
1953 glEnable(GL_LIGHT0 + glIndex);
1954 checkGLcall("glEnable GL_LIGHT0 new setup");
1955 LEAVE_GL();
1957 /* If we reached the end of the allocated lights, with space in the
1958 gl lights, setup a new light */
1959 } else if (pos->glIndex == -1) {
1961 /* We reached the end of the allocated gl lights, so already
1962 know the index of the next one! */
1963 glIndex = Index;
1964 lightInfo->glIndex = glIndex;
1965 lightInfo->lightEnabled = TRUE;
1967 /* In an ideal world, it's already in the right place */
1968 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
1969 /* No need to move it */
1970 } else {
1971 /* Remove this light from the list */
1972 lightInfo->prev->next = lightInfo->next;
1973 if (lightInfo->next != NULL) {
1974 lightInfo->next->prev = lightInfo->prev;
1977 /* Add in at appropriate place (inbetween prev and pos) */
1978 lightInfo->prev = prev;
1979 lightInfo->next = pos;
1980 if (prev == NULL) {
1981 This->stateBlock->lights = lightInfo;
1982 } else {
1983 prev->next = lightInfo;
1985 if (pos != NULL) {
1986 pos->prev = lightInfo;
1990 /* Finally set up the light in gl itself */
1991 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
1992 ENTER_GL();
1993 setup_light(iface, glIndex, lightInfo);
1994 glEnable(GL_LIGHT0 + glIndex);
1995 checkGLcall("glEnable GL_LIGHT0 new setup");
1996 LEAVE_GL();
2001 return D3D_OK;
2004 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2006 PLIGHTINFOEL *lightInfo = NULL;
2007 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2008 TRACE("(%p) : for idx(%ld)\n", This, Index);
2010 /* Locate the light in the live lights */
2011 lightInfo = This->stateBlock->lights;
2012 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2014 if (lightInfo == NULL) {
2015 TRACE("Light enabled state requested but light not defined\n");
2016 return D3DERR_INVALIDCALL;
2018 *pEnable = lightInfo->lightEnabled;
2019 return D3D_OK;
2022 /*****
2023 * Get / Set Clip Planes
2024 *****/
2025 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2026 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2027 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2029 /* Validate Index */
2030 if (Index >= GL_LIMITS(clipplanes)) {
2031 TRACE("Application has requested clipplane this device doesn't support\n");
2032 return D3DERR_INVALIDCALL;
2035 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2036 This->updateStateBlock->set.clipplane[Index] = TRUE;
2037 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2038 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2039 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2040 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2042 /* Handle recording of state blocks */
2043 if (This->isRecordingState) {
2044 TRACE("Recording... not performing anything\n");
2045 return D3D_OK;
2048 /* Apply it */
2050 ENTER_GL();
2052 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2053 glMatrixMode(GL_MODELVIEW);
2054 glPushMatrix();
2055 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2057 TRACE("Clipplane [%f,%f,%f,%f]\n",
2058 This->updateStateBlock->clipplane[Index][0],
2059 This->updateStateBlock->clipplane[Index][1],
2060 This->updateStateBlock->clipplane[Index][2],
2061 This->updateStateBlock->clipplane[Index][3]);
2062 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2063 checkGLcall("glClipPlane");
2065 glPopMatrix();
2066 LEAVE_GL();
2068 return D3D_OK;
2071 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2072 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2073 TRACE("(%p) : for idx %ld\n", This, Index);
2075 /* Validate Index */
2076 if (Index >= GL_LIMITS(clipplanes)) {
2077 TRACE("Application has requested clipplane this device doesn't support\n");
2078 return D3DERR_INVALIDCALL;
2081 pPlane[0] = This->stateBlock->clipplane[Index][0];
2082 pPlane[1] = This->stateBlock->clipplane[Index][1];
2083 pPlane[2] = This->stateBlock->clipplane[Index][2];
2084 pPlane[3] = This->stateBlock->clipplane[Index][3];
2085 return D3D_OK;
2088 /*****
2089 * Get / Set Clip Plane Status
2090 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2091 *****/
2092 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2093 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2094 FIXME("(%p) : stub\n", This);
2095 if (NULL == pClipStatus) {
2096 return D3DERR_INVALIDCALL;
2098 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2099 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2100 return D3D_OK;
2103 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2104 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2105 FIXME("(%p) : stub\n", This);
2106 if (NULL == pClipStatus) {
2107 return D3DERR_INVALIDCALL;
2109 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2110 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2111 return D3D_OK;
2114 /*****
2115 * Get / Set Material
2116 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2117 *****/
2118 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2119 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2121 This->updateStateBlock->changed.material = TRUE;
2122 This->updateStateBlock->set.material = TRUE;
2123 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2125 /* Handle recording of state blocks */
2126 if (This->isRecordingState) {
2127 TRACE("Recording... not performing anything\n");
2128 return D3D_OK;
2131 ENTER_GL();
2132 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2133 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2134 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2135 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2136 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2138 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2139 checkGLcall("glMaterialfv");
2140 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2141 checkGLcall("glMaterialfv");
2143 /* Only change material color if specular is enabled, otherwise it is set to black */
2144 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2145 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2146 checkGLcall("glMaterialfv");
2147 } else {
2148 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2149 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2150 checkGLcall("glMaterialfv");
2152 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2153 checkGLcall("glMaterialfv");
2154 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2155 checkGLcall("glMaterialf");
2157 LEAVE_GL();
2158 return D3D_OK;
2161 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2162 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2163 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2164 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2165 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2166 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2167 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2168 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2169 return D3D_OK;
2172 /*****
2173 * Get / Set Indices
2174 *****/
2175 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2176 UINT BaseVertexIndex) {
2177 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2178 IWineD3DIndexBuffer *oldIdxs;
2180 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2181 oldIdxs = This->updateStateBlock->pIndexData;
2183 This->updateStateBlock->changed.indices = TRUE;
2184 This->updateStateBlock->set.indices = TRUE;
2185 This->updateStateBlock->pIndexData = pIndexData;
2186 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2188 /* Handle recording of state blocks */
2189 if (This->isRecordingState) {
2190 TRACE("Recording... not performing anything\n");
2191 return D3D_OK;
2194 if (oldIdxs) IWineD3DIndexBuffer_Release(oldIdxs);
2195 if (pIndexData) IWineD3DIndexBuffer_AddRef(This->stateBlock->pIndexData);
2196 return D3D_OK;
2199 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2200 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2202 *ppIndexData = This->stateBlock->pIndexData;
2204 /* up ref count on ppindexdata */
2205 if (*ppIndexData) IWineD3DIndexBuffer_AddRef(*ppIndexData);
2206 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2208 return D3D_OK;
2211 /*****
2212 * Get / Set Viewports
2213 *****/
2214 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2215 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2217 TRACE("(%p)\n", This);
2218 This->updateStateBlock->changed.viewport = TRUE;
2219 This->updateStateBlock->set.viewport = TRUE;
2220 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2222 /* Handle recording of state blocks */
2223 if (This->isRecordingState) {
2224 TRACE("Recording... not performing anything\n");
2225 return D3D_OK;
2228 ENTER_GL();
2230 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2231 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2233 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2234 checkGLcall("glDepthRange");
2235 /* Note: GL requires lower left, DirectX supplies upper left */
2236 /* TODO: replace usage of renderTarget with context management */
2237 glViewport(pViewport->X, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2238 pViewport->Width, pViewport->Height);
2239 checkGLcall("glViewport");
2241 LEAVE_GL();
2243 return D3D_OK;
2247 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2248 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2249 TRACE("(%p)\n", This);
2250 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2251 return D3D_OK;
2254 /*****
2255 * Get / Set Render States
2256 * TODO: Verify against dx9 definitions
2257 *****/
2258 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2260 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2261 DWORD OldValue = This->stateBlock->renderState[State];
2263 /* Simple way of referring to either a DWORD or a 4 byte float */
2264 union {
2265 DWORD d;
2266 float f;
2267 } tmpvalue;
2269 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2270 This->updateStateBlock->changed.renderState[State] = TRUE;
2271 This->updateStateBlock->set.renderState[State] = TRUE;
2272 This->updateStateBlock->renderState[State] = Value;
2274 /* Handle recording of state blocks */
2275 if (This->isRecordingState) {
2276 TRACE("Recording... not performing anything\n");
2277 return D3D_OK;
2280 ENTER_GL();
2282 switch (State) {
2283 case WINED3DRS_FILLMODE :
2284 switch ((D3DFILLMODE) Value) {
2285 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2286 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2287 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2288 default:
2289 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
2291 checkGLcall("glPolygonMode (fillmode)");
2292 break;
2294 case WINED3DRS_LIGHTING :
2295 if (Value) {
2296 glEnable(GL_LIGHTING);
2297 checkGLcall("glEnable GL_LIGHTING");
2298 } else {
2299 glDisable(GL_LIGHTING);
2300 checkGLcall("glDisable GL_LIGHTING");
2302 break;
2304 case WINED3DRS_ZENABLE :
2305 switch ((D3DZBUFFERTYPE) Value) {
2306 case D3DZB_FALSE:
2307 glDisable(GL_DEPTH_TEST);
2308 checkGLcall("glDisable GL_DEPTH_TEST");
2309 break;
2310 case D3DZB_TRUE:
2311 glEnable(GL_DEPTH_TEST);
2312 checkGLcall("glEnable GL_DEPTH_TEST");
2313 break;
2314 case D3DZB_USEW:
2315 glEnable(GL_DEPTH_TEST);
2316 checkGLcall("glEnable GL_DEPTH_TEST");
2317 FIXME("W buffer is not well handled\n");
2318 break;
2319 default:
2320 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2322 break;
2324 case WINED3DRS_CULLMODE :
2326 /* If we are culling "back faces with clockwise vertices" then
2327 set front faces to be counter clockwise and enable culling
2328 of back faces */
2329 switch ((D3DCULL) Value) {
2330 case D3DCULL_NONE:
2331 glDisable(GL_CULL_FACE);
2332 checkGLcall("glDisable GL_CULL_FACE");
2333 break;
2334 case D3DCULL_CW:
2335 glEnable(GL_CULL_FACE);
2336 checkGLcall("glEnable GL_CULL_FACE");
2337 if (This->renderUpsideDown) {
2338 glFrontFace(GL_CW);
2339 checkGLcall("glFrontFace GL_CW");
2340 } else {
2341 glFrontFace(GL_CCW);
2342 checkGLcall("glFrontFace GL_CCW");
2344 glCullFace(GL_BACK);
2345 break;
2346 case D3DCULL_CCW:
2347 glEnable(GL_CULL_FACE);
2348 checkGLcall("glEnable GL_CULL_FACE");
2349 if (This->renderUpsideDown) {
2350 glFrontFace(GL_CCW);
2351 checkGLcall("glFrontFace GL_CCW");
2352 } else {
2353 glFrontFace(GL_CW);
2354 checkGLcall("glFrontFace GL_CW");
2356 glCullFace(GL_BACK);
2357 break;
2358 default:
2359 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2361 break;
2363 case WINED3DRS_SHADEMODE :
2364 switch ((D3DSHADEMODE) Value) {
2365 case D3DSHADE_FLAT:
2366 glShadeModel(GL_FLAT);
2367 checkGLcall("glShadeModel");
2368 break;
2369 case D3DSHADE_GOURAUD:
2370 glShadeModel(GL_SMOOTH);
2371 checkGLcall("glShadeModel");
2372 break;
2373 case D3DSHADE_PHONG:
2374 FIXME("D3DSHADE_PHONG isn't supported?\n");
2376 LEAVE_GL();
2377 return D3DERR_INVALIDCALL;
2378 default:
2379 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2381 break;
2383 case WINED3DRS_DITHERENABLE :
2384 if (Value) {
2385 glEnable(GL_DITHER);
2386 checkGLcall("glEnable GL_DITHER");
2387 } else {
2388 glDisable(GL_DITHER);
2389 checkGLcall("glDisable GL_DITHER");
2391 break;
2393 case WINED3DRS_ZWRITEENABLE :
2394 if (Value) {
2395 glDepthMask(1);
2396 checkGLcall("glDepthMask");
2397 } else {
2398 glDepthMask(0);
2399 checkGLcall("glDepthMask");
2401 break;
2403 case WINED3DRS_ZFUNC :
2405 int glParm = GL_LESS;
2407 switch ((D3DCMPFUNC) Value) {
2408 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2409 case D3DCMP_LESS: glParm=GL_LESS; break;
2410 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2411 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2412 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2413 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2414 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2415 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2416 default:
2417 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2419 glDepthFunc(glParm);
2420 checkGLcall("glDepthFunc");
2422 break;
2424 case WINED3DRS_AMBIENT :
2426 float col[4];
2427 D3DCOLORTOGLFLOAT4(Value, col);
2428 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2429 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2430 checkGLcall("glLightModel for MODEL_AMBIENT");
2433 break;
2435 case WINED3DRS_ALPHABLENDENABLE :
2436 if (Value) {
2437 glEnable(GL_BLEND);
2438 checkGLcall("glEnable GL_BLEND");
2439 } else {
2440 glDisable(GL_BLEND);
2441 checkGLcall("glDisable GL_BLEND");
2443 break;
2445 case WINED3DRS_SRCBLEND :
2446 case WINED3DRS_DESTBLEND :
2448 int newVal = GL_ZERO;
2449 switch (Value) {
2450 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2451 case D3DBLEND_ONE : newVal = GL_ONE; break;
2452 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2453 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2454 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2455 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2456 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2457 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2458 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2459 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2460 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2462 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2463 This->srcBlend = newVal;
2464 This->dstBlend = newVal;
2465 break;
2467 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2468 This->srcBlend = newVal;
2469 This->dstBlend = newVal;
2470 break;
2471 default:
2472 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2475 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2476 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2477 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2478 glBlendFunc(This->srcBlend, This->dstBlend);
2480 checkGLcall("glBlendFunc");
2482 break;
2484 case WINED3DRS_ALPHATESTENABLE :
2485 if (Value) {
2486 glEnable(GL_ALPHA_TEST);
2487 checkGLcall("glEnable GL_ALPHA_TEST");
2488 } else {
2489 glDisable(GL_ALPHA_TEST);
2490 checkGLcall("glDisable GL_ALPHA_TEST");
2492 break;
2494 case WINED3DRS_ALPHAFUNC :
2496 int glParm = GL_LESS;
2497 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2499 switch ((D3DCMPFUNC) Value) {
2500 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2501 case D3DCMP_LESS: glParm = GL_LESS; break;
2502 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2503 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2504 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2505 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2506 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2507 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2508 default:
2509 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2511 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2512 glAlphaFunc(glParm, ref);
2513 This->alphafunc = glParm;
2514 checkGLcall("glAlphaFunc");
2516 break;
2518 case WINED3DRS_ALPHAREF :
2520 int glParm = This->alphafunc;
2521 float ref = 1.0f;
2523 ref = ((float) Value) / 255.0f;
2524 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2525 glAlphaFunc(glParm, ref);
2526 checkGLcall("glAlphaFunc");
2528 break;
2530 case WINED3DRS_CLIPPLANEENABLE :
2531 case WINED3DRS_CLIPPING :
2533 /* Ensure we only do the changed clip planes */
2534 DWORD enable = 0xFFFFFFFF;
2535 DWORD disable = 0x00000000;
2537 /* If enabling / disabling all */
2538 if (State == WINED3DRS_CLIPPING) {
2539 if (Value) {
2540 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2541 disable = 0x00;
2542 } else {
2543 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2544 enable = 0x00;
2546 } else {
2547 enable = Value & ~OldValue;
2548 disable = ~Value & OldValue;
2551 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2552 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2553 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2554 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2555 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2556 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2558 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2559 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2560 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2561 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2562 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2563 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2565 /** update clipping status */
2566 if (enable) {
2567 This->stateBlock->clip_status.ClipUnion = 0;
2568 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
2569 } else {
2570 This->stateBlock->clip_status.ClipUnion = 0;
2571 This->stateBlock->clip_status.ClipIntersection = 0;
2574 break;
2576 case WINED3DRS_BLENDOP :
2578 int glParm = GL_FUNC_ADD;
2580 switch ((D3DBLENDOP) Value) {
2581 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2582 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2583 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2584 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2585 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2586 default:
2587 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2589 TRACE("glBlendEquation(%x)\n", glParm);
2590 glBlendEquation(glParm);
2591 checkGLcall("glBlendEquation");
2593 break;
2595 case WINED3DRS_TEXTUREFACTOR :
2597 unsigned int i;
2599 /* Note the texture color applies to all textures whereas
2600 GL_TEXTURE_ENV_COLOR applies to active only */
2601 float col[4];
2602 D3DCOLORTOGLFLOAT4(Value, col);
2603 /* Set the default alpha blend color */
2604 glBlendColor(col[0], col[1], col[2], col[3]);
2605 checkGLcall("glBlendColor");
2607 /* And now the default texture color as well */
2608 for (i = 0; i < GL_LIMITS(textures); i++) {
2610 /* Note the D3DRS value applies to all textures, but GL has one
2611 per texture, so apply it now ready to be used! */
2612 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2613 GLACTIVETEXTURE(i);
2614 } else if (i>0) {
2615 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2618 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2619 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2622 break;
2624 case WINED3DRS_SPECULARENABLE :
2626 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2627 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2628 specular color. This is wrong:
2629 Separate specular color means the specular colour is maintained separately, whereas
2630 single color means it is merged in. However in both cases they are being used to
2631 some extent.
2632 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2633 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2634 running 1.4 yet!
2636 if (Value) {
2637 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2638 checkGLcall("glMaterialfv");
2639 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2640 glEnable(GL_COLOR_SUM_EXT);
2641 } else {
2642 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2644 checkGLcall("glEnable(GL_COLOR_SUM)");
2645 } else {
2646 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2648 /* for the case of enabled lighting: */
2649 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2650 checkGLcall("glMaterialfv");
2652 /* for the case of disabled lighting: */
2653 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2654 glDisable(GL_COLOR_SUM_EXT);
2655 } else {
2656 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2658 checkGLcall("glDisable(GL_COLOR_SUM)");
2661 break;
2663 case WINED3DRS_STENCILENABLE :
2664 if (Value) {
2665 glEnable(GL_STENCIL_TEST);
2666 checkGLcall("glEnable GL_STENCIL_TEST");
2667 } else {
2668 glDisable(GL_STENCIL_TEST);
2669 checkGLcall("glDisable GL_STENCIL_TEST");
2671 break;
2673 case WINED3DRS_STENCILFUNC :
2675 int glParm = GL_ALWAYS;
2676 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2677 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2679 switch ((D3DCMPFUNC) Value) {
2680 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2681 case D3DCMP_LESS: glParm=GL_LESS; break;
2682 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2683 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2684 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2685 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2686 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2687 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2688 default:
2689 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2691 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2692 This->stencilfunc = glParm;
2693 glStencilFunc(glParm, ref, mask);
2694 checkGLcall("glStencilFunc");
2696 break;
2698 case WINED3DRS_STENCILREF :
2700 int glParm = This->stencilfunc;
2701 int ref = 0;
2702 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2704 ref = Value;
2705 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2706 glStencilFunc(glParm, ref, mask);
2707 checkGLcall("glStencilFunc");
2709 break;
2711 case WINED3DRS_STENCILMASK :
2713 int glParm = This->stencilfunc;
2714 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2715 GLuint mask = Value;
2717 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2718 glStencilFunc(glParm, ref, mask);
2719 checkGLcall("glStencilFunc");
2721 break;
2723 case WINED3DRS_STENCILFAIL :
2725 GLenum fail ;
2726 GLenum zpass ;
2727 GLenum zfail ;
2729 fail = StencilOp(Value);
2730 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2731 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2732 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2733 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2735 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2736 glStencilOp(fail, zfail, zpass);
2737 checkGLcall("glStencilOp(fail, zfail, zpass);");
2739 break;
2740 case WINED3DRS_STENCILZFAIL :
2742 GLenum fail ;
2743 GLenum zpass ;
2744 GLenum zfail ;
2746 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2747 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2748 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2749 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2750 zfail = StencilOp(Value);
2752 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2753 glStencilOp(fail, zfail, zpass);
2754 checkGLcall("glStencilOp(fail, zfail, zpass);");
2756 break;
2757 case WINED3DRS_STENCILPASS :
2759 GLenum fail ;
2760 GLenum zpass ;
2761 GLenum zfail ;
2763 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2764 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2765 zpass = StencilOp(Value);
2766 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2767 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2769 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2770 glStencilOp(fail, zfail, zpass);
2771 checkGLcall("glStencilOp(fail, zfail, zpass);");
2773 break;
2775 case WINED3DRS_STENCILWRITEMASK :
2777 glStencilMask(Value);
2778 TRACE("glStencilMask(%lu)\n", Value);
2779 checkGLcall("glStencilMask");
2781 break;
2783 case WINED3DRS_FOGENABLE :
2785 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2786 glEnable(GL_FOG);
2787 checkGLcall("glEnable GL_FOG");
2788 } else {
2789 glDisable(GL_FOG);
2790 checkGLcall("glDisable GL_FOG");
2793 break;
2795 case WINED3DRS_RANGEFOGENABLE :
2797 if (Value) {
2798 TRACE("Enabled RANGEFOG");
2799 } else {
2800 TRACE("Disabled RANGEFOG");
2803 break;
2805 case WINED3DRS_FOGCOLOR :
2807 float col[4];
2808 D3DCOLORTOGLFLOAT4(Value, col);
2809 /* Set the default alpha blend color */
2810 glFogfv(GL_FOG_COLOR, &col[0]);
2811 checkGLcall("glFog GL_FOG_COLOR");
2813 break;
2815 case WINED3DRS_FOGTABLEMODE :
2817 glHint(GL_FOG_HINT, GL_NICEST);
2818 switch (Value) {
2819 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2820 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2821 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2822 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2823 default:
2824 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
2826 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2827 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
2830 break;
2832 case WINED3DRS_FOGVERTEXMODE :
2834 glHint(GL_FOG_HINT, GL_FASTEST);
2835 switch (Value) {
2836 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2837 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2838 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2839 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2840 default:
2841 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
2843 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2844 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
2847 break;
2849 case WINED3DRS_FOGSTART :
2851 tmpvalue.d = Value;
2852 glFogfv(GL_FOG_START, &tmpvalue.f);
2853 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2854 TRACE("Fog Start == %f\n", tmpvalue.f);
2856 break;
2858 case WINED3DRS_FOGEND :
2860 tmpvalue.d = Value;
2861 glFogfv(GL_FOG_END, &tmpvalue.f);
2862 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2863 TRACE("Fog End == %f\n", tmpvalue.f);
2865 break;
2867 case WINED3DRS_FOGDENSITY :
2869 tmpvalue.d = Value;
2870 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
2871 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2873 break;
2875 case WINED3DRS_VERTEXBLEND :
2877 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2878 TRACE("Vertex Blending state to %ld\n", Value);
2880 break;
2882 case WINED3DRS_TWEENFACTOR :
2884 tmpvalue.d = Value;
2885 This->updateStateBlock->tween_factor = tmpvalue.f;
2886 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
2888 break;
2890 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
2892 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2894 break;
2896 case WINED3DRS_COLORVERTEX :
2897 case WINED3DRS_DIFFUSEMATERIALSOURCE :
2898 case WINED3DRS_SPECULARMATERIALSOURCE :
2899 case WINED3DRS_AMBIENTMATERIALSOURCE :
2900 case WINED3DRS_EMISSIVEMATERIALSOURCE :
2902 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2904 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
2905 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2906 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
2907 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
2908 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
2909 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
2911 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2912 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2913 Parm = GL_AMBIENT_AND_DIFFUSE;
2914 } else {
2915 Parm = GL_DIFFUSE;
2917 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2918 Parm = GL_AMBIENT;
2919 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2920 Parm = GL_EMISSION;
2921 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2922 Parm = GL_SPECULAR;
2923 } else {
2924 Parm = -1;
2927 if (Parm == -1) {
2928 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2929 } else {
2930 This->tracking_color = NEEDS_TRACKING;
2931 This->tracking_parm = Parm;
2934 } else {
2935 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2938 break;
2940 case WINED3DRS_LINEPATTERN :
2942 union {
2943 DWORD d;
2944 D3DLINEPATTERN lp;
2945 } tmppattern;
2946 tmppattern.d = Value;
2948 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2950 if (tmppattern.lp.wRepeatFactor) {
2951 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2952 checkGLcall("glLineStipple(repeat, linepattern)");
2953 glEnable(GL_LINE_STIPPLE);
2954 checkGLcall("glEnable(GL_LINE_STIPPLE);");
2955 } else {
2956 glDisable(GL_LINE_STIPPLE);
2957 checkGLcall("glDisable(GL_LINE_STIPPLE);");
2960 break;
2962 case WINED3DRS_ZBIAS :
2964 if (Value) {
2965 tmpvalue.d = Value;
2966 TRACE("ZBias value %f\n", tmpvalue.f);
2967 glPolygonOffset(0, -tmpvalue.f);
2968 checkGLcall("glPolygonOffset(0, -Value)");
2969 glEnable(GL_POLYGON_OFFSET_FILL);
2970 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
2971 glEnable(GL_POLYGON_OFFSET_LINE);
2972 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
2973 glEnable(GL_POLYGON_OFFSET_POINT);
2974 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
2975 } else {
2976 glDisable(GL_POLYGON_OFFSET_FILL);
2977 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
2978 glDisable(GL_POLYGON_OFFSET_LINE);
2979 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
2980 glDisable(GL_POLYGON_OFFSET_POINT);
2981 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
2984 break;
2986 case WINED3DRS_NORMALIZENORMALS :
2987 if (Value) {
2988 glEnable(GL_NORMALIZE);
2989 checkGLcall("glEnable(GL_NORMALIZE);");
2990 } else {
2991 glDisable(GL_NORMALIZE);
2992 checkGLcall("glDisable(GL_NORMALIZE);");
2994 break;
2996 case WINED3DRS_POINTSIZE :
2997 tmpvalue.d = Value;
2998 TRACE("Set point size to %f\n", tmpvalue.f);
2999 glPointSize(tmpvalue.f);
3000 checkGLcall("glPointSize(...);");
3001 break;
3003 case WINED3DRS_POINTSIZE_MIN :
3004 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3005 tmpvalue.d = Value;
3006 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3007 checkGLcall("glPointParameterfEXT(...);");
3008 } else {
3009 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3011 break;
3013 case WINED3DRS_POINTSIZE_MAX :
3014 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3015 tmpvalue.d = Value;
3016 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3017 checkGLcall("glPointParameterfEXT(...);");
3018 } else {
3019 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3021 break;
3023 case WINED3DRS_POINTSCALE_A :
3024 case WINED3DRS_POINTSCALE_B :
3025 case WINED3DRS_POINTSCALE_C :
3026 case WINED3DRS_POINTSCALEENABLE :
3028 /* If enabled, supply the parameters, otherwise fall back to defaults */
3029 if (This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3030 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3031 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]);
3032 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]);
3033 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]);
3035 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3036 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3037 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3038 } else {
3039 TRACE("WINED3DRS_POINTSCALEENABLE not supported on this opengl\n");
3041 } else {
3042 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3043 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3044 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3045 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3046 } else {
3047 TRACE("WINED3DRS_POINTSCALEENABLE not supported, but not on either\n");
3050 break;
3053 case WINED3DRS_COLORWRITEENABLE :
3055 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3056 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3057 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3058 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3059 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3060 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3061 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3062 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3063 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3064 checkGLcall("glColorMask(...)");
3066 break;
3068 case WINED3DRS_LOCALVIEWER :
3070 GLint state = (Value) ? 1 : 0;
3071 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3072 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3074 break;
3076 case WINED3DRS_LASTPIXEL :
3078 if (Value) {
3079 TRACE("Last Pixel Drawing Enabled\n");
3080 } else {
3081 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3084 break;
3086 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3088 if (Value) {
3089 TRACE("Software Processing Enabled\n");
3090 } else {
3091 TRACE("Software Processing Disabled\n");
3094 break;
3096 /** not supported */
3097 case WINED3DRS_ZVISIBLE :
3099 LEAVE_GL();
3100 return D3DERR_INVALIDCALL;
3103 /* Unhandled yet...! */
3104 case WINED3DRS_EDGEANTIALIAS :
3105 case WINED3DRS_WRAP0 :
3106 case WINED3DRS_WRAP1 :
3107 case WINED3DRS_WRAP2 :
3108 case WINED3DRS_WRAP3 :
3109 case WINED3DRS_WRAP4 :
3110 case WINED3DRS_WRAP5 :
3111 case WINED3DRS_WRAP6 :
3112 case WINED3DRS_WRAP7 :
3113 case WINED3DRS_POINTSPRITEENABLE :
3114 case WINED3DRS_MULTISAMPLEANTIALIAS :
3115 case WINED3DRS_MULTISAMPLEMASK :
3116 case WINED3DRS_PATCHEDGESTYLE :
3117 case WINED3DRS_PATCHSEGMENTS :
3118 case WINED3DRS_DEBUGMONITORTOKEN :
3119 case WINED3DRS_POSITIONORDER :
3120 case WINED3DRS_NORMALORDER :
3121 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3122 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3123 break;
3124 default:
3125 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3128 LEAVE_GL();
3130 return D3D_OK;
3133 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3134 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3135 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3136 *pValue = This->stateBlock->renderState[State];
3137 return D3D_OK;
3140 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value){
3141 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3143 * SetSampler is designed to allow for more than the standard upto 8 textures
3144 * and Geforce has stopped suporting more than 6 standards texture in openGL,
3145 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3147 * http://developer.nvidia.com/object/General_FAQ.html#t6
3149 * There are two new settings for GForce
3150 * the sampler one:
3151 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3152 * and the texture one:
3153 * GL_MAX_TEXTURE_COORDS_ARB.
3154 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3155 ******************/
3156 union {
3157 float f;
3158 DWORD d;
3159 } tmpvalue;
3161 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
3163 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > HIGHEST_SAMPLER_STATE || Type < 0){
3164 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), HIGHEST_SAMPLER_STATE, Sampler, Type);
3165 return D3DERR_INVALIDCALL;
3168 This->updateStateBlock->changed.samplerState[Sampler][Type] = TRUE;
3169 This->updateStateBlock->set.samplerState[Sampler][Type] = TRUE;
3170 TRACE("Setting sampler %ld %d to %ld \n", Sampler, Type, Value);
3171 This->updateStateBlock->samplerState[Sampler][Type] = Value;
3173 /* Handle recording of state blocks */
3174 if (This->isRecordingState) {
3175 TRACE("Recording... not performing anything\n");
3176 return D3D_OK;
3179 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
3180 clamping, MIPLOD, etc. This will work for up to 16 samplers.
3181 is this just GL_TEXTURE_2D or is it GL_TEXTURE_1D and GL_TEXTURE_3D as well?
3183 ENTER_GL();
3184 VTRACE(("Activating appropriate texture state %ld\n", Sampler));
3185 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3186 GLACTIVETEXTURE(Sampler);
3187 } else if (Sampler > 0) {
3188 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3192 switch (Type) {
3194 case WINED3DSAMP_ADDRESSU : /* 1 */
3195 case WINED3DSAMP_ADDRESSV : /* 2 */
3196 case WINED3DSAMP_ADDRESSW : /* 3 */
3198 GLint wrapParm = GL_REPEAT;
3199 switch (Value) {
3200 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3201 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3202 case D3DTADDRESS_BORDER:
3204 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3205 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3206 } else {
3207 /* FIXME: Not right, but better */
3208 TRACE("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3209 wrapParm = GL_REPEAT;
3212 break;
3213 case D3DTADDRESS_MIRROR:
3215 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3216 wrapParm = GL_MIRRORED_REPEAT_ARB;
3217 } else {
3218 /* Unsupported in OpenGL pre-1.4 */
3219 TRACE("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3220 wrapParm = GL_REPEAT;
3223 break;
3224 case D3DTADDRESS_MIRRORONCE:
3226 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3227 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3228 } else {
3229 TRACE("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3230 wrapParm = GL_REPEAT;
3233 break;
3235 default:
3236 /* This is for the whole context, not just the sampler,
3237 so we should warn if two states are baing set for any given scene */
3238 if (Type!=0)
3239 TRACE("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3240 wrapParm = GL_REPEAT;
3242 switch (Type) {
3243 case WINED3DSAMP_ADDRESSU:
3244 TRACE("Setting WRAP_S for %ld to %d \n", Sampler, wrapParm);
3245 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_WRAP_S, wrapParm);
3246 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3247 break;
3248 case WINED3DSAMP_ADDRESSV:
3249 TRACE("Setting WRAP_T for %ld to %d\n", Sampler, wrapParm);
3250 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_WRAP_T, wrapParm);
3251 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3252 break;
3254 case WINED3DSAMP_ADDRESSW:
3255 TRACE("Setting WRAP_R for %ld to %d\n", Sampler, wrapParm);
3256 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_WRAP_R, wrapParm);
3257 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3258 break;
3259 default: /* nop */
3260 break; /** stupic compilator */
3263 break;
3265 case WINED3DSAMP_BORDERCOLOR : /* 4 */
3267 float col[4];
3268 D3DCOLORTOGLFLOAT4(Value, col);
3269 TRACE("Setting border color for %ld to %lx\n", Sampler, Value);
3270 glTexParameterfv(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_BORDER_COLOR, &col[0]);
3271 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3273 break;
3275 case WINED3DSAMP_MAGFILTER : /* 5 */
3277 DWORD ValueMAG = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAGFILTER];
3278 GLint realVal = GL_NEAREST;
3280 if (ValueMAG == D3DTEXF_POINT) {
3281 realVal = GL_NEAREST;
3282 } else if (ValueMAG == D3DTEXF_LINEAR) {
3283 realVal = GL_LINEAR;
3284 } else if (ValueMAG == D3DTEXF_ANISOTROPIC) {
3285 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3286 realVal = GL_LINEAR;
3287 } else {
3288 FIXME("Trying to use ANISOTROPIC_FILTERING for WINED3DTSS_MAGFILTER. But not supported by current OpenGL driver\n");
3289 realVal = GL_NEAREST;
3291 } else {
3292 FIXME("Unhandled WINED3DTSS_MAGFILTER value of %ld\n", ValueMAG);
3293 realVal = GL_NEAREST;
3295 TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", ValueMAG, realVal);
3296 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_MAG_FILTER, realVal);
3297 checkGLcall("glTexParameter GL_TEXTURE_MAG_FILTER, ...");
3299 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3301 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMAG) {
3302 glTexParameteri(This->stateBlock->textureDimensions[Sampler],
3303 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3304 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXANISOTROPY]);
3305 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3308 break;
3310 case WINED3DSAMP_MINFILTER: /* 6 */
3311 case WINED3DSAMP_MIPFILTER: /* 7 */
3313 DWORD ValueMIN = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MINFILTER];
3314 DWORD ValueMIP = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPFILTER];
3315 GLint realVal = GL_LINEAR;
3317 if (ValueMIN == D3DTEXF_NONE) {
3318 /* Doesn't really make sense - Windows just seems to disable
3319 mipmapping when this occurs */
3320 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3321 realVal = GL_LINEAR;
3322 } else if (ValueMIN == D3DTEXF_POINT) {
3323 /* GL_NEAREST_* */
3324 if (ValueMIP == D3DTEXF_NONE) {
3325 realVal = GL_NEAREST;
3326 } else if (ValueMIP == D3DTEXF_POINT) {
3327 realVal = GL_NEAREST_MIPMAP_NEAREST;
3328 } else if (ValueMIP == D3DTEXF_LINEAR) {
3329 realVal = GL_NEAREST_MIPMAP_LINEAR;
3330 } else {
3331 FIXME("Unhandled WINED3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3332 realVal = GL_NEAREST;
3334 } else if (ValueMIN == D3DTEXF_LINEAR) {
3335 /* GL_LINEAR_* */
3336 if (ValueMIP == D3DTEXF_NONE) {
3337 realVal = GL_LINEAR;
3338 } else if (ValueMIP == D3DTEXF_POINT) {
3339 realVal = GL_LINEAR_MIPMAP_NEAREST;
3340 } else if (ValueMIP == D3DTEXF_LINEAR) {
3341 realVal = GL_LINEAR_MIPMAP_LINEAR;
3342 } else {
3343 FIXME("Unhandled WINED3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3344 realVal = GL_LINEAR;
3346 } else if (ValueMIN == D3DTEXF_ANISOTROPIC) {
3347 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3348 if (ValueMIP == D3DTEXF_NONE) {
3349 realVal = GL_LINEAR_MIPMAP_LINEAR;
3350 } else if (ValueMIP == D3DTEXF_POINT) {
3351 realVal = GL_LINEAR_MIPMAP_NEAREST;
3352 } else if (ValueMIP == D3DTEXF_LINEAR) {
3353 realVal = GL_LINEAR_MIPMAP_LINEAR;
3354 } else {
3355 FIXME("Unhandled WINED3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3356 realVal = GL_LINEAR;
3358 } else {
3359 WARN("Trying to use ANISOTROPIC_FILTERING for WINED3DTSS_MINFILTER. But not supported by OpenGL driver\n");
3360 realVal = GL_LINEAR;
3362 } else {
3363 FIXME("Unhandled WINED3DTSS_MINFILTER value of %ld\n", ValueMIN);
3364 realVal = GL_LINEAR_MIPMAP_LINEAR;
3367 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3368 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_MIN_FILTER, realVal);
3369 checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
3371 * if we just choose to use ANISOTROPIC filtering, refresh openGL state
3373 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMIN) {
3374 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_MAX_ANISOTROPY_EXT,
3375 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXANISOTROPY]);
3376 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3379 break;
3381 case WINED3DSAMP_MIPMAPLODBIAS : /* 8 */
3383 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3384 tmpvalue.d = Value;
3385 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3386 GL_TEXTURE_LOD_BIAS_EXT,
3387 tmpvalue.f);
3388 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
3391 break;
3393 case WINED3DSAMP_MAXMIPLEVEL : /* 9 */
3396 * Not really the same, but the more apprioprate than nothing
3398 glTexParameteri(This->stateBlock->textureDimensions[Sampler],
3399 GL_TEXTURE_BASE_LEVEL,
3400 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXMIPLEVEL]);
3401 checkGLcall("glTexParameteri GL_TEXTURE_BASE_LEVEL ...");
3403 break;
3405 case WINED3DSAMP_MAXANISOTROPY : /* 10 */
3407 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3408 glTexParameteri(This->stateBlock->textureDimensions[Sampler],
3409 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3410 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXANISOTROPY]);
3411 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3414 break;
3415 case WINED3DSAMP_SRGBTEXTURE : /* 11 */
3416 /* Per texture gamma correction, default 0 */
3417 case WINED3DSAMP_ELEMENTINDEX : /* 12 */
3418 /* When a multi-element textures is used this indicates the element, (what's a multielement texture?) */
3419 case WINED3DSAMP_DMAPOFFSET : /* 13 */
3420 /* Value of a precompiled displacement map used by the tesselator, default 0 */
3421 TRACE("Unsupported sampler setting, Sampler=%ld, Type=%d, Value =%ld\n", Sampler, Type, Value);
3422 break;
3423 default:
3425 TRACE("invalid sampler setting, Sampler=%ld, Type=%d, Value =%ld\n", Sampler, Type, Value);
3427 LEAVE_GL();
3428 return D3D_OK;
3431 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value){
3432 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3433 /** TODO: check that sampler is in range **/
3434 *Value = This->updateStateBlock->samplerState[Sampler][Type];
3435 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
3436 return D3D_OK;
3440 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect){
3441 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3442 ENTER_GL();
3444 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3445 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3446 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3447 LEAVE_GL();
3448 return D3D_OK;
3451 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect){
3452 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3453 GLint scissorBox[4];
3455 ENTER_GL();
3456 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3457 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
3458 pRect->left = scissorBox[1];
3459 pRect->top = scissorBox[2];
3460 pRect->right = scissorBox[1] + scissorBox[3];
3461 pRect->bottom = scissorBox[2] + scissorBox[4];
3462 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3463 LEAVE_GL();
3464 return D3D_OK;
3467 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3468 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3470 TRACE("(%p) : pDecl=%p\n", This, pDecl);
3472 IWineD3DVertexDeclaration_AddRef(pDecl);
3473 if (NULL != This->updateStateBlock->vertexDecl) {
3474 IWineD3DVertexDeclaration_Release(This->updateStateBlock->vertexDecl);
3476 This->updateStateBlock->vertexDecl = pDecl;
3477 This->updateStateBlock->changed.vertexDecl = TRUE;
3478 This->updateStateBlock->set.vertexDecl = TRUE;
3479 return D3D_OK;
3482 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3483 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3485 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3487 *ppDecl = This->updateStateBlock->vertexDecl;
3488 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3489 return D3D_OK;
3492 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader){
3493 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3495 static BOOL showFixmes = TRUE;
3497 This->updateStateBlock->vertexShader = pShader;
3498 This->updateStateBlock->changed.vertexShader = TRUE;
3499 This->updateStateBlock->set.vertexShader = TRUE;
3501 if(pShader == NULL){
3502 /* clear down the shader */
3503 TRACE("Clear down the shader\n");
3504 }else{
3505 if(showFixmes){
3506 FIXME("(%p) : stub pShader(%p)\n", This, pShader);
3507 showFixmes = FALSE;
3511 return D3D_OK;
3513 /** FIXME: refernece counting? **/
3514 if (pShader == NULL) { /* only valid with non FVF shaders */
3515 TRACE_(d3d_shader)("(%p) : FVF Shader, pShader=%p\n", This, pShader);
3516 This->updateStateBlock->vertexShader = NULL;
3517 } else {
3518 TRACE_(d3d_shader)("(%p) : Created shader, pShader=%p\n", This, pShader);
3519 This->updateStateBlock->vertexShader = pShader;
3522 This->updateStateBlock->changed.vertexShader = TRUE;
3523 This->updateStateBlock->set.vertexShader = TRUE;
3525 /* Handle recording of state blocks */
3526 if (This->isRecordingState) {
3527 TRACE("Recording... not performing anything\n");
3528 return D3D_OK;
3531 * TODO: merge HAL shaders context switching from prototype
3533 return D3D_OK;
3537 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader){
3538 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3539 *ppShader = This->stateBlock->vertexShader;
3540 if(*ppShader != NULL)
3541 IWineD3DVertexShader_AddRef(*ppShader);
3542 TRACE("(%p) : returning %p\n", This, *ppShader);
3543 return D3D_OK;
3546 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
3547 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3549 TRACE("(%p) : stub\n", This);
3550 return D3D_OK;
3553 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
3554 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3555 TRACE("(%p) : stub\n", This);
3556 return D3D_OK;
3559 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
3560 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3561 TRACE("(%p) : stub\n", This);
3562 return D3D_OK;
3565 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
3566 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3567 TRACE("(%p) : stub\n", This);
3568 return D3D_OK;
3571 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
3572 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3573 TRACE("(%p) : stub\n", This);
3574 return D3D_OK;
3577 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
3578 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3579 TRACE("(%p) : stub\n", This);
3580 return D3D_OK;
3583 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader){
3584 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3585 TRACE("(%p) : stub\n", This);
3586 return D3D_OK;
3589 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader){
3590 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3591 TRACE("(%p) : stub\n", This);
3592 return D3D_OK;
3596 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
3597 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3598 TRACE("(%p) : stub\n", This);
3599 return D3D_OK;
3602 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
3603 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3604 TRACE("(%p) : stub\n", This);
3605 return D3D_OK;
3608 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
3609 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3610 TRACE("(%p) : stub\n", This);
3611 return D3D_OK;
3614 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
3615 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3616 TRACE("(%p) : stub\n", This);
3617 return D3D_OK;
3620 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
3621 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3622 TRACE("(%p) : stub\n", This);
3623 return D3D_OK;
3626 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
3627 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3628 TRACE("(%p) : stub\n", This);
3629 return D3D_OK;
3632 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags){
3633 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3634 FIXME("(%p) : stub\n", This);
3635 return D3D_OK;
3638 /*****
3639 * Get / Set Texture Stage States
3640 * TODO: Verify against dx9 definitions
3641 *****/
3642 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3643 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3645 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3647 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3649 /* Reject invalid texture units */
3650 if (Stage >= GL_LIMITS(textures)) {
3651 TRACE("Attempt to access invalid texture rejected\n");
3652 return D3DERR_INVALIDCALL;
3655 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
3656 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
3657 This->updateStateBlock->textureState[Stage][Type] = Value;
3659 /* Handle recording of state blocks */
3660 if (This->isRecordingState) {
3661 TRACE("Recording... not performing anything\n");
3662 return D3D_OK;
3665 ENTER_GL();
3667 /* Make appropriate texture active */
3668 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3669 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3670 GLACTIVETEXTURE(Stage);
3671 } else if (Stage > 0) {
3672 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3675 switch (Type) {
3676 case WINED3DTSS_ALPHAOP :
3677 case WINED3DTSS_COLOROP :
3680 if ((Value == D3DTOP_DISABLE) && (Type == WINED3DTSS_COLOROP)) {
3681 /* TODO: Disable by making this and all later levels disabled */
3682 glDisable(GL_TEXTURE_1D);
3683 checkGLcall("Disable GL_TEXTURE_1D");
3684 glDisable(GL_TEXTURE_2D);
3685 checkGLcall("Disable GL_TEXTURE_2D");
3686 glDisable(GL_TEXTURE_3D);
3687 checkGLcall("Disable GL_TEXTURE_3D");
3688 break; /* Don't bother setting the texture operations */
3689 } else {
3690 /* Enable only the appropriate texture dimension */
3691 if (Type == WINED3DTSS_COLOROP) {
3692 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3693 glEnable(GL_TEXTURE_1D);
3694 checkGLcall("Enable GL_TEXTURE_1D");
3695 } else {
3696 glDisable(GL_TEXTURE_1D);
3697 checkGLcall("Disable GL_TEXTURE_1D");
3699 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3700 if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
3701 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
3702 checkGLcall("Enable GL_TEXTURE_2D");
3703 } else {
3704 glEnable(GL_TEXTURE_2D);
3705 checkGLcall("Enable GL_TEXTURE_2D");
3707 } else {
3708 glDisable(GL_TEXTURE_2D);
3709 checkGLcall("Disable GL_TEXTURE_2D");
3711 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3712 glEnable(GL_TEXTURE_3D);
3713 checkGLcall("Enable GL_TEXTURE_3D");
3714 } else {
3715 glDisable(GL_TEXTURE_3D);
3716 checkGLcall("Disable GL_TEXTURE_3D");
3718 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3719 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3720 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3721 } else {
3722 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3723 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3727 /* Drop through... (Except disable case) */
3728 case WINED3DTSS_COLORARG0 :
3729 case WINED3DTSS_COLORARG1 :
3730 case WINED3DTSS_COLORARG2 :
3731 case WINED3DTSS_ALPHAARG0 :
3732 case WINED3DTSS_ALPHAARG1 :
3733 case WINED3DTSS_ALPHAARG2 :
3735 BOOL isAlphaArg = (Type == WINED3DTSS_ALPHAOP || Type == WINED3DTSS_ALPHAARG1 ||
3736 Type == WINED3DTSS_ALPHAARG2 || Type == WINED3DTSS_ALPHAARG0);
3737 if (isAlphaArg) {
3738 set_tex_op(iface, TRUE, Stage, This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAOP],
3739 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG1],
3740 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG2],
3741 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG0]);
3742 } else {
3743 set_tex_op(iface, FALSE, Stage, This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP],
3744 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG1],
3745 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG2],
3746 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG0]);
3749 break;
3752 case WINED3DTSS_ADDRESSW :
3754 GLint wrapParm = GL_REPEAT;
3756 switch (Value) {
3757 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3758 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3759 case D3DTADDRESS_BORDER:
3761 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3762 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3763 } else {
3764 /* FIXME: Not right, but better */
3765 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3766 wrapParm = GL_REPEAT;
3769 break;
3770 case D3DTADDRESS_MIRROR:
3772 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3773 wrapParm = GL_MIRRORED_REPEAT_ARB;
3774 } else {
3775 /* Unsupported in OpenGL pre-1.4 */
3776 FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3777 wrapParm = GL_REPEAT;
3780 break;
3781 case D3DTADDRESS_MIRRORONCE:
3783 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3784 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3785 } else {
3786 FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3787 wrapParm = GL_REPEAT;
3790 break;
3792 default:
3793 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3794 wrapParm = GL_REPEAT;
3797 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
3798 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3799 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3801 break;
3803 case WINED3DTSS_TEXCOORDINDEX :
3805 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3807 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
3808 one flag, you can still specify an index value, which the system uses to
3809 determine the texture wrapping mode.
3810 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3811 means use the vertex position (camera-space) as the input texture coordinates
3812 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
3813 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3814 to the TEXCOORDINDEX value */
3816 /**
3817 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3819 switch (Value & 0xFFFF0000) {
3820 case D3DTSS_TCI_PASSTHRU:
3821 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3822 glDisable(GL_TEXTURE_GEN_S);
3823 glDisable(GL_TEXTURE_GEN_T);
3824 glDisable(GL_TEXTURE_GEN_R);
3825 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3826 break;
3828 case D3DTSS_TCI_CAMERASPACEPOSITION:
3829 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3830 as the input texture coordinates for this stage's texture transformation. This
3831 equates roughly to EYE_LINEAR */
3833 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3834 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3835 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3836 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3837 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3839 glMatrixMode(GL_MODELVIEW);
3840 glPushMatrix();
3841 glLoadIdentity();
3842 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3843 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3844 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3845 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3846 glPopMatrix();
3848 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3849 glEnable(GL_TEXTURE_GEN_S);
3850 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3851 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3852 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3853 glEnable(GL_TEXTURE_GEN_T);
3854 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3855 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3856 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3857 glEnable(GL_TEXTURE_GEN_R);
3858 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3859 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3860 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3862 break;
3864 case D3DTSS_TCI_CAMERASPACENORMAL:
3866 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3867 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3868 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3869 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3870 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3871 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3873 glMatrixMode(GL_MODELVIEW);
3874 glPushMatrix();
3875 glLoadIdentity();
3876 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3877 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3878 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3879 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3880 glPopMatrix();
3882 glEnable(GL_TEXTURE_GEN_S);
3883 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3884 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3885 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3886 glEnable(GL_TEXTURE_GEN_T);
3887 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3888 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3889 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3890 glEnable(GL_TEXTURE_GEN_R);
3891 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3892 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3893 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3896 break;
3898 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3900 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3901 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3902 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3903 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3904 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3905 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3907 glMatrixMode(GL_MODELVIEW);
3908 glPushMatrix();
3909 glLoadIdentity();
3910 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3911 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3912 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3913 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3914 glPopMatrix();
3916 glEnable(GL_TEXTURE_GEN_S);
3917 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3918 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3919 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3920 glEnable(GL_TEXTURE_GEN_T);
3921 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3922 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3923 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3924 glEnable(GL_TEXTURE_GEN_R);
3925 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3926 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3927 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3930 break;
3932 /* Unhandled types: */
3933 default:
3934 /* Todo: */
3935 /* ? disable GL_TEXTURE_GEN_n ? */
3936 glDisable(GL_TEXTURE_GEN_S);
3937 glDisable(GL_TEXTURE_GEN_T);
3938 glDisable(GL_TEXTURE_GEN_R);
3939 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
3940 break;
3943 break;
3945 /* Unhandled */
3946 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
3947 set_texture_matrix((float *)&This->stateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
3948 break;
3950 case WINED3DTSS_BUMPENVMAT00 :
3951 case WINED3DTSS_BUMPENVMAT01 :
3952 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
3953 break;
3954 case WINED3DTSS_BUMPENVMAT10 :
3955 case WINED3DTSS_BUMPENVMAT11 :
3956 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
3957 break;
3959 case WINED3DTSS_BUMPENVLSCALE :
3960 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3961 break;
3963 case WINED3DTSS_BUMPENVLOFFSET :
3964 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3965 break;
3967 case WINED3DTSS_RESULTARG :
3968 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3969 break;
3971 default:
3972 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3973 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3976 LEAVE_GL();
3978 return D3D_OK;
3981 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
3982 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3983 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
3984 *pValue = This->updateStateBlock->textureState[Stage][Type];
3985 return D3D_OK;
3988 /*****
3989 * Get / Set Texture
3990 *****/
3991 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
3993 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3994 IWineD3DBaseTexture *oldTexture;
3995 BOOL reapplyStates = TRUE;
3996 DWORD reapplyFlags = 0;
3997 INT oldTextureDimensions = -1;
3998 D3DRESOURCETYPE textureType;
4000 oldTexture = This->updateStateBlock->textures[Stage];
4001 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
4003 /* Reject invalid texture units */
4004 if (Stage >= GL_LIMITS(textures)) {
4005 TRACE("Attempt to access invalid texture rejected\n");
4006 return D3DERR_INVALIDCALL;
4009 This->updateStateBlock->set.textures[Stage] = TRUE;
4010 This->updateStateBlock->changed.textures[Stage] = TRUE;
4011 This->updateStateBlock->textures[Stage] = pTexture;
4013 /* Handle recording of state blocks */
4014 if (This->isRecordingState) {
4015 TRACE("Recording... not performing anything\n");
4016 return D3D_OK;
4019 oldTextureDimensions = This->updateStateBlock->textureDimensions[Stage];
4021 ENTER_GL();
4023 /* Make appropriate texture active */
4024 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
4025 GLACTIVETEXTURE(Stage);
4027 } else if (Stage>0) {
4028 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
4031 /** NOTE: MSDN says that setTexture increases the reference count,
4032 * and the the application nust set the texture back to null (or have a leaky application),
4033 * This means we should pass the refcount upto the parent
4034 *******************************/
4035 if (NULL != oldTexture) {
4037 IUnknown *textureParent;
4038 IWineD3DBaseTexture_GetParent(oldTexture, (IUnknown **)&textureParent);
4039 IUnknown_Release(textureParent);
4040 IUnknown_Release(textureParent); /** NOTE: Twice because GetParent adds a ref **/
4041 oldTexture = NULL;
4045 if (NULL != pTexture) {
4046 IUnknown *textureParent;
4047 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[Stage], (IUnknown **)&textureParent);
4048 /** NOTE: GetParent will increase the ref count for me, I won't clean up untill the texture is set to NULL **/
4050 /* Now setup the texture appropraitly */
4051 textureType = IWineD3DBaseTexture_GetType(pTexture);
4053 if (textureType == D3DRTYPE_TEXTURE) {
4055 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
4056 TRACE("Skipping setting texture as old == new\n");
4057 reapplyStates = FALSE;
4059 } else {
4061 /* Standard 2D texture */
4062 TRACE("Standard 2d texture\n");
4063 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
4065 /* Load up the texture now */
4066 IWineD3DTexture_PreLoad((IWineD3DTexture *) pTexture);
4069 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
4071 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
4072 TRACE("Skipping setting texture as old == new\n");
4073 reapplyStates = FALSE;
4075 } else {
4077 /* Standard 3D (volume) texture */
4078 TRACE("Standard 3d texture\n");
4079 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
4081 /* Load up the texture now */
4082 IWineD3DVolumeTexture_PreLoad((IWineD3DVolumeTexture *) pTexture);
4085 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
4087 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
4088 TRACE("Skipping setting texture as old == new\n");
4089 reapplyStates = FALSE;
4091 } else {
4093 /* Standard Cube texture */
4094 TRACE("Standard Cube texture\n");
4095 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
4097 /* Load up the texture now */
4098 IWineD3DCubeTexture_PreLoad((IWineD3DCubeTexture *) pTexture);
4101 } else {
4102 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dresourcetype(textureType));
4105 } else {
4107 TRACE("Setting to no texture (ie default texture)\n");
4108 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
4109 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
4110 checkGLcall("glBindTexture");
4111 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
4114 /* Disable the old texture binding and enable the new one (unless operations are disabled) */
4115 if (oldTextureDimensions != This->updateStateBlock->textureDimensions[Stage]) {
4117 glDisable(oldTextureDimensions);
4118 checkGLcall("Disable oldTextureDimensions");
4120 if (This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP] != D3DTOP_DISABLE) {
4121 glEnable(This->updateStateBlock->textureDimensions[Stage]);
4122 checkGLcall("glEnable new texture dimensions");
4125 /* If Alpha arg1 is texture then handle the special case when there changes between a
4126 texture and no texture - See comments in set_tex_op */
4127 if ((This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
4128 (((oldTexture == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTexture != NULL))))
4130 reapplyFlags |= REAPPLY_ALPHAOP;
4135 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
4136 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
4137 if (reapplyStates) {
4138 IWineD3DDeviceImpl_SetupTextureStates(iface, Stage, reapplyFlags);
4141 LEAVE_GL();
4142 TRACE("Texture now fully setup\n");
4144 return D3D_OK;
4147 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4148 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4149 TRACE("(%p) : returning %p for stage %ld\n", This, This->updateStateBlock->textures[Stage], Stage);
4150 *ppTexture = (IWineD3DBaseTexture *) This->updateStateBlock->textures[Stage];
4151 if (*ppTexture)
4152 IWineD3DBaseTexture_AddRef(*ppTexture);
4153 return D3D_OK;
4156 /*****
4157 * Get Back Buffer
4158 *****/
4159 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type,
4160 IWineD3DSurface** ppBackBuffer) {
4161 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4162 IWineD3DSwapChain *swapChain;
4163 HRESULT hr;
4165 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4167 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4168 if(hr == D3D_OK){
4169 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4170 IWineD3DSwapChain_Release(swapChain);
4171 }else{
4172 *ppBackBuffer = NULL;
4174 return hr;
4177 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4178 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4179 WARN("(%p) : stub, calling idirect3d for now\n", This);
4180 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4183 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
4184 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4185 IWineD3DSwapChain *swapChain;
4186 HRESULT hr;
4188 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4189 if (hr == D3D_OK) {
4190 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4191 IWineD3DSwapChain_Release(swapChain);
4192 }else{
4193 FIXME("(%p) Error getting display mode\n", This);
4195 return hr;
4197 /*****
4198 * Stateblock related functions
4199 *****/
4201 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4202 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4203 IWineD3DStateBlockImpl *object;
4204 TRACE("(%p)", This);
4205 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4206 if(NULL == object ){
4207 FIXME("(%p)Error allocating memory for stateblock\n", This);
4208 return E_OUTOFMEMORY;
4210 TRACE("(%p) creted object %p\n", This, object);
4211 object->wineD3DDevice= This;
4212 /** FIXME: object->parent = parent; **/
4213 object->parent = NULL;
4214 object->blockType = D3DSBT_ALL;
4215 object->ref = 1;
4216 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
4218 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4219 This->updateStateBlock = object;
4220 This->isRecordingState = TRUE;
4222 TRACE("(%p) recording stateblock %p\n",This , object);
4223 return D3D_OK;
4226 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4227 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4229 if (!This->isRecordingState) {
4230 FIXME("(%p) not recording! returning error\n", This);
4231 *ppStateBlock = NULL;
4232 return D3DERR_INVALIDCALL;
4235 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4236 This->isRecordingState = FALSE;
4237 This->updateStateBlock = This->stateBlock;
4238 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4239 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4240 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4241 return D3D_OK;
4244 /*****
4245 * Scene related functions
4246 *****/
4247 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4248 /* At the moment we have no need for any functionality at the beginning
4249 of a scene */
4250 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4251 TRACE("(%p) : stub\n", This);
4252 return D3D_OK;
4255 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4256 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4257 TRACE("(%p)\n", This);
4258 ENTER_GL();
4259 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4260 glFlush();
4261 checkGLcall("glFlush");
4263 TRACE("End Scene\n");
4264 if(This->renderTarget != NULL){
4266 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4267 IUnknown *targetContainer = NULL;
4268 if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)) {
4269 TRACE("RenderTarget is either standalone of a texture.\n");
4270 /** always dirtify for now. we must find a better way to see that surface have been modified
4271 (Modifications should will only occur via draw-primitive, but we do need better locking
4272 switching to render-to-texture should remove the overhead though.
4274 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4275 IWineD3DBaseTexture_SetDirty((IWineD3DBaseTexture *)targetContainer, TRUE);
4276 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *)targetContainer);
4277 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4278 IUnknown_Release(targetContainer);
4283 LEAVE_GL();
4284 return D3D_OK;
4287 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4288 CONST RECT* pSourceRect, CONST RECT* pDestRect,
4289 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4290 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4291 IWineD3DSwapChain *swapChain = NULL;
4292 int i;
4293 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4295 TRACE("(%p) Presenting the frame\n", This);
4297 for(i = 0 ; i < swapchains ; i ++){
4299 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4300 TRACE("presentinng chain %d, %p\n", i, swapChain);
4301 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4302 IWineD3DSwapChain_Release(swapChain);
4305 return D3D_OK;
4308 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4309 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4310 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4312 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4313 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4314 when the depth-buffer format does not contain stencil buffer information, this method fails. */
4315 GLbitfield glMask = 0;
4316 GLboolean old_ztest;
4317 GLfloat old_z_clear_value;
4318 GLint old_stencil_clear_value;
4319 GLfloat old_color_clear_value[4];
4320 unsigned int i;
4321 CONST D3DRECT* curRect;
4323 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4324 Count, pRects, Flags, Z, Stencil);
4326 ENTER_GL();
4328 glEnable(GL_SCISSOR_TEST);
4329 checkGLcall("glEnable GL_SCISSOR_TEST");
4331 if (Count > 0 && pRects) {
4332 curRect = pRects;
4333 } else {
4334 curRect = NULL;
4337 /* Only set the values up once, as they are not changing */
4338 if (Flags & D3DCLEAR_STENCIL) {
4339 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4340 glClearStencil(Stencil);
4341 checkGLcall("glClearStencil");
4342 glMask = glMask | GL_STENCIL_BUFFER_BIT;
4343 glStencilMask(0xFFFFFFFF);
4346 if (Flags & D3DCLEAR_ZBUFFER) {
4347 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4348 glDepthMask(GL_TRUE);
4349 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4350 glClearDepth(Z);
4351 checkGLcall("glClearDepth");
4352 glMask = glMask | GL_DEPTH_BUFFER_BIT;
4355 if (Flags & D3DCLEAR_TARGET) {
4356 TRACE("Clearing screen with glClear to color %lx\n", Color);
4357 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4358 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
4359 ((Color >> 8) & 0xFF) / 255.0f,
4360 ((Color >> 0) & 0xFF) / 255.0f,
4361 ((Color >> 24) & 0xFF) / 255.0f);
4362 checkGLcall("glClearColor");
4364 /* Clear ALL colors! */
4365 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4366 glMask = glMask | GL_COLOR_BUFFER_BIT;
4369 /* Now process each rect in turn */
4370 for (i = 0; i < Count || i == 0; i++) {
4372 if (curRect) {
4373 /* Note gl uses lower left, width/height */
4374 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4375 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4376 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4377 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4378 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4379 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4380 checkGLcall("glScissor");
4381 } else {
4382 glScissor(This->stateBlock->viewport.X,
4383 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4384 This->stateBlock->viewport.Width,
4385 This->stateBlock->viewport.Height);
4386 checkGLcall("glScissor");
4389 /* Clear the selected rectangle (or full screen) */
4390 glClear(glMask);
4391 checkGLcall("glClear");
4393 /* Step to the next rectangle */
4394 if (curRect) curRect = curRect + sizeof(D3DRECT);
4397 /* Restore the old values (why..?) */
4398 if (Flags & D3DCLEAR_STENCIL) {
4399 glClearStencil(old_stencil_clear_value);
4400 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4402 if (Flags & D3DCLEAR_ZBUFFER) {
4403 glDepthMask(old_ztest);
4404 glClearDepth(old_z_clear_value);
4406 if (Flags & D3DCLEAR_TARGET) {
4407 glClearColor(old_color_clear_value[0],
4408 old_color_clear_value[1],
4409 old_color_clear_value[2],
4410 old_color_clear_value[3]);
4411 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4412 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4413 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4414 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4417 glDisable(GL_SCISSOR_TEST);
4418 checkGLcall("glDisable");
4419 LEAVE_GL();
4421 return D3D_OK;
4424 /*****
4425 * Drawing functions
4426 *****/
4427 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4428 UINT PrimitiveCount) {
4430 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4431 This->stateBlock->streamIsUP = FALSE;
4433 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4434 debug_d3dprimitivetype(PrimitiveType),
4435 StartVertex, PrimitiveCount);
4436 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
4438 return D3D_OK;
4441 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4442 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4443 D3DPRIMITIVETYPE PrimitiveType,
4444 INT baseVIndex, UINT minIndex,
4445 UINT NumVertices,UINT startIndex,UINT primCount) {
4447 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4448 UINT idxStride = 2;
4449 IWineD3DIndexBuffer *pIB;
4450 D3DINDEXBUFFER_DESC IdxBufDsc;
4452 pIB = This->stateBlock->pIndexData;
4453 This->stateBlock->streamIsUP = FALSE;
4455 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d \n", This,
4456 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4457 minIndex, NumVertices, startIndex, baseVIndex, primCount);
4459 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4460 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4461 idxStride = 2;
4462 } else {
4463 idxStride = 4;
4466 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex,
4467 startIndex, idxStride,
4468 ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory,
4469 minIndex);
4471 return D3D_OK;
4474 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4475 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4476 UINT VertexStreamZeroStride) {
4477 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4479 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4480 debug_d3dprimitivetype(PrimitiveType),
4481 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4483 if (This->stateBlock->stream_source[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->stream_source[0]);
4485 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4486 This->stateBlock->stream_source[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4487 This->stateBlock->stream_stride[0] = VertexStreamZeroStride;
4488 This->stateBlock->streamIsUP = TRUE;
4489 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
4490 This->stateBlock->stream_stride[0] = 0;
4491 This->stateBlock->stream_source[0] = NULL;
4493 /*stream zero settings set to null at end, as per the msdn */
4494 return D3D_OK;
4497 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4498 UINT MinVertexIndex,
4499 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
4500 WINED3DFORMAT IndexDataFormat, CONST void* pVertexStreamZeroData,
4501 UINT VertexStreamZeroStride) {
4502 int idxStride;
4503 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4505 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4506 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4507 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData,
4508 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4510 if (This->stateBlock->stream_source[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->stream_source[0]);
4512 if (IndexDataFormat == WINED3DFMT_INDEX16) {
4513 idxStride = 2;
4514 } else {
4515 idxStride = 4;
4518 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4519 This->stateBlock->stream_source[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4520 This->stateBlock->streamIsUP = TRUE;
4521 This->stateBlock->stream_stride[0] = VertexStreamZeroStride;
4523 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, idxStride, pIndexData, MinVertexIndex);
4525 /* stream zero settings set to null at end as per the msdn */
4526 This->stateBlock->stream_source[0] = NULL;
4527 This->stateBlock->stream_stride[0] = 0;
4528 IWineD3DDevice_SetIndices(iface, NULL, 0);
4530 return D3D_OK;
4533 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
4534 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4536 TRACE("(%p) : stub\n", This);
4537 return D3D_OK;
4540 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
4541 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
4542 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
4543 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4545 TRACE("(%p) : stub\n", This);
4546 return D3D_OK;
4548 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface){
4549 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4551 TRACE("(%p) : stub\n", This);
4552 return D3D_OK;
4555 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface){
4556 IWineD3DSwapChain *swapChain;
4557 HRESULT hr;
4558 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4559 if(hr == D3D_OK){
4560 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
4561 IWineD3DSwapChain_Release(swapChain);
4563 return hr;
4566 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4567 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4568 /* return a sensible default */
4569 *pNumPasses = 1;
4570 FIXME("(%p) : stub\n", This);
4571 return D3D_OK;
4574 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4575 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4576 FIXME("(%p) : stub\n", This);
4577 return D3D_OK;
4580 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4581 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4582 FIXME("(%p) : stub\n", This);
4583 return D3D_OK;
4586 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4587 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4588 FIXME("(%p) : stub\n", This);
4589 return D3D_OK;
4592 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4593 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4594 FIXME("(%p) : stub\n", This);
4595 return D3D_OK;
4598 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4599 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4600 FIXME("(%p) : stub\n", This);
4601 return D3D_OK;
4605 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4606 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4607 FIXME("(%p) : stub\n", This);
4608 return FALSE;
4612 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
4613 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4615 pRasterStatus->InVBlank = TRUE;
4616 pRasterStatus->ScanLine = 0;
4617 FIXME("(%p) : stub\n", This);
4618 return D3D_OK;
4622 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4623 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4624 static BOOL showfixmes = TRUE;
4625 if(nSegments != 0.0f){
4626 if( showfixmes){
4627 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4628 showfixmes = FALSE;
4631 return D3D_OK;
4634 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4635 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4636 static BOOL showfixmes = TRUE;
4637 if( showfixmes){
4638 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4639 showfixmes = FALSE;
4641 return 0.0f;
4645 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4646 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4647 FIXME("(%p) : stub\n", This);
4648 return D3D_OK;
4652 /* Implementation details at http://developer.nvidia.com/attach/6494
4654 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
4655 hmm.. no longer supported use
4656 OpenGL evaluators or tessellate surfaces within your application.
4659 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
4660 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo){
4661 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4662 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p) \n", This, Handle, pNumSegs, pRectPatchInfo);
4663 FIXME("(%p) : Stub\n", This);
4664 return D3D_OK;
4668 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
4669 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo){
4670 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4671 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p) \n", This, Handle, pNumSegs, pTriPatchInfo);
4672 FIXME("(%p) : Stub\n", This);
4673 return D3D_OK;
4676 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle){
4677 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4678 TRACE("(%p) Handle(%d)\n", This, Handle);
4679 FIXME("(%p) : Stub\n", This);
4680 return D3D_OK;
4683 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color){
4684 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4686 FIXME("(%p) : stub\n", This);
4687 return D3D_OK;
4690 /* rendertarget and deptth stencil functions */
4691 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget){
4692 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4694 /* FIXME: Implelent RenderTargetIndex >0 */
4695 if(RenderTargetIndex > 0)
4696 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
4698 *ppRenderTarget = (IWineD3DSurface *)This->renderTarget;
4699 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
4700 /* Note inc ref on returned surface */
4701 if(*ppRenderTarget != NULL)
4702 IWineD3DSurface_AddRef(*ppRenderTarget);
4703 return D3D_OK;
4706 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface){
4707 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4708 *ppZStencilSurface = (IWineD3DSurface *)This->depthStencilBuffer;
4709 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
4711 if(*ppZStencilSurface != NULL){
4712 /* Note inc ref on returned surface */
4713 IWineD3DSurface_AddRef(*ppZStencilSurface);
4715 return D3D_OK;
4718 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget){
4719 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4721 FIXME("(%p) : stub\n", This);
4722 return D3D_OK;
4725 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil){
4726 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4728 FIXME("(%p) : stub\n", This);
4729 return D3D_OK;
4732 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
4733 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
4734 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4735 /* TODO: the use of Impl is deprecated. */
4736 /* some basic validation checks */
4737 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
4739 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
4741 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
4742 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
4743 return D3DERR_INVALIDCALL;
4745 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
4746 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
4747 return D3DERR_INVALIDCALL;
4749 /* TODO: make the cursor 'real' */
4751 This->xHotSpot = XHotSpot;
4752 This->yHotSpot = YHotSpot;
4754 return D3D_OK;
4757 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
4758 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4759 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
4761 This->xScreenSpace = XScreenSpace;
4762 This->yScreenSpace = YScreenSpace;
4764 return;
4768 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
4769 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4770 TRACE("(%p) : visible(%d)\n", This, bShow);
4772 This->bCursorVisible = bShow;
4774 return D3D_OK;
4777 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
4778 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4779 FIXME("(%p) : stub\n", This); /* No way of notifying yet! */
4780 return D3D_OK;
4784 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
4785 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4786 /** FIXME: Resource tracking needs to be done,
4787 * The closes we can do to this is set the priorities of all managed textures low
4788 * and then reset them.
4789 ***********************************************************/
4790 FIXME("(%p) : stub\n", This);
4791 return D3D_OK;
4794 HRESULT WINAPI IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
4795 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4796 /** FIXME: Resource trascking needs to be done.
4797 * in effect this pulls all non only default
4798 * textures out of video memory and deletes all glTextures (glDeleteTextures)
4799 * and should clear down the context and set it up according to pPresentationParameters
4800 ***********************************************************/
4801 FIXME("(%p) : stub\n", This);
4802 return D3D_OK;
4805 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs){
4806 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4807 /** FIXME: always true at the moment **/
4808 if(bEnableDialogs == FALSE){
4809 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
4811 return D3D_OK;
4815 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
4816 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4818 FIXME("(%p) : stub\n", This);
4819 /* Setup some reasonable defaults */
4820 pParameters->AdapterOrdinal = 0; /* always for now */
4821 pParameters->DeviceType = D3DDEVTYPE_HAL; /* always for now */
4822 pParameters->hFocusWindow = 0;
4823 pParameters->BehaviorFlags =0;
4824 return D3D_OK;
4827 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
4828 IWineD3DSwapChain *swapchain;
4829 HRESULT hrc = D3D_OK;
4831 TRACE("Relaying to swapchain\n");
4833 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK){
4834 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (D3DGAMMARAMP *)pRamp);
4835 IWineD3DSwapChain_Release(swapchain);
4837 return;
4840 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
4841 IWineD3DSwapChain *swapchain;
4842 HRESULT hrc = D3D_OK;
4844 TRACE("Relaying to swapchain\n");
4846 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK){
4847 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
4848 IWineD3DSwapChain_Release(swapchain);
4850 return;
4853 /**********************************************************
4854 * IWineD3DDevice VTbl follows
4855 **********************************************************/
4857 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
4859 /*** IUnknown methods ***/
4860 IWineD3DDeviceImpl_QueryInterface,
4861 IWineD3DDeviceImpl_AddRef,
4862 IWineD3DDeviceImpl_Release,
4863 /*** IWineD3DDevice methods ***/
4864 IWineD3DDeviceImpl_GetParent,
4865 /*** Creation methods**/
4866 IWineD3DDeviceImpl_CreateVertexBuffer,
4867 IWineD3DDeviceImpl_CreateIndexBuffer,
4868 IWineD3DDeviceImpl_CreateStateBlock,
4869 IWineD3DDeviceImpl_CreateSurface,
4870 IWineD3DDeviceImpl_CreateTexture,
4871 IWineD3DDeviceImpl_CreateVolumeTexture,
4872 IWineD3DDeviceImpl_CreateVolume,
4873 IWineD3DDeviceImpl_CreateCubeTexture,
4874 IWineD3DDeviceImpl_CreateQuery,
4875 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
4876 IWineD3DDeviceImpl_CreateVertexDeclaration,
4877 IWineD3DDeviceImpl_CreateVertexShader,
4878 IWineD3DDeviceImpl_CreatePixelShader,
4880 /*** Odd functions **/
4881 IWineD3DDeviceImpl_EvictManagedResources,
4882 IWineD3DDeviceImpl_GetAvailableTextureMem,
4883 IWineD3DDeviceImpl_GetBackBuffer,
4884 IWineD3DDeviceImpl_GetCreationParameters,
4885 IWineD3DDeviceImpl_GetDeviceCaps,
4886 IWineD3DDeviceImpl_GetDirect3D,
4887 IWineD3DDeviceImpl_GetDisplayMode,
4888 IWineD3DDeviceImpl_GetNumberOfSwapChains,
4889 IWineD3DDeviceImpl_GetRasterStatus,
4890 IWineD3DDeviceImpl_GetSwapChain,
4891 IWineD3DDeviceImpl_Reset,
4892 IWineD3DDeviceImpl_SetDialogBoxMode,
4893 IWineD3DDeviceImpl_SetCursorProperties,
4894 IWineD3DDeviceImpl_SetCursorPosition,
4895 IWineD3DDeviceImpl_ShowCursor,
4896 IWineD3DDeviceImpl_TestCooperativeLevel,
4897 /*** Getters and setters **/
4898 IWineD3DDeviceImpl_SetClipPlane,
4899 IWineD3DDeviceImpl_GetClipPlane,
4900 IWineD3DDeviceImpl_SetClipStatus,
4901 IWineD3DDeviceImpl_GetClipStatus,
4902 IWineD3DDeviceImpl_SetCurrentTexturePalette,
4903 IWineD3DDeviceImpl_GetCurrentTexturePalette,
4904 IWineD3DDeviceImpl_SetDepthStencilSurface,
4905 IWineD3DDeviceImpl_GetDepthStencilSurface,
4906 IWineD3DDeviceImpl_SetFVF,
4907 IWineD3DDeviceImpl_GetFVF,
4908 IWineD3DDeviceImpl_SetGammaRamp,
4909 IWineD3DDeviceImpl_GetGammaRamp,
4910 IWineD3DDeviceImpl_SetIndices,
4911 IWineD3DDeviceImpl_GetIndices,
4912 IWineD3DDeviceImpl_SetLight,
4913 IWineD3DDeviceImpl_GetLight,
4914 IWineD3DDeviceImpl_SetLightEnable,
4915 IWineD3DDeviceImpl_GetLightEnable,
4916 IWineD3DDeviceImpl_SetMaterial,
4917 IWineD3DDeviceImpl_GetMaterial,
4918 IWineD3DDeviceImpl_SetNPatchMode,
4919 IWineD3DDeviceImpl_GetNPatchMode,
4920 IWineD3DDeviceImpl_SetPaletteEntries,
4921 IWineD3DDeviceImpl_GetPaletteEntries,
4922 IWineD3DDeviceImpl_SetPixelShader,
4923 IWineD3DDeviceImpl_GetPixelShader,
4924 IWineD3DDeviceImpl_SetPixelShaderConstantB,
4925 IWineD3DDeviceImpl_GetPixelShaderConstantB,
4926 IWineD3DDeviceImpl_SetPixelShaderConstantI,
4927 IWineD3DDeviceImpl_GetPixelShaderConstantI,
4928 IWineD3DDeviceImpl_SetPixelShaderConstantF,
4929 IWineD3DDeviceImpl_GetPixelShaderConstantF,
4930 IWineD3DDeviceImpl_SetRenderState,
4931 IWineD3DDeviceImpl_GetRenderState,
4932 IWineD3DDeviceImpl_SetRenderTarget,
4933 IWineD3DDeviceImpl_GetRenderTarget,
4934 IWineD3DDeviceImpl_SetSamplerState,
4935 IWineD3DDeviceImpl_GetSamplerState,
4936 IWineD3DDeviceImpl_SetScissorRect,
4937 IWineD3DDeviceImpl_GetScissorRect,
4938 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
4939 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
4940 IWineD3DDeviceImpl_SetStreamSource,
4941 IWineD3DDeviceImpl_GetStreamSource,
4942 IWineD3DDeviceImpl_SetStreamSourceFreq,
4943 IWineD3DDeviceImpl_GetStreamSourceFreq,
4944 IWineD3DDeviceImpl_SetTexture,
4945 IWineD3DDeviceImpl_GetTexture,
4946 IWineD3DDeviceImpl_SetTextureStageState,
4947 IWineD3DDeviceImpl_GetTextureStageState,
4948 IWineD3DDeviceImpl_SetTransform,
4949 IWineD3DDeviceImpl_GetTransform,
4950 IWineD3DDeviceImpl_SetVertexDeclaration,
4951 IWineD3DDeviceImpl_GetVertexDeclaration,
4952 IWineD3DDeviceImpl_SetVertexShader,
4953 IWineD3DDeviceImpl_GetVertexShader,
4954 IWineD3DDeviceImpl_SetVertexShaderConstantB,
4955 IWineD3DDeviceImpl_GetVertexShaderConstantB,
4956 IWineD3DDeviceImpl_SetVertexShaderConstantI,
4957 IWineD3DDeviceImpl_GetVertexShaderConstantI,
4958 IWineD3DDeviceImpl_SetVertexShaderConstantF,
4959 IWineD3DDeviceImpl_GetVertexShaderConstantF,
4960 IWineD3DDeviceImpl_SetViewport,
4961 IWineD3DDeviceImpl_GetViewport,
4962 IWineD3DDeviceImpl_MultiplyTransform,
4963 IWineD3DDeviceImpl_ValidateDevice,
4964 IWineD3DDeviceImpl_ProcessVertices,
4965 /*** State block ***/
4966 IWineD3DDeviceImpl_BeginStateBlock,
4967 IWineD3DDeviceImpl_EndStateBlock,
4968 /*** Scene management ***/
4969 IWineD3DDeviceImpl_BeginScene,
4970 IWineD3DDeviceImpl_EndScene,
4971 IWineD3DDeviceImpl_Present,
4972 IWineD3DDeviceImpl_Clear,
4973 /*** Drawing ***/
4974 IWineD3DDeviceImpl_DrawPrimitive,
4975 IWineD3DDeviceImpl_DrawIndexedPrimitive,
4976 IWineD3DDeviceImpl_DrawPrimitiveUP,
4977 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
4978 IWineD3DDeviceImpl_DrawRectPatch,
4979 IWineD3DDeviceImpl_DrawTriPatch,
4980 IWineD3DDeviceImpl_DeletePatch,
4981 IWineD3DDeviceImpl_ColorFill,
4982 IWineD3DDeviceImpl_UpdateTexture,
4983 IWineD3DDeviceImpl_UpdateSurface,
4984 IWineD3DDeviceImpl_StretchRect,
4985 IWineD3DDeviceImpl_GetRenderTargetData,
4986 IWineD3DDeviceImpl_GetFrontBufferData,
4987 /*** Internal use IWineD3DDevice methods ***/
4988 IWineD3DDeviceImpl_SetupTextureStates