Make all newly created surfces dirty, so that they are loaded properly
[wine/multimedia.git] / dlls / wined3d / device.c
blob6c6db93978e1b33425a8704dfbf4939e47dc7820
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 D3DTSS_COLORARG0: /* Will be picked up when setting color op */
202 case D3DTSS_COLORARG1: /* Will be picked up when setting color op */
203 case D3DTSS_COLORARG2: /* Will be picked up when setting color op */
204 case D3DTSS_ALPHAARG0: /* Will be picked up when setting alpha op */
205 case D3DTSS_ALPHAARG1: /* Will be picked up when setting alpha op */
206 case D3DTSS_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 D3DTSS_COLOROP:
220 case D3DTSS_TEXCOORDINDEX:
221 if (!(Flags == REAPPLY_ALL)) skip=TRUE;
222 break;
224 case D3DTSS_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 /* Note the D3DRS value applies to all textures, but GL has one
250 * per texture, so apply it now ready to be used!
252 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
253 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
254 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
256 TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
259 /**********************************************************
260 * IUnknown parts follows
261 **********************************************************/
263 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
265 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
266 /* FIXME: This needs to extend an IWineD3DBaseObject */
268 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
269 if (IsEqualGUID(riid, &IID_IUnknown)
270 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
271 IUnknown_AddRef(iface);
272 *ppobj = This;
273 return D3D_OK;
276 return E_NOINTERFACE;
279 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
280 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
281 ULONG refCount = InterlockedIncrement(&This->ref);
283 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
284 return refCount;
287 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
288 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
289 ULONG refCount = InterlockedDecrement(&This->ref);
291 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
293 if (!refCount) {
294 /* TODO: Clean up all the surfaces and textures! */
295 /* FIXME: Create targets and state blocks in d3d8 */
296 if (((IWineD3DImpl *)This->wineD3D)->dxVersion > 8) { /*We don't create a state block in d3d8 yet*/
297 /* NOTE: You must release the parent if the objects was created via a callback
298 ** ***************************/
299 int i;
300 IUnknown* swapChainParent;
302 /* Release all of the swapchains, except the implicite swapchain (#0) */
303 for(i = 1; i < This->numberOfSwapChains; i++){
304 /* TODO: don't access swapchains[x] directly! */
305 IWineD3DSwapChain_Release(This->swapchains[i]);
308 if (This->stateBlock != NULL) {
309 IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->stateBlock);
312 if (This->swapchains[0] != NULL) {
313 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release it's parent now */
314 /* TODO: don't access swapchains[x] directly!, check that there are no-more swapchains left for this device! */
315 IWineD3DSwapChain_GetParent(This->swapchains[0], &swapChainParent);
316 IUnknown_Release(swapChainParent); /* once for the get parent */
317 if (IUnknown_Release(swapChainParent) > 0){ /* the second time for when it was created */
318 FIXME("(%p) Something's still holding the implicite swapchain\n",This);
323 IWineD3D_Release(This->wineD3D);
324 HeapFree(GetProcessHeap(), 0, This);
326 return refCount;
329 /**********************************************************
330 * IWineD3DDevice implementation follows
331 **********************************************************/
332 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
333 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
334 *pParent = This->parent;
335 IUnknown_AddRef(This->parent);
336 return D3D_OK;
339 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
340 DWORD FVF, D3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
341 IUnknown *parent) {
342 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
343 IWineD3DVertexBufferImpl *object;
344 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
345 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, D3DRTYPE_VERTEXBUFFER)
347 object->resource.size = Size;
348 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
349 object->FVF = FVF;
351 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
352 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
354 return D3D_OK;
357 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
358 WINED3DFORMAT Format, D3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
359 HANDLE *sharedHandle, IUnknown *parent) {
360 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
361 IWineD3DIndexBufferImpl *object;
362 TRACE("(%p) Creating index buffer\n", This);
364 /* Allocate the storage for the device */
365 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,D3DRTYPE_INDEXBUFFER)
367 object->resource.size = Length;
368 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
370 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
371 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
372 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
374 return D3D_OK;
377 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, D3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
379 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
380 IWineD3DStateBlockImpl *object;
382 D3DCREATEOBJECTINSTANCE(object, StateBlock)
383 object->blockType = Type;
385 /* Special case - Used during initialization to produce a placeholder stateblock
386 so other functions called can update a state block */
387 if (Type == (D3DSTATEBLOCKTYPE) 0) {
388 /* Don't bother increasing the reference count otherwise a device will never
389 be freed due to circular dependencies */
390 return D3D_OK;
393 /* Otherwise, might as well set the whole state block to the appropriate values */
394 IWineD3DDevice_AddRef(iface);
395 memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
396 FIXME("unfinished - needs to set up changed and set attributes\n");
397 return D3D_OK;
401 /* ************************************
402 MSDN:
403 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
405 Discard
406 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
408 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.
410 ******************************** */
412 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) {
413 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
414 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
415 unsigned int pow2Width, pow2Height;
417 TRACE("(%p) Create surface\n",This);
419 /** FIXME: Check ranges on the inputs are valid
420 * MSDN
421 * MultisampleQuality
422 * [in] Quality level. The valid range is between zero and one less than the level
423 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
424 * Passing a larger value returns the error D3DERR_INVALIDCALL. The MultisampleQuality
425 * values of paired render targets, depth stencil surfaces, and the MultiSample type
426 * must all match.
427 *******************************/
431 * TODO: Discard MSDN
432 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
434 * If this flag is set, the contents of the depth stencil buffer will be
435 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
436 * with a different depth surface.
438 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
439 ***************************/
441 if(MultisampleQuality < 0) {
442 FIXME("Invalid multisample level %ld \n", MultisampleQuality);
443 return D3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
446 if(MultisampleQuality > 0){
447 FIXME("MultisampleQuality set to %ld, substituting 0 \n" , MultisampleQuality);
448 MultisampleQuality=0;
451 /* Non-power2 support */
453 /* Find the nearest pow2 match */
454 pow2Width = pow2Height = 1;
455 while (pow2Width < Width) pow2Width <<= 1;
456 while (pow2Height < Height) pow2Height <<= 1;
458 if((pow2Width > Width || pow2Height > Height) && !Usage & D3DUSAGE_RENDERTARGET) {
459 /** TODO: add support for non power two textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
460 FIXME("non-power-two textures unsupported\n");
461 return D3DERR_NOTAVAILABLE;
464 /** TODO: Check against the maximum texture sizes supported by the video card **/
466 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,D3DRTYPE_SURFACE)
467 object->container = (IUnknown*) This;
469 object->currentDesc.Width = Width;
470 object->currentDesc.Height = Height;
471 object->currentDesc.Level = Level;
472 object->currentDesc.MultiSampleType = MultiSample;
473 object->currentDesc.MultiSampleQuality = MultisampleQuality;
474 object->discard = Discard;
475 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
477 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
478 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
479 * space!
480 *********************************/
481 if (Format == WINED3DFMT_DXT1) {
482 /* DXT1 is half byte per pixel */
483 object->resource.size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4)) / 2;
485 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
486 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
487 object->resource.size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4));
488 } else {
489 object->resource.size = (Width * object->bytesPerPixel) * Height;
492 TRACE("Pool %d %d %d %d",Pool, D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM);
494 #if 0
495 /* TODO: Check that we have enough video ram left */
496 if(Pool == D3DPOOL_DEFAULT && IWineD3DDevice_GetAvailableTextureMem(iface) <= object->currentDesc.Size){
497 TRACE("Out of 'bogus' video memory\n");
498 HeapFree(GetProcessHeap(),0,object);
499 *ppSurface = NULL;
500 return D3DERR_OUTOFVIDEOMEMORY;
502 #endif
504 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
505 * this function is too deap to need to care about things like this.
506 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
507 * ****************************************/
508 switch(Pool) {
509 case D3DPOOL_SCRATCH:
510 if(Lockable == FALSE)
511 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
512 which are mutually exclusive, setting lockable to true\n");
513 Lockable = TRUE;
514 break;
515 case D3DPOOL_SYSTEMMEM:
516 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
517 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
518 case D3DPOOL_MANAGED:
519 if(Usage == D3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
520 Usage of DYNAMIC which are mutually exclusive, not doing \
521 anything just telling you.\n");
522 break;
523 case D3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
524 if(!(Usage & D3DUSAGE_DYNAMIC) && !(Usage & D3DUSAGE_RENDERTARGET)
525 && !(Usage && D3DUSAGE_DEPTHSTENCIL ) && Lockable == TRUE)
526 FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
527 break;
528 default:
529 FIXME("(%p) Unknown pool %d\n", This, Pool);
530 break;
533 if (Usage & D3DUSAGE_RENDERTARGET && Pool != D3DPOOL_DEFAULT){
534 FIXME("Trying to create a render target that isn't in the default pool\n");
538 object->locked = FALSE;
539 object->lockable = (WINED3DFMT_D16_LOCKABLE == Format) ? TRUE : Lockable;
540 /* TODO: memory management */
541 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
542 if(object->resource.allocatedMemory == NULL ) {
543 FIXME("Out of memory!\n");
544 HeapFree(GetProcessHeap(),0,object);
545 *ppSurface = NULL;
546 return D3DERR_OUTOFVIDEOMEMORY;
550 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
551 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
552 This, Width, Height, Format, debug_d3dformat(Format),
553 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
554 return D3D_OK;
558 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
559 DWORD Usage, WINED3DFORMAT Format, D3DPOOL Pool,
560 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
561 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
563 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
564 IWineD3DTextureImpl *object;
565 unsigned int i;
566 UINT tmpW;
567 UINT tmpH;
568 HRESULT hr;
570 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) .... \n", This, Width, Height, Levels, Usage);
572 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, D3DRTYPE_TEXTURE);
573 D3DINITILIZEBASETEXTURE(object->baseTexture);
574 object->width = Width;
575 object->height = Height;
577 /* Calculate levels for mip mapping */
578 if (Levels == 0) {
579 TRACE("calculating levels %d\n", object->baseTexture.levels);
580 object->baseTexture.levels++;
581 tmpW = Width;
582 tmpH = Height;
583 while (tmpW > 1 && tmpH > 1) {
584 tmpW = max(1, tmpW >> 1);
585 tmpH = max(1, tmpH >> 1);
586 object->baseTexture.levels++;
588 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
591 /* Generate all the surfaces */
592 tmpW = Width;
593 tmpH = Height;
594 for (i = 0; i < object->baseTexture.levels; i++)
596 /* use the callback to create the texture surface */
597 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
598 if(hr!= D3D_OK){
599 int j;
600 FIXME("Failed to create surface %p \n",object);
601 /* clean up */
602 for(j=0;j<i;j++){
603 IWineD3DSurface_Release(object->surfaces[j]);
605 /* heap free object */
606 HeapFree(GetProcessHeap(),0,object);
608 *ppTexture = NULL;
609 return hr;
612 IWineD3DSurface_SetContainer(object->surfaces[i], (IUnknown *)object);
613 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
614 /* calculate the next mipmap level */
615 tmpW = max(1, tmpW >> 1);
616 tmpH = max(1, tmpH >> 1);
619 TRACE("(%p) : Created texture %p\n", This, object);
620 return D3D_OK;
623 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
624 UINT Width, UINT Height, UINT Depth,
625 UINT Levels, DWORD Usage,
626 WINED3DFORMAT Format, D3DPOOL Pool,
627 IWineD3DVolumeTexture** ppVolumeTexture,
628 HANDLE* pSharedHandle, IUnknown *parent,
629 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
631 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
632 IWineD3DVolumeTextureImpl *object;
633 unsigned int i;
634 UINT tmpW;
635 UINT tmpH;
636 UINT tmpD;
638 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, D3DRTYPE_VOLUMETEXTURE);
639 D3DINITILIZEBASETEXTURE(object->baseTexture);
641 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
642 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
644 object->width = Width;
645 object->height = Height;
646 object->depth = Depth;
648 /* Calculate levels for mip mapping */
649 if (Levels == 0) {
650 object->baseTexture.levels++;
651 tmpW = Width;
652 tmpH = Height;
653 tmpD = Depth;
654 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
655 tmpW = max(1, tmpW >> 1);
656 tmpH = max(1, tmpH >> 1);
657 tmpD = max(1, tmpD >> 1);
658 object->baseTexture.levels++;
660 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
663 /* Generate all the surfaces */
664 tmpW = Width;
665 tmpH = Height;
666 tmpD = Depth;
668 for (i = 0; i < object->baseTexture.levels; i++)
670 /* Create the volume */
671 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
672 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
673 IWineD3DVolume_SetContainer(object->volumes[i], (IUnknown *)object);
675 tmpW = max(1, tmpW >> 1);
676 tmpH = max(1, tmpH >> 1);
677 tmpD = max(1, tmpD >> 1);
680 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
681 TRACE("(%p) : Created volume texture %p\n", This, object);
682 return D3D_OK;
685 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
686 UINT Width, UINT Height, UINT Depth,
687 DWORD Usage,
688 WINED3DFORMAT Format, D3DPOOL Pool,
689 IWineD3DVolume** ppVolume,
690 HANDLE* pSharedHandle, IUnknown *parent) {
692 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
693 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
695 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, D3DRTYPE_VOLUME)
697 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
698 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
700 object->currentDesc.Width = Width;
701 object->currentDesc.Height = Height;
702 object->currentDesc.Depth = Depth;
703 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
705 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
706 object->resource.size = (Width * object->bytesPerPixel) * Height * Depth;
707 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
708 object->lockable = TRUE;
709 object->locked = FALSE;
710 memset(&object->lockedBox, 0, sizeof(D3DBOX));
711 object->dirty = FALSE;
712 return IWineD3DVolume_CleanDirtyBox((IWineD3DVolume *) object);
715 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
716 UINT Levels, DWORD Usage,
717 WINED3DFORMAT Format, D3DPOOL Pool,
718 IWineD3DCubeTexture** ppCubeTexture,
719 HANDLE* pSharedHandle, IUnknown *parent,
720 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
722 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
723 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
724 unsigned int i,j;
725 UINT tmpW;
726 HRESULT hr;
728 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, D3DRTYPE_CUBETEXTURE);
729 D3DINITILIZEBASETEXTURE(object->baseTexture);
731 TRACE("(%p) Create Cube Texture \n", This);
733 object->edgeLength = EdgeLength;
735 /* Calculate levels for mip mapping */
736 if (Levels == 0) {
737 object->baseTexture.levels++;
738 tmpW = EdgeLength;
739 while (tmpW > 1) {
740 tmpW = max(1, tmpW / 2);
741 object->baseTexture.levels++;
743 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
746 /* Generate all the surfaces */
747 tmpW = EdgeLength;
748 for (i = 0; i < object->baseTexture.levels; i++) {
750 /* Create the 6 faces */
751 for (j = 0; j < 6; j++) {
753 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
754 i /* Level */, &object->surfaces[j][i],pSharedHandle);
756 if(hr!= D3D_OK){
757 /* clean up */
758 int k;
759 int l;
760 for (l=0;l<j;l++) {
761 IWineD3DSurface_Release(object->surfaces[j][i]);
763 for (k=0;k<i;k++) {
764 for (l=0;l<6;l++) {
765 IWineD3DSurface_Release(object->surfaces[l][j]);
769 FIXME("(%p) Failed to create surface\n",object);
770 HeapFree(GetProcessHeap(),0,object);
771 *ppCubeTexture = NULL;
772 return hr;
774 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IUnknown *)object);
775 TRACE("Created surface level %d @ %p, \n", i, object->surfaces[j][i]);
777 tmpW = max(1, tmpW >> 1);
780 TRACE("(%p) : Created Cube Texture %p\n", This, object);
781 *ppCubeTexture = (IWineD3DCubeTexture *) object;
782 return D3D_OK;
785 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent){
786 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
787 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
789 if(NULL == ppQuery){
790 /* Just a check to see if we support this type of query */
791 HRESULT hr = D3DERR_NOTAVAILABLE;
792 /* Lie and say everything is good (we can return ok fake data from a stub) */
793 switch(Type){
794 case WINED3DQUERYTYPE_VCACHE:
795 case WINED3DQUERYTYPE_RESOURCEMANAGER:
796 case WINED3DQUERYTYPE_VERTEXSTATS:
797 case WINED3DQUERYTYPE_EVENT:
798 case WINED3DQUERYTYPE_OCCLUSION:
799 case WINED3DQUERYTYPE_TIMESTAMP:
800 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
801 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
802 case WINED3DQUERYTYPE_PIPELINETIMINGS:
803 case WINED3DQUERYTYPE_INTERFACETIMINGS:
804 case WINED3DQUERYTYPE_VERTEXTIMINGS:
805 case WINED3DQUERYTYPE_PIXELTIMINGS:
806 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
807 case WINED3DQUERYTYPE_CACHEUTILIZATION:
808 hr = D3D_OK;
809 break;
810 default:
811 FIXME("(%p) Unhandled query type %d\n",This , Type);
813 FIXME("(%p) : Stub request for query type %d returned %ld\n", This, Type, hr);
814 return hr;
817 D3DCREATEOBJECTINSTANCE(object, Query)
818 object->type = Type;
819 object->extendedData = 0;
820 TRACE("(%p) : Created Query %p\n", This, object);
821 return D3D_OK;
824 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
825 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
826 IUnknown* parent,
827 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
828 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil){
829 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
831 HDC hDc;
832 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
833 int num;
834 XVisualInfo template;
835 GLXContext oldContext;
836 Drawable oldDrawable;
837 HRESULT hr = D3D_OK;
839 TRACE("(%p) : Created Aditional Swap Chain\n", This);
841 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
842 * does a device hold a reference to a swap chain giving them a lifetime of the device
843 * or does the swap chain notify the device of it'd destruction.
844 *******************************/
846 D3DCREATEOBJECTINSTANCE(object, SwapChain)
848 /* Initialize other useful values */
849 object->presentParms.BackBufferCount = 1; /* TODO:? support for gl_aux buffers */
851 /*********************
852 * Lookup the window Handle and the relating X window handle
853 ********************/
855 /* Setup hwnd we are using, plus which display this equates to */
856 object->win_handle = *(pPresentationParameters->hDeviceWindow);
857 if (!object->win_handle) {
858 object->win_handle = This->createParms.hFocusWindow;
861 object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window" );
862 hDc = GetDC(object->win_handle);
863 object->display = get_display(hDc);
864 ReleaseDC(object->win_handle, hDc);
865 TRACE("Using a display of %p %p \n", object->display, hDc);
867 if (NULL == object->display || NULL == hDc) {
868 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
869 return D3DERR_NOTAVAILABLE;
872 if (object->win == 0) {
873 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
874 return D3DERR_NOTAVAILABLE;
877 * Create an opengl context for the display visual
878 * NOTE: the visual is chosen as the window is created and the glcontext cannot
879 * use different properties after that point in time. FIXME: How to handle when requested format
880 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
881 * it chooses is identical to the one already being used!
882 **********************************/
884 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
885 ENTER_GL();
887 /* Create a new context for this swapchain */
888 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
889 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
890 (or the best possible if none is requested) */
891 TRACE("Found x visual ID : %ld\n", template.visualid);
893 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
894 if (NULL == object->visInfo) {
895 ERR("cannot really get XVisual\n");
896 LEAVE_GL();
897 return D3DERR_NOTAVAILABLE;
898 } else {
899 int n, value;
900 /* Write out some debug info about the visual/s */
901 TRACE("Using x visual ID : %ld\n", template.visualid);
902 TRACE(" visual info: %p\n", object->visInfo);
903 TRACE(" num items : %d\n", num);
904 for(n = 0;n < num; n++){
905 TRACE("=====item=====: %d\n", n + 1);
906 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
907 TRACE(" screen : %d\n", object->visInfo[n].screen);
908 TRACE(" depth : %u\n", object->visInfo[n].depth);
909 TRACE(" class : %d\n", object->visInfo[n].class);
910 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
911 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
912 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
913 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
914 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
915 /* log some extra glx info */
916 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
917 TRACE(" gl_aux_buffers : %d\n", value);
918 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
919 TRACE(" gl_buffer_size : %d\n", value);
920 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
921 TRACE(" gl_red_size : %d\n", value);
922 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
923 TRACE(" gl_green_size : %d\n", value);
924 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
925 TRACE(" gl_blue_size : %d\n", value);
926 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
927 TRACE(" gl_alpha_size : %d\n", value);
928 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
929 TRACE(" gl_depth_size : %d\n", value);
930 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
931 TRACE(" gl_stencil_size : %d\n", value);
933 /* Now choose a simila visual ID*/
935 #ifdef USE_CONTEXT_MANAGER
937 /** TODO: use a context mamager **/
938 #endif
941 IWineD3DSwapChain *implSwapChain;
942 if (D3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
943 /* The first time around we create the context that is shared with all other swapchians and render targets */
944 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
945 TRACE("Creating implicite context for vis %p, hwnd %p\n", object->display, object->visInfo);
946 } else {
948 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
949 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
950 /* and create a new context with the implicit swapchains context as the shared context */
951 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
952 IWineD3DSwapChain_Release(implSwapChain);
956 /* Cleanup */
957 XFree(object->visInfo);
958 object->visInfo = NULL;
960 if (NULL == object->glCtx) {
961 ERR("cannot create glxContext\n");
962 LEAVE_GL();
963 return D3DERR_NOTAVAILABLE;
966 LEAVE_GL();
967 if (object->glCtx == NULL) {
968 ERR("Error in context creation !\n");
969 return D3DERR_INVALIDCALL;
970 } else {
971 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
972 object->win_handle, object->glCtx, object->win, object->visInfo);
975 /*********************
976 * Windowed / Fullscreen
977 *******************/
980 * TODO: MSDNsays that we are only allowed one fullscreen swapchain per device,
981 * so we should really check to see if their is a fullscreen swapchain already
982 * I think Windows and X have differnt ideas about fullscreen, does a single head count as full screen?
983 **************************************/
985 if (!*(pPresentationParameters->Windowed)) {
987 DEVMODEW devmode;
988 HDC hdc;
989 int bpp = 0;
991 /* Get info on the current display setup */
992 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
993 bpp = GetDeviceCaps(hdc, BITSPIXEL);
994 DeleteDC(hdc);
996 /* Change the display settings */
997 memset(&devmode, 0, sizeof(DEVMODEW));
998 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
999 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1000 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1001 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1002 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1003 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1005 /* Make popup window */
1006 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1007 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1008 *(pPresentationParameters->BackBufferWidth),
1009 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1015 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1016 * then the corresponding dimension of the client area of the hDeviceWindow
1017 * (or the focus window, if hDeviceWindow is NULL) is taken.
1018 **********************/
1020 if (*(pPresentationParameters->Windowed) &&
1021 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1022 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1024 RECT Rect;
1025 GetClientRect(object->win_handle, &Rect);
1027 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1028 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1029 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1031 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1032 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1033 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1037 /*********************
1038 * finish off parameter initialization
1039 *******************/
1041 /* Put the correct figures in the presentation parameters */
1042 TRACE("Coppying accross presentaion paraneters\n");
1043 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1044 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1045 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1046 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1047 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1048 object->presentParms.MultiSampleQuality = *(pPresentationParameters->MultiSampleQuality);
1049 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1050 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1051 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1052 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1053 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1054 object->presentParms.Flags = *(pPresentationParameters->Flags);
1055 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1056 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1059 /* FIXME: check for any failures */
1060 /*********************
1061 * Create the back, front and stencil buffers
1062 *******************/
1063 TRACE("calling rendertarget CB\n");
1064 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1065 object->presentParms.BackBufferWidth,
1066 object->presentParms.BackBufferHeight,
1067 object->presentParms.BackBufferFormat,
1068 object->presentParms.MultiSampleType,
1069 object->presentParms.MultiSampleQuality,
1070 TRUE /* Lockable */,
1071 &object->frontBuffer,
1072 NULL /* pShared (always null)*/);
1073 if (object->frontBuffer != NULL)
1074 IWineD3DSurface_SetContainer(object->frontBuffer, (IUnknown *)object);
1075 TRACE("calling rendertarget CB\n");
1076 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1077 object->presentParms.BackBufferWidth,
1078 object->presentParms.BackBufferHeight,
1079 object->presentParms.BackBufferFormat,
1080 object->presentParms.MultiSampleType,
1081 object->presentParms.MultiSampleQuality,
1082 TRUE /* Lockable */,
1083 &object->backBuffer,
1084 NULL /* pShared (always null)*/);
1085 if (object->backBuffer != NULL)
1086 IWineD3DSurface_SetContainer(object->backBuffer, (IUnknown *)object);
1088 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1089 if (pPresentationParameters->EnableAutoDepthStencil) {
1090 TRACE("Creating depth stencil buffer\n");
1091 if (This->depthStencilBuffer == NULL ) {
1092 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1093 object->presentParms.BackBufferWidth,
1094 object->presentParms.BackBufferHeight,
1095 object->presentParms.AutoDepthStencilFormat,
1096 object->presentParms.MultiSampleType,
1097 object->presentParms.MultiSampleQuality,
1098 FALSE /* FIXME: Discard */,
1099 &This->depthStencilBuffer,
1100 NULL /* pShared (always null)*/ );
1101 if (This->depthStencilBuffer != NULL)
1102 IWineD3DSurface_SetContainer(This->depthStencilBuffer, (IUnknown *)iface);
1105 /** TODO: A check on width, height and multisample types
1106 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1107 ****************************/
1108 object->wantsDepthStencilBuffer = TRUE;
1109 } else {
1110 object->wantsDepthStencilBuffer = FALSE;
1113 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1116 /*********************
1117 * init the default renderTarget management
1118 *******************/
1119 object->drawable = object->win;
1120 object->render_ctx = object->glCtx;
1122 if(hr == D3D_OK){
1123 /*********************
1124 * Setup some defaults and clear down the buffers
1125 *******************/
1126 ENTER_GL();
1127 /** save current context and drawable **/
1128 oldContext = glXGetCurrentContext();
1129 oldDrawable = glXGetCurrentDrawable();
1131 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1132 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1133 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1135 checkGLcall("glXMakeCurrent");
1137 TRACE("Setting up the screen\n");
1138 /* Clear the screen */
1139 glClearColor(0.0, 0.0, 0.0, 0.0);
1140 checkGLcall("glClearColor");
1141 glClearIndex(0);
1142 glClearDepth(1);
1143 glClearStencil(0xffff);
1145 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1146 checkGLcall("glClear");
1148 glColor3f(1.0, 1.0, 1.0);
1149 checkGLcall("glColor3f");
1151 glEnable(GL_LIGHTING);
1152 checkGLcall("glEnable");
1154 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1155 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1157 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1158 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1160 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1161 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1163 /* switch back to the original context (unless it was zero)*/
1164 if (This->numberOfSwapChains != 0) {
1165 /** TODO: restore the context and drawable **/
1166 glXMakeCurrent(object->display, oldDrawable, oldContext);
1169 LEAVE_GL();
1171 /* TODO: move this off into a linked list implementation! (add swapchain, remove swapchain or something along those lines) */
1172 #if 0
1173 IListOperator *listOperator;
1174 IListStore_CreateListOperator(This->swapchainStore, &listOperator);
1175 IListOperator_Append(listOperator, (void *)object);
1176 IListOperator_Release(listOperator);
1177 #endif
1179 This->swapchains[This->numberOfSwapChains++] = (IWineD3DSwapChain *)object;
1180 TRACE("Set swapchain to %p\n", object);
1181 } else { /* something went wrong so clean up */
1182 IUnknown* bufferParent;
1183 if (object->frontBuffer) {
1184 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1185 IUnknown_Release(bufferParent); /* once for the get parent */
1186 if(IUnknown_Release(bufferParent) > 0){
1187 FIXME("(%p) Something's still holding the front buffer\n",This);
1190 if (object->backBuffer) {
1191 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1192 IUnknown_Release(bufferParent); /* once for the get parent */
1193 if(IUnknown_Release(bufferParent) > 0){
1194 FIXME("(%p) Something's still holding the back buffer\n",This);
1197 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1198 /* Clean up the context */
1199 /* check that we are the current context first (we shouldn't be though!) */
1200 if (object->glCtx != 0) {
1201 if(glXGetCurrentContext() == object->glCtx){
1202 glXMakeCurrent(object->display, None, NULL);
1204 glXDestroyContext(object->display, object->glCtx);
1206 HeapFree(GetProcessHeap(), 0, object);
1209 return hr;
1212 /** NOTE: These are ahead of the other getters and setters to save using a forward declartion **/
1213 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1214 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1216 /* TODO: move over to using a linked list. */
1217 TRACE("(%p) returning %d\n", This, This->numberOfSwapChains);
1218 return This->numberOfSwapChains;
1221 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1222 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1223 TRACE("(%p) : swapchain %d \n", This, iSwapChain);
1225 if(iSwapChain >= IWineD3DDeviceImpl_GetNumberOfSwapChains(iface) || iSwapChain < 0){
1226 *pSwapChain = NULL;
1227 return D3DERR_INVALIDCALL;
1228 }else{
1229 /** TODO: move off to a linked list implementation **/
1230 *pSwapChain = This->swapchains[iSwapChain];
1233 /* TODO: move over to using stores and linked lists. */
1235 IWineD3DSwapChain_AddRef(*pSwapChain);
1236 TRACE("(%p) returning %p\n", This, *pSwapChain);
1237 return D3D_OK;
1240 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters){
1241 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1243 FIXME("(%p) : Stub\n",This);
1244 return D3D_OK;
1248 /*****
1249 * Vertex Declaration
1250 *****/
1251 /* TODO: Get ridd of thease and put the functions in the IWineD3DVertexDeclaration interface */
1252 #if 1
1253 extern HRESULT IWineD3DVertexDeclarationImpl_ParseDeclaration8(IWineD3DDeviceImpl * This, const DWORD* pDecl, IWineD3DVertexDeclarationImpl * object);
1254 extern HRESULT IWineD3DVertexDeclarationImpl_ParseDeclaration9(IWineD3DDeviceImpl * This, const D3DVERTEXELEMENT9* pDecl, IWineD3DVertexDeclarationImpl * object);
1257 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1258 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1259 IWineD3DVertexDeclarationImpl *object = NULL;
1260 HRESULT hr = D3D_OK;
1262 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1263 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1264 object->allFVF = 0;
1266 if (8 == ((IWineD3DImpl *)This->wineD3D)->dxVersion) {
1267 /** @TODO */
1268 hr = IWineD3DVertexDeclarationImpl_ParseDeclaration8(This, (const DWORD*) pDeclaration, object);
1269 } else {
1270 hr = IWineD3DVertexDeclarationImpl_ParseDeclaration9(This, (const D3DVERTEXELEMENT9*) pDeclaration, object);
1273 return hr;
1277 #else
1278 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration8(IWineD3DDevice* iface, const DWORD* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent){
1279 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1280 IWineD3DVertexDeclarationImpl *object = NULL; /* NOTE: impl allowed, this is a create */
1281 HRESULT hr = D3D_OK;
1282 /* TODO: replace impl usage with a call to Version*/
1283 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1284 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1285 object->allFVF = 0;
1286 /* TODO: get ridd of the impl usage, we should only be using interfaces */
1287 hr = IWineD3DVertexDeclarationImpl_ParseDeclaration8(This, pDeclaration, object);
1289 return hr;
1292 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration9(IWineD3DDevice* iface, const D3DVERTEXELEMENT9* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent){
1293 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1294 IWineD3DVertexDeclarationImpl *object = NULL; /* NOTE: impl allowed, this is a create */
1295 HRESULT hr = D3D_OK;
1296 /* TODO: replace impl usage with a call to Version*/
1297 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1298 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1299 object->allFVF = 0;
1300 /* TODO: get ridd of the impl usage, we should only be using interfaces */
1301 hr = IWineD3DVertexDeclarationImpl_ParseDeclaration9(This, pDeclaration, object);
1303 return hr;
1305 #endif
1307 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1308 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DVertexShader** ppVertexShader, IUnknown *parent){
1309 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1310 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1311 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1312 object->function = pFunction;
1313 FIXME("(%p) : STUB: Created Vertex shader %p\n", This, ppVertexShader);
1314 return D3D_OK;
1318 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DPixelShader** ppPixelShader, IUnknown *parent){
1319 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1320 FIXME("(%p) : Stub\n", This);
1321 return D3D_OK;
1324 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice* iface, IWineD3D** ppD3D){
1325 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1326 *ppD3D= This->wineD3D;
1327 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1328 IWineD3D_AddRef(*ppD3D);
1329 return D3D_OK;
1333 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1334 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1335 FIXME("Stub :(%p) returning 64Mib\n", This);
1336 return 64*1024*1024;
1340 /*****
1341 * Get / Set FVF
1342 *****/
1343 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1344 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1346 /* Update the current state block */
1347 This->updateStateBlock->fvf = fvf;
1348 This->updateStateBlock->changed.fvf = TRUE;
1349 This->updateStateBlock->set.fvf = TRUE;
1351 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1353 /* No difference if recording or not */
1354 return D3D_OK;
1356 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1357 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1358 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1359 *pfvf = This->stateBlock->fvf;
1360 return D3D_OK;
1363 /*****
1364 * Get / Set Stream Source
1365 *****/
1366 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1367 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1368 IWineD3DVertexBuffer *oldSrc;
1370 oldSrc = This->stateBlock->stream_source[StreamNumber];
1371 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1373 This->updateStateBlock->changed.stream_source[StreamNumber] = TRUE;
1374 This->updateStateBlock->set.stream_source[StreamNumber] = TRUE;
1375 This->updateStateBlock->stream_stride[StreamNumber] = Stride;
1376 This->updateStateBlock->stream_source[StreamNumber] = pStreamData;
1377 This->updateStateBlock->stream_offset[StreamNumber] = OffsetInBytes;
1379 /* Handle recording of state blocks */
1380 if (This->isRecordingState) {
1381 TRACE("Recording... not performing anything\n");
1382 return D3D_OK;
1385 /* Not recording... */
1386 if (oldSrc != NULL) IWineD3DVertexBuffer_Release(oldSrc);
1387 if (pStreamData != NULL) IWineD3DVertexBuffer_AddRef(pStreamData);
1389 return D3D_OK;
1392 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
1393 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1395 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->stateBlock->stream_source[StreamNumber], This->stateBlock->stream_stride[StreamNumber]);
1396 *pStream = This->stateBlock->stream_source[StreamNumber];
1397 *pStride = This->stateBlock->stream_stride[StreamNumber];
1398 *pOffset = This->stateBlock->stream_offset[StreamNumber];
1399 if (*pStream != NULL) IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
1400 return D3D_OK;
1403 /*Should be quite easy, just an extension of vertexdata
1404 ref...
1405 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1407 The divider is a bit odd though
1409 VertexOffset = StartVertex / Divider * StreamStride +
1410 VertexIndex / Divider * StreamStride + StreamOffset
1413 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider){
1414 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1416 FIXME("(%p) : stub\n", This);
1417 return D3D_OK;
1420 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider){
1421 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1423 FIXME("(%p) : stub\n", This);
1424 return D3D_OK;
1428 /*****
1429 * Get / Set & Multipy Transform
1430 *****/
1431 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1432 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1434 /* Most of this routine, comments included copied from ddraw tree initially: */
1435 TRACE("(%p) : Transform State=%d\n", This, d3dts);
1437 /* Handle recording of state blocks */
1438 if (This->isRecordingState) {
1439 TRACE("Recording... not performing anything\n");
1440 This->updateStateBlock->changed.transform[d3dts] = TRUE;
1441 This->updateStateBlock->set.transform[d3dts] = TRUE;
1442 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1443 return D3D_OK;
1447 * If the new matrix is the same as the current one,
1448 * we cut off any further processing. this seems to be a reasonable
1449 * optimization because as was noticed, some apps (warcraft3 for example)
1450 * tend towards setting the same matrix repeatedly for some reason.
1452 * From here on we assume that the new matrix is different, wherever it matters.
1454 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1455 TRACE("The app is setting the same matrix over again\n");
1456 return D3D_OK;
1457 } else {
1458 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1462 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1463 where ViewMat = Camera space, WorldMat = world space.
1465 In OpenGL, camera and world space is combined into GL_MODELVIEW
1466 matrix. The Projection matrix stay projection matrix.
1469 /* Capture the times we can just ignore the change for now */
1470 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1471 This->modelview_valid = FALSE;
1472 return D3D_OK;
1474 } else if (d3dts == D3DTS_PROJECTION) {
1475 This->proj_valid = FALSE;
1476 return D3D_OK;
1478 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1479 /* Indexed Vertex Blending Matrices 256 -> 511 */
1480 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1481 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1482 return D3D_OK;
1485 /* Now we really are going to have to change a matrix */
1486 ENTER_GL();
1488 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1489 if (d3dts < GL_LIMITS(textures)) {
1490 int tex = d3dts - D3DTS_TEXTURE0;
1491 GLACTIVETEXTURE(tex);
1492 set_texture_matrix((float *)lpmatrix,
1493 This->updateStateBlock->textureState[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
1496 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1497 unsigned int k;
1499 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1500 * NOTE: We have to reset the positions even if the light/plane is not currently
1501 * enabled, since the call to enable it will not reset the position.
1502 * NOTE2: Apparently texture transforms do NOT need reapplying
1505 PLIGHTINFOEL *lightChain = NULL;
1506 This->modelview_valid = FALSE;
1507 This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
1509 glMatrixMode(GL_MODELVIEW);
1510 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1511 glPushMatrix();
1512 glLoadMatrixf((float *)lpmatrix);
1513 checkGLcall("glLoadMatrixf(...)");
1515 /* Reset lights */
1516 lightChain = This->stateBlock->lights;
1517 while (lightChain && lightChain->glIndex != -1) {
1518 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1519 checkGLcall("glLightfv posn");
1520 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1521 checkGLcall("glLightfv dirn");
1522 lightChain = lightChain->next;
1525 /* Reset Clipping Planes if clipping is enabled */
1526 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1527 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1528 checkGLcall("glClipPlane");
1530 glPopMatrix();
1532 } else { /* What was requested!?? */
1533 WARN("invalid matrix specified: %i\n", d3dts);
1536 /* Release lock, all done */
1537 LEAVE_GL();
1538 return D3D_OK;
1541 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1542 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1543 TRACE("(%p) : for Transform State %d\n", This, State);
1544 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1545 return D3D_OK;
1548 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1549 D3DMATRIX *mat = NULL;
1550 D3DMATRIX temp;
1552 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1553 * below means it will be recorded in a state block change, but it
1554 * works regardless where it is recorded.
1555 * If this is found to be wrong, change to StateBlock.
1557 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1558 TRACE("(%p) : For state %u\n", This, State);
1560 if (State < HIGHEST_TRANSFORMSTATE)
1562 mat = &This->updateStateBlock->transforms[State];
1563 } else {
1564 FIXME("Unhandled transform state!!\n");
1567 /* Copied from ddraw code: */
1568 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);
1569 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);
1570 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);
1571 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);
1573 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);
1574 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);
1575 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);
1576 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);
1578 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);
1579 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);
1580 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);
1581 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);
1583 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);
1584 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);
1585 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);
1586 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);
1588 /* Apply change via set transform - will reapply to eg. lights this way */
1589 IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
1590 return D3D_OK;
1593 /*****
1594 * Get / Set Light
1595 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
1596 *****/
1597 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1598 you can reference any indexes you want as long as that number max are enabled at any
1599 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1600 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1601 but when recording, just build a chain pretty much of commands to be replayed. */
1603 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
1604 float rho;
1605 PLIGHTINFOEL *object, *temp;
1607 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1608 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1610 /* If recording state block, just add to end of lights chain */
1611 if (This->isRecordingState) {
1612 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1613 if (NULL == object) {
1614 return D3DERR_OUTOFVIDEOMEMORY;
1616 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1617 object->OriginalIndex = Index;
1618 object->glIndex = -1;
1619 object->changed = TRUE;
1621 /* Add to the END of the chain of lights changes to be replayed */
1622 if (This->updateStateBlock->lights == NULL) {
1623 This->updateStateBlock->lights = object;
1624 } else {
1625 temp = This->updateStateBlock->lights;
1626 while (temp->next != NULL) temp=temp->next;
1627 temp->next = object;
1629 TRACE("Recording... not performing anything more\n");
1630 return D3D_OK;
1633 /* Ok, not recording any longer so do real work */
1634 object = This->stateBlock->lights;
1635 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1637 /* If we didn't find it in the list of lights, time to add it */
1638 if (object == NULL) {
1639 PLIGHTINFOEL *insertAt,*prevPos;
1641 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1642 if (NULL == object) {
1643 return D3DERR_OUTOFVIDEOMEMORY;
1645 object->OriginalIndex = Index;
1646 object->glIndex = -1;
1648 /* Add it to the front of list with the idea that lights will be changed as needed
1649 BUT after any lights currently assigned GL indexes */
1650 insertAt = This->stateBlock->lights;
1651 prevPos = NULL;
1652 while (insertAt != NULL && insertAt->glIndex != -1) {
1653 prevPos = insertAt;
1654 insertAt = insertAt->next;
1657 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1658 This->stateBlock->lights = object;
1659 } else if (insertAt == NULL) { /* End of list */
1660 prevPos->next = object;
1661 object->prev = prevPos;
1662 } else { /* Middle of chain */
1663 if (prevPos == NULL) {
1664 This->stateBlock->lights = object;
1665 } else {
1666 prevPos->next = object;
1668 object->prev = prevPos;
1669 object->next = insertAt;
1670 insertAt->prev = object;
1674 /* Initialze the object */
1675 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,
1676 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1677 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1678 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1679 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1680 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1681 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1683 /* Save away the information */
1684 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1686 switch (pLight->Type) {
1687 case D3DLIGHT_POINT:
1688 /* Position */
1689 object->lightPosn[0] = pLight->Position.x;
1690 object->lightPosn[1] = pLight->Position.y;
1691 object->lightPosn[2] = pLight->Position.z;
1692 object->lightPosn[3] = 1.0f;
1693 object->cutoff = 180.0f;
1694 /* FIXME: Range */
1695 break;
1697 case D3DLIGHT_DIRECTIONAL:
1698 /* Direction */
1699 object->lightPosn[0] = -pLight->Direction.x;
1700 object->lightPosn[1] = -pLight->Direction.y;
1701 object->lightPosn[2] = -pLight->Direction.z;
1702 object->lightPosn[3] = 0.0;
1703 object->exponent = 0.0f;
1704 object->cutoff = 180.0f;
1705 break;
1707 case D3DLIGHT_SPOT:
1708 /* Position */
1709 object->lightPosn[0] = pLight->Position.x;
1710 object->lightPosn[1] = pLight->Position.y;
1711 object->lightPosn[2] = pLight->Position.z;
1712 object->lightPosn[3] = 1.0;
1714 /* Direction */
1715 object->lightDirn[0] = pLight->Direction.x;
1716 object->lightDirn[1] = pLight->Direction.y;
1717 object->lightDirn[2] = pLight->Direction.z;
1718 object->lightDirn[3] = 1.0;
1721 * opengl-ish and d3d-ish spot lights use too different models for the
1722 * light "intensity" as a function of the angle towards the main light direction,
1723 * so we only can approximate very roughly.
1724 * however spot lights are rather rarely used in games (if ever used at all).
1725 * furthermore if still used, probably nobody pays attention to such details.
1727 if (pLight->Falloff == 0) {
1728 rho = 6.28f;
1729 } else {
1730 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1732 if (rho < 0.0001) rho = 0.0001f;
1733 object->exponent = -0.3/log(cos(rho/2));
1734 object->cutoff = pLight->Phi*90/M_PI;
1736 /* FIXME: Range */
1737 break;
1739 default:
1740 FIXME("Unrecognized light type %d\n", pLight->Type);
1743 /* Update the live definitions if the light is currently assigned a glIndex */
1744 if (object->glIndex != -1) {
1745 setup_light(iface, object->glIndex, object);
1747 return D3D_OK;
1750 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
1751 PLIGHTINFOEL *lightInfo = NULL;
1752 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1753 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1755 /* Locate the light in the live lights */
1756 lightInfo = This->stateBlock->lights;
1757 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1759 if (lightInfo == NULL) {
1760 TRACE("Light information requested but light not defined\n");
1761 return D3DERR_INVALIDCALL;
1764 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
1765 return D3D_OK;
1768 /*****
1769 * Get / Set Light Enable
1770 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
1771 *****/
1772 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
1773 PLIGHTINFOEL *lightInfo = NULL;
1774 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1775 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1777 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1778 if (This->isRecordingState) {
1779 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1780 if (NULL == lightInfo) {
1781 return D3DERR_OUTOFVIDEOMEMORY;
1783 lightInfo->OriginalIndex = Index;
1784 lightInfo->glIndex = -1;
1785 lightInfo->enabledChanged = TRUE;
1787 /* Add to the END of the chain of lights changes to be replayed */
1788 if (This->updateStateBlock->lights == NULL) {
1789 This->updateStateBlock->lights = lightInfo;
1790 } else {
1791 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
1792 while (temp->next != NULL) temp=temp->next;
1793 temp->next = lightInfo;
1795 TRACE("Recording... not performing anything more\n");
1796 return D3D_OK;
1799 /* Not recording... So, locate the light in the live lights */
1800 lightInfo = This->stateBlock->lights;
1801 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1803 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1804 if (lightInfo == NULL) {
1805 D3DLIGHT9 lightParms;
1806 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1807 wait until someone confirms it seems to work! */
1808 TRACE("Light enabled requested but light not defined, so defining one!\n");
1809 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1810 lightParms.Diffuse.r = 1.0;
1811 lightParms.Diffuse.g = 1.0;
1812 lightParms.Diffuse.b = 1.0;
1813 lightParms.Diffuse.a = 0.0;
1814 lightParms.Specular.r = 0.0;
1815 lightParms.Specular.g = 0.0;
1816 lightParms.Specular.b = 0.0;
1817 lightParms.Specular.a = 0.0;
1818 lightParms.Ambient.r = 0.0;
1819 lightParms.Ambient.g = 0.0;
1820 lightParms.Ambient.b = 0.0;
1821 lightParms.Ambient.a = 0.0;
1822 lightParms.Position.x = 0.0;
1823 lightParms.Position.y = 0.0;
1824 lightParms.Position.z = 0.0;
1825 lightParms.Direction.x = 0.0;
1826 lightParms.Direction.y = 0.0;
1827 lightParms.Direction.z = 1.0;
1828 lightParms.Range = 0.0;
1829 lightParms.Falloff = 0.0;
1830 lightParms.Attenuation0 = 0.0;
1831 lightParms.Attenuation1 = 0.0;
1832 lightParms.Attenuation2 = 0.0;
1833 lightParms.Theta = 0.0;
1834 lightParms.Phi = 0.0;
1835 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
1837 /* Search for it again! Should be fairly quick as near head of list */
1838 lightInfo = This->stateBlock->lights;
1839 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1840 if (lightInfo == NULL) {
1841 FIXME("Adding default lights has failed dismally\n");
1842 return D3DERR_INVALIDCALL;
1846 /* OK, we now have a light... */
1847 if (Enable == FALSE) {
1849 /* If we are disabling it, check it was enabled, and
1850 still only do something if it has assigned a glIndex (which it should have!) */
1851 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
1852 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1853 ENTER_GL();
1854 glDisable(GL_LIGHT0 + lightInfo->glIndex);
1855 checkGLcall("glDisable GL_LIGHT0+Index");
1856 LEAVE_GL();
1857 } else {
1858 TRACE("Nothing to do as light was not enabled\n");
1860 lightInfo->lightEnabled = FALSE;
1861 } else {
1863 /* We are enabling it. If it is enabled, it's really simple */
1864 if (lightInfo->lightEnabled) {
1865 /* nop */
1866 TRACE("Nothing to do as light was enabled\n");
1868 /* If it already has a glIndex, it's still simple */
1869 } else if (lightInfo->glIndex != -1) {
1870 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
1871 lightInfo->lightEnabled = TRUE;
1872 ENTER_GL();
1873 glEnable(GL_LIGHT0 + lightInfo->glIndex);
1874 checkGLcall("glEnable GL_LIGHT0+Index already setup");
1875 LEAVE_GL();
1877 /* Otherwise got to find space - lights are ordered gl indexes first */
1878 } else {
1879 PLIGHTINFOEL *bsf = NULL;
1880 PLIGHTINFOEL *pos = This->stateBlock->lights;
1881 PLIGHTINFOEL *prev = NULL;
1882 int Index= 0;
1883 int glIndex = -1;
1885 /* Try to minimize changes as much as possible */
1886 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
1888 /* Try to remember which index can be replaced if necessary */
1889 if (bsf==NULL && pos->lightEnabled == FALSE) {
1890 /* Found a light we can replace, save as best replacement */
1891 bsf = pos;
1894 /* Step to next space */
1895 prev = pos;
1896 pos = pos->next;
1897 Index ++;
1900 /* If we have too many active lights, fail the call */
1901 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
1902 FIXME("Program requests too many concurrent lights\n");
1903 return D3DERR_INVALIDCALL;
1905 /* If we have allocated all lights, but not all are enabled,
1906 reuse one which is not enabled */
1907 } else if (Index == This->maxConcurrentLights) {
1908 /* use bsf - Simply swap the new light and the BSF one */
1909 PLIGHTINFOEL *bsfNext = bsf->next;
1910 PLIGHTINFOEL *bsfPrev = bsf->prev;
1912 /* Sort out ends */
1913 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
1914 if (bsf->prev != NULL) {
1915 bsf->prev->next = lightInfo;
1916 } else {
1917 This->stateBlock->lights = lightInfo;
1920 /* If not side by side, lots of chains to update */
1921 if (bsf->next != lightInfo) {
1922 lightInfo->prev->next = bsf;
1923 bsf->next->prev = lightInfo;
1924 bsf->next = lightInfo->next;
1925 bsf->prev = lightInfo->prev;
1926 lightInfo->next = bsfNext;
1927 lightInfo->prev = bsfPrev;
1929 } else {
1930 /* Simple swaps */
1931 bsf->prev = lightInfo;
1932 bsf->next = lightInfo->next;
1933 lightInfo->next = bsf;
1934 lightInfo->prev = bsfPrev;
1938 /* Update states */
1939 glIndex = bsf->glIndex;
1940 bsf->glIndex = -1;
1941 lightInfo->glIndex = glIndex;
1942 lightInfo->lightEnabled = TRUE;
1944 /* Finally set up the light in gl itself */
1945 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
1946 ENTER_GL();
1947 setup_light(iface, glIndex, lightInfo);
1948 glEnable(GL_LIGHT0 + glIndex);
1949 checkGLcall("glEnable GL_LIGHT0 new setup");
1950 LEAVE_GL();
1952 /* If we reached the end of the allocated lights, with space in the
1953 gl lights, setup a new light */
1954 } else if (pos->glIndex == -1) {
1956 /* We reached the end of the allocated gl lights, so already
1957 know the index of the next one! */
1958 glIndex = Index;
1959 lightInfo->glIndex = glIndex;
1960 lightInfo->lightEnabled = TRUE;
1962 /* In an ideal world, it's already in the right place */
1963 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
1964 /* No need to move it */
1965 } else {
1966 /* Remove this light from the list */
1967 lightInfo->prev->next = lightInfo->next;
1968 if (lightInfo->next != NULL) {
1969 lightInfo->next->prev = lightInfo->prev;
1972 /* Add in at appropriate place (inbetween prev and pos) */
1973 lightInfo->prev = prev;
1974 lightInfo->next = pos;
1975 if (prev == NULL) {
1976 This->stateBlock->lights = lightInfo;
1977 } else {
1978 prev->next = lightInfo;
1980 if (pos != NULL) {
1981 pos->prev = lightInfo;
1985 /* Finally set up the light in gl itself */
1986 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
1987 ENTER_GL();
1988 setup_light(iface, glIndex, lightInfo);
1989 glEnable(GL_LIGHT0 + glIndex);
1990 checkGLcall("glEnable GL_LIGHT0 new setup");
1991 LEAVE_GL();
1996 return D3D_OK;
1999 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2001 PLIGHTINFOEL *lightInfo = NULL;
2002 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2003 TRACE("(%p) : for idx(%ld)\n", This, Index);
2005 /* Locate the light in the live lights */
2006 lightInfo = This->stateBlock->lights;
2007 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2009 if (lightInfo == NULL) {
2010 TRACE("Light enabled state requested but light not defined\n");
2011 return D3DERR_INVALIDCALL;
2013 *pEnable = lightInfo->lightEnabled;
2014 return D3D_OK;
2017 /*****
2018 * Get / Set Clip Planes
2019 *****/
2020 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2021 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2022 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2024 /* Validate Index */
2025 if (Index >= GL_LIMITS(clipplanes)) {
2026 TRACE("Application has requested clipplane this device doesn't support\n");
2027 return D3DERR_INVALIDCALL;
2030 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2031 This->updateStateBlock->set.clipplane[Index] = TRUE;
2032 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2033 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2034 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2035 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2037 /* Handle recording of state blocks */
2038 if (This->isRecordingState) {
2039 TRACE("Recording... not performing anything\n");
2040 return D3D_OK;
2043 /* Apply it */
2045 ENTER_GL();
2047 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2048 glMatrixMode(GL_MODELVIEW);
2049 glPushMatrix();
2050 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2052 TRACE("Clipplane [%f,%f,%f,%f]\n",
2053 This->updateStateBlock->clipplane[Index][0],
2054 This->updateStateBlock->clipplane[Index][1],
2055 This->updateStateBlock->clipplane[Index][2],
2056 This->updateStateBlock->clipplane[Index][3]);
2057 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2058 checkGLcall("glClipPlane");
2060 glPopMatrix();
2061 LEAVE_GL();
2063 return D3D_OK;
2066 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2067 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2068 TRACE("(%p) : for idx %ld\n", This, Index);
2070 /* Validate Index */
2071 if (Index >= GL_LIMITS(clipplanes)) {
2072 TRACE("Application has requested clipplane this device doesn't support\n");
2073 return D3DERR_INVALIDCALL;
2076 pPlane[0] = This->stateBlock->clipplane[Index][0];
2077 pPlane[1] = This->stateBlock->clipplane[Index][1];
2078 pPlane[2] = This->stateBlock->clipplane[Index][2];
2079 pPlane[3] = This->stateBlock->clipplane[Index][3];
2080 return D3D_OK;
2083 /*****
2084 * Get / Set Clip Plane Status
2085 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2086 *****/
2087 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2088 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2089 FIXME("(%p) : stub\n", This);
2090 if (NULL == pClipStatus) {
2091 return D3DERR_INVALIDCALL;
2093 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2094 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2095 return D3D_OK;
2098 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2099 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2100 FIXME("(%p) : stub\n", This);
2101 if (NULL == pClipStatus) {
2102 return D3DERR_INVALIDCALL;
2104 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2105 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2106 return D3D_OK;
2109 /*****
2110 * Get / Set Material
2111 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2112 *****/
2113 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2114 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2116 This->updateStateBlock->changed.material = TRUE;
2117 This->updateStateBlock->set.material = TRUE;
2118 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2120 /* Handle recording of state blocks */
2121 if (This->isRecordingState) {
2122 TRACE("Recording... not performing anything\n");
2123 return D3D_OK;
2126 ENTER_GL();
2127 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2128 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2129 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2130 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2131 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2133 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2134 checkGLcall("glMaterialfv");
2135 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2136 checkGLcall("glMaterialfv");
2138 /* Only change material color if specular is enabled, otherwise it is set to black */
2139 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2140 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2141 checkGLcall("glMaterialfv");
2142 } else {
2143 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2144 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2145 checkGLcall("glMaterialfv");
2147 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2148 checkGLcall("glMaterialfv");
2149 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2150 checkGLcall("glMaterialf");
2152 LEAVE_GL();
2153 return D3D_OK;
2156 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2157 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2158 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2159 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2160 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2161 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2162 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2163 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2164 return D3D_OK;
2167 /*****
2168 * Get / Set Indices
2169 *****/
2170 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2171 UINT BaseVertexIndex) {
2172 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2173 IWineD3DIndexBuffer *oldIdxs;
2175 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2176 oldIdxs = This->updateStateBlock->pIndexData;
2178 This->updateStateBlock->changed.indices = TRUE;
2179 This->updateStateBlock->set.indices = TRUE;
2180 This->updateStateBlock->pIndexData = pIndexData;
2181 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2183 /* Handle recording of state blocks */
2184 if (This->isRecordingState) {
2185 TRACE("Recording... not performing anything\n");
2186 return D3D_OK;
2189 if (oldIdxs) IWineD3DIndexBuffer_Release(oldIdxs);
2190 if (pIndexData) IWineD3DIndexBuffer_AddRef(This->stateBlock->pIndexData);
2191 return D3D_OK;
2194 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2195 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2197 *ppIndexData = This->stateBlock->pIndexData;
2199 /* up ref count on ppindexdata */
2200 if (*ppIndexData) IWineD3DIndexBuffer_AddRef(*ppIndexData);
2201 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2203 return D3D_OK;
2206 /*****
2207 * Get / Set Viewports
2208 *****/
2209 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2210 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2212 TRACE("(%p)\n", This);
2213 This->updateStateBlock->changed.viewport = TRUE;
2214 This->updateStateBlock->set.viewport = TRUE;
2215 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2217 /* Handle recording of state blocks */
2218 if (This->isRecordingState) {
2219 TRACE("Recording... not performing anything\n");
2220 return D3D_OK;
2223 ENTER_GL();
2225 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2226 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2228 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2229 checkGLcall("glDepthRange");
2230 /* Note: GL requires lower left, DirectX supplies upper left */
2231 /* TODO: replace usage of renderTarget with context management */
2232 glViewport(pViewport->X, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2233 pViewport->Width, pViewport->Height);
2234 checkGLcall("glViewport");
2236 LEAVE_GL();
2238 return D3D_OK;
2242 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2243 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2244 TRACE("(%p)\n", This);
2245 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2246 return D3D_OK;
2249 /*****
2250 * Get / Set Render States
2251 * TODO: Verify against dx9 definitions
2252 *****/
2253 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2255 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2256 DWORD OldValue = This->stateBlock->renderState[State];
2258 /* Simple way of referring to either a DWORD or a 4 byte float */
2259 union {
2260 DWORD d;
2261 float f;
2262 } tmpvalue;
2264 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2265 This->updateStateBlock->changed.renderState[State] = TRUE;
2266 This->updateStateBlock->set.renderState[State] = TRUE;
2267 This->updateStateBlock->renderState[State] = Value;
2269 /* Handle recording of state blocks */
2270 if (This->isRecordingState) {
2271 TRACE("Recording... not performing anything\n");
2272 return D3D_OK;
2275 ENTER_GL();
2277 switch (State) {
2278 case WINED3DRS_FILLMODE :
2279 switch ((D3DFILLMODE) Value) {
2280 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2281 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2282 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2283 default:
2284 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
2286 checkGLcall("glPolygonMode (fillmode)");
2287 break;
2289 case WINED3DRS_LIGHTING :
2290 if (Value) {
2291 glEnable(GL_LIGHTING);
2292 checkGLcall("glEnable GL_LIGHTING");
2293 } else {
2294 glDisable(GL_LIGHTING);
2295 checkGLcall("glDisable GL_LIGHTING");
2297 break;
2299 case WINED3DRS_ZENABLE :
2300 switch ((D3DZBUFFERTYPE) Value) {
2301 case D3DZB_FALSE:
2302 glDisable(GL_DEPTH_TEST);
2303 checkGLcall("glDisable GL_DEPTH_TEST");
2304 break;
2305 case D3DZB_TRUE:
2306 glEnable(GL_DEPTH_TEST);
2307 checkGLcall("glEnable GL_DEPTH_TEST");
2308 break;
2309 case D3DZB_USEW:
2310 glEnable(GL_DEPTH_TEST);
2311 checkGLcall("glEnable GL_DEPTH_TEST");
2312 FIXME("W buffer is not well handled\n");
2313 break;
2314 default:
2315 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2317 break;
2319 case WINED3DRS_CULLMODE :
2321 /* If we are culling "back faces with clockwise vertices" then
2322 set front faces to be counter clockwise and enable culling
2323 of back faces */
2324 switch ((D3DCULL) Value) {
2325 case D3DCULL_NONE:
2326 glDisable(GL_CULL_FACE);
2327 checkGLcall("glDisable GL_CULL_FACE");
2328 break;
2329 case D3DCULL_CW:
2330 glEnable(GL_CULL_FACE);
2331 checkGLcall("glEnable GL_CULL_FACE");
2332 if (This->renderUpsideDown) {
2333 glFrontFace(GL_CW);
2334 checkGLcall("glFrontFace GL_CW");
2335 } else {
2336 glFrontFace(GL_CCW);
2337 checkGLcall("glFrontFace GL_CCW");
2339 glCullFace(GL_BACK);
2340 break;
2341 case D3DCULL_CCW:
2342 glEnable(GL_CULL_FACE);
2343 checkGLcall("glEnable GL_CULL_FACE");
2344 if (This->renderUpsideDown) {
2345 glFrontFace(GL_CCW);
2346 checkGLcall("glFrontFace GL_CCW");
2347 } else {
2348 glFrontFace(GL_CW);
2349 checkGLcall("glFrontFace GL_CW");
2351 glCullFace(GL_BACK);
2352 break;
2353 default:
2354 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2356 break;
2358 case WINED3DRS_SHADEMODE :
2359 switch ((D3DSHADEMODE) Value) {
2360 case D3DSHADE_FLAT:
2361 glShadeModel(GL_FLAT);
2362 checkGLcall("glShadeModel");
2363 break;
2364 case D3DSHADE_GOURAUD:
2365 glShadeModel(GL_SMOOTH);
2366 checkGLcall("glShadeModel");
2367 break;
2368 case D3DSHADE_PHONG:
2369 FIXME("D3DSHADE_PHONG isn't supported?\n");
2371 LEAVE_GL();
2372 return D3DERR_INVALIDCALL;
2373 default:
2374 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2376 break;
2378 case WINED3DRS_DITHERENABLE :
2379 if (Value) {
2380 glEnable(GL_DITHER);
2381 checkGLcall("glEnable GL_DITHER");
2382 } else {
2383 glDisable(GL_DITHER);
2384 checkGLcall("glDisable GL_DITHER");
2386 break;
2388 case WINED3DRS_ZWRITEENABLE :
2389 if (Value) {
2390 glDepthMask(1);
2391 checkGLcall("glDepthMask");
2392 } else {
2393 glDepthMask(0);
2394 checkGLcall("glDepthMask");
2396 break;
2398 case WINED3DRS_ZFUNC :
2400 int glParm = GL_LESS;
2402 switch ((D3DCMPFUNC) Value) {
2403 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2404 case D3DCMP_LESS: glParm=GL_LESS; break;
2405 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2406 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2407 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2408 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2409 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2410 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2411 default:
2412 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2414 glDepthFunc(glParm);
2415 checkGLcall("glDepthFunc");
2417 break;
2419 case WINED3DRS_AMBIENT :
2421 float col[4];
2422 D3DCOLORTOGLFLOAT4(Value, col);
2423 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2424 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2425 checkGLcall("glLightModel for MODEL_AMBIENT");
2428 break;
2430 case WINED3DRS_ALPHABLENDENABLE :
2431 if (Value) {
2432 glEnable(GL_BLEND);
2433 checkGLcall("glEnable GL_BLEND");
2434 } else {
2435 glDisable(GL_BLEND);
2436 checkGLcall("glDisable GL_BLEND");
2438 break;
2440 case WINED3DRS_SRCBLEND :
2441 case WINED3DRS_DESTBLEND :
2443 int newVal = GL_ZERO;
2444 switch (Value) {
2445 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2446 case D3DBLEND_ONE : newVal = GL_ONE; break;
2447 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2448 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2449 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2450 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2451 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2452 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2453 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2454 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2455 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2457 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2458 This->srcBlend = newVal;
2459 This->dstBlend = newVal;
2460 break;
2462 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2463 This->srcBlend = newVal;
2464 This->dstBlend = newVal;
2465 break;
2466 default:
2467 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2470 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2471 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2472 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2473 glBlendFunc(This->srcBlend, This->dstBlend);
2475 checkGLcall("glBlendFunc");
2477 break;
2479 case WINED3DRS_ALPHATESTENABLE :
2480 if (Value) {
2481 glEnable(GL_ALPHA_TEST);
2482 checkGLcall("glEnable GL_ALPHA_TEST");
2483 } else {
2484 glDisable(GL_ALPHA_TEST);
2485 checkGLcall("glDisable GL_ALPHA_TEST");
2487 break;
2489 case WINED3DRS_ALPHAFUNC :
2491 int glParm = GL_LESS;
2492 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2494 switch ((D3DCMPFUNC) Value) {
2495 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2496 case D3DCMP_LESS: glParm = GL_LESS; break;
2497 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2498 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2499 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2500 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2501 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2502 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2503 default:
2504 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2506 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2507 glAlphaFunc(glParm, ref);
2508 This->alphafunc = glParm;
2509 checkGLcall("glAlphaFunc");
2511 break;
2513 case WINED3DRS_ALPHAREF :
2515 int glParm = This->alphafunc;
2516 float ref = 1.0f;
2518 ref = ((float) Value) / 255.0f;
2519 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2520 glAlphaFunc(glParm, ref);
2521 checkGLcall("glAlphaFunc");
2523 break;
2525 case WINED3DRS_CLIPPLANEENABLE :
2526 case WINED3DRS_CLIPPING :
2528 /* Ensure we only do the changed clip planes */
2529 DWORD enable = 0xFFFFFFFF;
2530 DWORD disable = 0x00000000;
2532 /* If enabling / disabling all */
2533 if (State == WINED3DRS_CLIPPING) {
2534 if (Value) {
2535 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2536 disable = 0x00;
2537 } else {
2538 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2539 enable = 0x00;
2541 } else {
2542 enable = Value & ~OldValue;
2543 disable = ~Value & OldValue;
2546 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2547 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2548 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2549 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2550 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2551 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2553 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2554 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2555 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2556 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2557 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2558 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2560 /** update clipping status */
2561 if (enable) {
2562 This->stateBlock->clip_status.ClipUnion = 0;
2563 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
2564 } else {
2565 This->stateBlock->clip_status.ClipUnion = 0;
2566 This->stateBlock->clip_status.ClipIntersection = 0;
2569 break;
2571 case WINED3DRS_BLENDOP :
2573 int glParm = GL_FUNC_ADD;
2575 switch ((D3DBLENDOP) Value) {
2576 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2577 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2578 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2579 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2580 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2581 default:
2582 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2584 TRACE("glBlendEquation(%x)\n", glParm);
2585 glBlendEquation(glParm);
2586 checkGLcall("glBlendEquation");
2588 break;
2590 case WINED3DRS_TEXTUREFACTOR :
2592 unsigned int i;
2594 /* Note the texture color applies to all textures whereas
2595 GL_TEXTURE_ENV_COLOR applies to active only */
2596 float col[4];
2597 D3DCOLORTOGLFLOAT4(Value, col);
2598 /* Set the default alpha blend color */
2599 glBlendColor(col[0], col[1], col[2], col[3]);
2600 checkGLcall("glBlendColor");
2602 /* And now the default texture color as well */
2603 for (i = 0; i < GL_LIMITS(textures); i++) {
2605 /* Note the D3DRS value applies to all textures, but GL has one
2606 per texture, so apply it now ready to be used! */
2607 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2608 GLACTIVETEXTURE(i);
2609 } else if (i>0) {
2610 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2613 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2614 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2617 break;
2619 case WINED3DRS_SPECULARENABLE :
2621 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2622 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2623 specular color. This is wrong:
2624 Separate specular color means the specular colour is maintained separately, whereas
2625 single color means it is merged in. However in both cases they are being used to
2626 some extent.
2627 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2628 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2629 running 1.4 yet!
2631 if (Value) {
2632 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2633 checkGLcall("glMaterialfv");
2634 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2635 glEnable(GL_COLOR_SUM_EXT);
2636 } else {
2637 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2639 checkGLcall("glEnable(GL_COLOR_SUM)");
2640 } else {
2641 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2643 /* for the case of enabled lighting: */
2644 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2645 checkGLcall("glMaterialfv");
2647 /* for the case of disabled lighting: */
2648 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2649 glDisable(GL_COLOR_SUM_EXT);
2650 } else {
2651 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2653 checkGLcall("glDisable(GL_COLOR_SUM)");
2656 break;
2658 case WINED3DRS_STENCILENABLE :
2659 if (Value) {
2660 glEnable(GL_STENCIL_TEST);
2661 checkGLcall("glEnable GL_STENCIL_TEST");
2662 } else {
2663 glDisable(GL_STENCIL_TEST);
2664 checkGLcall("glDisable GL_STENCIL_TEST");
2666 break;
2668 case WINED3DRS_STENCILFUNC :
2670 int glParm = GL_ALWAYS;
2671 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2672 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2674 switch ((D3DCMPFUNC) Value) {
2675 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2676 case D3DCMP_LESS: glParm=GL_LESS; break;
2677 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2678 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2679 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2680 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2681 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2682 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2683 default:
2684 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2686 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2687 This->stencilfunc = glParm;
2688 glStencilFunc(glParm, ref, mask);
2689 checkGLcall("glStencilFunc");
2691 break;
2693 case WINED3DRS_STENCILREF :
2695 int glParm = This->stencilfunc;
2696 int ref = 0;
2697 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2699 ref = Value;
2700 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2701 glStencilFunc(glParm, ref, mask);
2702 checkGLcall("glStencilFunc");
2704 break;
2706 case WINED3DRS_STENCILMASK :
2708 int glParm = This->stencilfunc;
2709 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2710 GLuint mask = Value;
2712 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2713 glStencilFunc(glParm, ref, mask);
2714 checkGLcall("glStencilFunc");
2716 break;
2718 case WINED3DRS_STENCILFAIL :
2720 GLenum fail ;
2721 GLenum zpass ;
2722 GLenum zfail ;
2724 fail = StencilOp(Value);
2725 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2726 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2727 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2728 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2730 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2731 glStencilOp(fail, zfail, zpass);
2732 checkGLcall("glStencilOp(fail, zfail, zpass);");
2734 break;
2735 case WINED3DRS_STENCILZFAIL :
2737 GLenum fail ;
2738 GLenum zpass ;
2739 GLenum zfail ;
2741 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2742 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2743 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2744 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2745 zfail = StencilOp(Value);
2747 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2748 glStencilOp(fail, zfail, zpass);
2749 checkGLcall("glStencilOp(fail, zfail, zpass);");
2751 break;
2752 case WINED3DRS_STENCILPASS :
2754 GLenum fail ;
2755 GLenum zpass ;
2756 GLenum zfail ;
2758 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2759 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2760 zpass = StencilOp(Value);
2761 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2762 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2764 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2765 glStencilOp(fail, zfail, zpass);
2766 checkGLcall("glStencilOp(fail, zfail, zpass);");
2768 break;
2770 case WINED3DRS_STENCILWRITEMASK :
2772 glStencilMask(Value);
2773 TRACE("glStencilMask(%lu)\n", Value);
2774 checkGLcall("glStencilMask");
2776 break;
2778 case WINED3DRS_FOGENABLE :
2780 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2781 glEnable(GL_FOG);
2782 checkGLcall("glEnable GL_FOG");
2783 } else {
2784 glDisable(GL_FOG);
2785 checkGLcall("glDisable GL_FOG");
2788 break;
2790 case WINED3DRS_RANGEFOGENABLE :
2792 if (Value) {
2793 TRACE("Enabled RANGEFOG");
2794 } else {
2795 TRACE("Disabled RANGEFOG");
2798 break;
2800 case WINED3DRS_FOGCOLOR :
2802 float col[4];
2803 D3DCOLORTOGLFLOAT4(Value, col);
2804 /* Set the default alpha blend color */
2805 glFogfv(GL_FOG_COLOR, &col[0]);
2806 checkGLcall("glFog GL_FOG_COLOR");
2808 break;
2810 case WINED3DRS_FOGTABLEMODE :
2812 glHint(GL_FOG_HINT, GL_NICEST);
2813 switch (Value) {
2814 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2815 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2816 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2817 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2818 default:
2819 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
2821 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2822 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
2825 break;
2827 case WINED3DRS_FOGVERTEXMODE :
2829 glHint(GL_FOG_HINT, GL_FASTEST);
2830 switch (Value) {
2831 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2832 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2833 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2834 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2835 default:
2836 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
2838 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2839 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
2842 break;
2844 case WINED3DRS_FOGSTART :
2846 tmpvalue.d = Value;
2847 glFogfv(GL_FOG_START, &tmpvalue.f);
2848 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2849 TRACE("Fog Start == %f\n", tmpvalue.f);
2851 break;
2853 case WINED3DRS_FOGEND :
2855 tmpvalue.d = Value;
2856 glFogfv(GL_FOG_END, &tmpvalue.f);
2857 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2858 TRACE("Fog End == %f\n", tmpvalue.f);
2860 break;
2862 case WINED3DRS_FOGDENSITY :
2864 tmpvalue.d = Value;
2865 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
2866 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2868 break;
2870 case WINED3DRS_VERTEXBLEND :
2872 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2873 TRACE("Vertex Blending state to %ld\n", Value);
2875 break;
2877 case WINED3DRS_TWEENFACTOR :
2879 tmpvalue.d = Value;
2880 This->updateStateBlock->tween_factor = tmpvalue.f;
2881 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
2883 break;
2885 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
2887 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2889 break;
2891 case WINED3DRS_COLORVERTEX :
2892 case WINED3DRS_DIFFUSEMATERIALSOURCE :
2893 case WINED3DRS_SPECULARMATERIALSOURCE :
2894 case WINED3DRS_AMBIENTMATERIALSOURCE :
2895 case WINED3DRS_EMISSIVEMATERIALSOURCE :
2897 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2899 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
2900 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2901 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
2902 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
2903 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
2904 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
2906 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2907 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2908 Parm = GL_AMBIENT_AND_DIFFUSE;
2909 } else {
2910 Parm = GL_DIFFUSE;
2912 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2913 Parm = GL_AMBIENT;
2914 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2915 Parm = GL_EMISSION;
2916 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2917 Parm = GL_SPECULAR;
2918 } else {
2919 Parm = -1;
2922 if (Parm == -1) {
2923 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2924 } else {
2925 This->tracking_color = NEEDS_TRACKING;
2926 This->tracking_parm = Parm;
2929 } else {
2930 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2933 break;
2935 case WINED3DRS_LINEPATTERN :
2937 union {
2938 DWORD d;
2939 D3DLINEPATTERN lp;
2940 } tmppattern;
2941 tmppattern.d = Value;
2943 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2945 if (tmppattern.lp.wRepeatFactor) {
2946 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2947 checkGLcall("glLineStipple(repeat, linepattern)");
2948 glEnable(GL_LINE_STIPPLE);
2949 checkGLcall("glEnable(GL_LINE_STIPPLE);");
2950 } else {
2951 glDisable(GL_LINE_STIPPLE);
2952 checkGLcall("glDisable(GL_LINE_STIPPLE);");
2955 break;
2957 case WINED3DRS_ZBIAS :
2959 if (Value) {
2960 tmpvalue.d = Value;
2961 TRACE("ZBias value %f\n", tmpvalue.f);
2962 glPolygonOffset(0, -tmpvalue.f);
2963 checkGLcall("glPolygonOffset(0, -Value)");
2964 glEnable(GL_POLYGON_OFFSET_FILL);
2965 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
2966 glEnable(GL_POLYGON_OFFSET_LINE);
2967 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
2968 glEnable(GL_POLYGON_OFFSET_POINT);
2969 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
2970 } else {
2971 glDisable(GL_POLYGON_OFFSET_FILL);
2972 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
2973 glDisable(GL_POLYGON_OFFSET_LINE);
2974 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
2975 glDisable(GL_POLYGON_OFFSET_POINT);
2976 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
2979 break;
2981 case WINED3DRS_NORMALIZENORMALS :
2982 if (Value) {
2983 glEnable(GL_NORMALIZE);
2984 checkGLcall("glEnable(GL_NORMALIZE);");
2985 } else {
2986 glDisable(GL_NORMALIZE);
2987 checkGLcall("glDisable(GL_NORMALIZE);");
2989 break;
2991 case WINED3DRS_POINTSIZE :
2992 tmpvalue.d = Value;
2993 TRACE("Set point size to %f\n", tmpvalue.f);
2994 glPointSize(tmpvalue.f);
2995 checkGLcall("glPointSize(...);");
2996 break;
2998 case WINED3DRS_POINTSIZE_MIN :
2999 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3000 tmpvalue.d = Value;
3001 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3002 checkGLcall("glPointParameterfEXT(...);");
3003 } else {
3004 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3006 break;
3008 case WINED3DRS_POINTSIZE_MAX :
3009 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3010 tmpvalue.d = Value;
3011 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3012 checkGLcall("glPointParameterfEXT(...);");
3013 } else {
3014 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3016 break;
3018 case WINED3DRS_POINTSCALE_A :
3019 case WINED3DRS_POINTSCALE_B :
3020 case WINED3DRS_POINTSCALE_C :
3021 case WINED3DRS_POINTSCALEENABLE :
3023 /* If enabled, supply the parameters, otherwise fall back to defaults */
3024 if (This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3025 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3026 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]);
3027 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]);
3028 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]);
3030 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3031 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3032 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3033 } else {
3034 TRACE("WINED3DRS_POINTSCALEENABLE not supported on this opengl\n");
3036 } else {
3037 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3038 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3039 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3040 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3041 } else {
3042 TRACE("WINED3DRS_POINTSCALEENABLE not supported, but not on either\n");
3045 break;
3048 case WINED3DRS_COLORWRITEENABLE :
3050 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3051 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3052 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3053 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3054 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3055 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3056 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3057 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3058 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3059 checkGLcall("glColorMask(...)");
3061 break;
3063 case WINED3DRS_LOCALVIEWER :
3065 GLint state = (Value) ? 1 : 0;
3066 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3067 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3069 break;
3071 case WINED3DRS_LASTPIXEL :
3073 if (Value) {
3074 TRACE("Last Pixel Drawing Enabled\n");
3075 } else {
3076 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3079 break;
3081 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3083 if (Value) {
3084 TRACE("Software Processing Enabled\n");
3085 } else {
3086 TRACE("Software Processing Disabled\n");
3089 break;
3091 /** not supported */
3092 case WINED3DRS_ZVISIBLE :
3094 LEAVE_GL();
3095 return D3DERR_INVALIDCALL;
3098 /* Unhandled yet...! */
3099 case WINED3DRS_EDGEANTIALIAS :
3100 case WINED3DRS_WRAP0 :
3101 case WINED3DRS_WRAP1 :
3102 case WINED3DRS_WRAP2 :
3103 case WINED3DRS_WRAP3 :
3104 case WINED3DRS_WRAP4 :
3105 case WINED3DRS_WRAP5 :
3106 case WINED3DRS_WRAP6 :
3107 case WINED3DRS_WRAP7 :
3108 case WINED3DRS_POINTSPRITEENABLE :
3109 case WINED3DRS_MULTISAMPLEANTIALIAS :
3110 case WINED3DRS_MULTISAMPLEMASK :
3111 case WINED3DRS_PATCHEDGESTYLE :
3112 case WINED3DRS_PATCHSEGMENTS :
3113 case WINED3DRS_DEBUGMONITORTOKEN :
3114 case WINED3DRS_POSITIONORDER :
3115 case WINED3DRS_NORMALORDER :
3116 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3117 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3118 break;
3119 default:
3120 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3123 LEAVE_GL();
3125 return D3D_OK;
3128 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3129 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3130 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3131 *pValue = This->stateBlock->renderState[State];
3132 return D3D_OK;
3135 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value){
3136 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3138 FIXME("(%p) : stub\n", This);
3139 return D3D_OK;
3142 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value){
3143 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3145 FIXME("(%p) : stub\n", This);
3146 return D3D_OK;
3150 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect){
3151 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3152 ENTER_GL();
3154 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3155 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3156 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3157 LEAVE_GL();
3158 return D3D_OK;
3161 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect){
3162 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3163 GLint scissorBox[4];
3165 ENTER_GL();
3166 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3167 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
3168 pRect->left = scissorBox[1];
3169 pRect->top = scissorBox[2];
3170 pRect->right = scissorBox[1] + scissorBox[3];
3171 pRect->bottom = scissorBox[2] + scissorBox[4];
3172 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3173 LEAVE_GL();
3174 return D3D_OK;
3177 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3178 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3180 TRACE("(%p) : pDecl=%p\n", This, pDecl);
3182 IWineD3DVertexDeclaration_AddRef(pDecl);
3183 if (NULL != This->updateStateBlock->vertexDecl) {
3184 IWineD3DVertexDeclaration_Release(This->updateStateBlock->vertexDecl);
3186 This->updateStateBlock->vertexDecl = pDecl;
3187 This->updateStateBlock->changed.vertexDecl = TRUE;
3188 This->updateStateBlock->set.vertexDecl = TRUE;
3189 return D3D_OK;
3192 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3193 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3195 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3197 *ppDecl = This->updateStateBlock->vertexDecl;
3198 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3199 return D3D_OK;
3202 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader){
3203 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3205 static BOOL showFixmes = TRUE;
3207 This->updateStateBlock->vertexShader = pShader;
3208 This->updateStateBlock->changed.vertexShader = TRUE;
3209 This->updateStateBlock->set.vertexShader = TRUE;
3211 if(pShader == NULL){
3212 /* clear down the shader */
3213 TRACE("Clear down the shader\n");
3214 }else{
3215 if(showFixmes){
3216 FIXME("(%p) : stub pShader(%p)\n", This, pShader);
3217 showFixmes = FALSE;
3221 return D3D_OK;
3223 /** FIXME: refernece counting? **/
3224 if (pShader == NULL) { /* only valid with non FVF shaders */
3225 TRACE_(d3d_shader)("(%p) : FVF Shader, pShader=%p\n", This, pShader);
3226 This->updateStateBlock->vertexShader = NULL;
3227 } else {
3228 TRACE_(d3d_shader)("(%p) : Created shader, pShader=%p\n", This, pShader);
3229 This->updateStateBlock->vertexShader = pShader;
3232 This->updateStateBlock->changed.vertexShader = TRUE;
3233 This->updateStateBlock->set.vertexShader = TRUE;
3235 /* Handle recording of state blocks */
3236 if (This->isRecordingState) {
3237 TRACE("Recording... not performing anything\n");
3238 return D3D_OK;
3241 * TODO: merge HAL shaders context switching from prototype
3243 return D3D_OK;
3247 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader){
3248 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3249 *ppShader = This->stateBlock->vertexShader;
3250 if(*ppShader != NULL)
3251 IWineD3DVertexShader_AddRef(*ppShader);
3252 TRACE("(%p) : returning %p\n", This, *ppShader);
3253 return D3D_OK;
3256 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
3257 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3259 TRACE("(%p) : stub\n", This);
3260 return D3D_OK;
3263 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
3264 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3265 TRACE("(%p) : stub\n", This);
3266 return D3D_OK;
3269 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
3270 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3271 TRACE("(%p) : stub\n", This);
3272 return D3D_OK;
3275 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
3276 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3277 TRACE("(%p) : stub\n", This);
3278 return D3D_OK;
3281 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
3282 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3283 TRACE("(%p) : stub\n", This);
3284 return D3D_OK;
3287 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
3288 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3289 TRACE("(%p) : stub\n", This);
3290 return D3D_OK;
3293 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader){
3294 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3295 TRACE("(%p) : stub\n", This);
3296 return D3D_OK;
3299 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader){
3300 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3301 TRACE("(%p) : stub\n", This);
3302 return D3D_OK;
3306 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
3307 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3308 TRACE("(%p) : stub\n", This);
3309 return D3D_OK;
3312 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
3313 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3314 TRACE("(%p) : stub\n", This);
3315 return D3D_OK;
3318 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
3319 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3320 TRACE("(%p) : stub\n", This);
3321 return D3D_OK;
3324 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
3325 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3326 TRACE("(%p) : stub\n", This);
3327 return D3D_OK;
3330 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
3331 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3332 TRACE("(%p) : stub\n", This);
3333 return D3D_OK;
3336 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
3337 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3338 TRACE("(%p) : stub\n", This);
3339 return D3D_OK;
3342 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags){
3343 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3344 FIXME("(%p) : stub\n", This);
3345 return D3D_OK;
3348 /*****
3349 * Get / Set Texture Stage States
3350 * TODO: Verify against dx9 definitions
3351 *****/
3352 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3353 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3354 union {
3355 float f;
3356 DWORD d;
3357 } tmpvalue;
3359 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3361 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3363 /* Reject invalid texture units */
3364 if (Stage >= GL_LIMITS(textures)) {
3365 TRACE("Attempt to access invalid texture rejected\n");
3366 return D3DERR_INVALIDCALL;
3369 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
3370 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
3371 This->updateStateBlock->textureState[Stage][Type] = Value;
3373 /* Handle recording of state blocks */
3374 if (This->isRecordingState) {
3375 TRACE("Recording... not performing anything\n");
3376 return D3D_OK;
3379 ENTER_GL();
3381 /* Make appropriate texture active */
3382 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3383 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3384 GLACTIVETEXTURE(Stage);
3385 } else if (Stage > 0) {
3386 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3389 switch (Type) {
3391 case D3DTSS_MINFILTER :
3392 case D3DTSS_MIPFILTER :
3394 DWORD ValueMIN = This->stateBlock->textureState[Stage][D3DTSS_MINFILTER];
3395 DWORD ValueMIP = This->stateBlock->textureState[Stage][D3DTSS_MIPFILTER];
3396 GLint realVal = GL_LINEAR;
3398 if (ValueMIN == D3DTEXF_NONE) {
3399 /* Doesn't really make sense - Windows just seems to disable
3400 mipmapping when this occurs */
3401 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3402 realVal = GL_LINEAR;
3403 } else if (ValueMIN == D3DTEXF_POINT) {
3404 /* GL_NEAREST_* */
3405 if (ValueMIP == D3DTEXF_NONE) {
3406 realVal = GL_NEAREST;
3407 } else if (ValueMIP == D3DTEXF_POINT) {
3408 realVal = GL_NEAREST_MIPMAP_NEAREST;
3409 } else if (ValueMIP == D3DTEXF_LINEAR) {
3410 realVal = GL_NEAREST_MIPMAP_LINEAR;
3411 } else {
3412 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3413 realVal = GL_NEAREST;
3415 } else if (ValueMIN == D3DTEXF_LINEAR) {
3416 /* GL_LINEAR_* */
3417 if (ValueMIP == D3DTEXF_NONE) {
3418 realVal = GL_LINEAR;
3419 } else if (ValueMIP == D3DTEXF_POINT) {
3420 realVal = GL_LINEAR_MIPMAP_NEAREST;
3421 } else if (ValueMIP == D3DTEXF_LINEAR) {
3422 realVal = GL_LINEAR_MIPMAP_LINEAR;
3423 } else {
3424 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3425 realVal = GL_LINEAR;
3427 } else if (ValueMIN == D3DTEXF_ANISOTROPIC) {
3428 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3429 if (ValueMIP == D3DTEXF_NONE) {
3430 realVal = GL_LINEAR_MIPMAP_LINEAR;
3431 } else if (ValueMIP == D3DTEXF_POINT) {
3432 realVal = GL_LINEAR_MIPMAP_NEAREST;
3433 } else if (ValueMIP == D3DTEXF_LINEAR) {
3434 realVal = GL_LINEAR_MIPMAP_LINEAR;
3435 } else {
3436 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3437 realVal = GL_LINEAR;
3439 } else {
3440 WARN("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MINFILTER. But not supported by OpenGL driver\n");
3441 realVal = GL_LINEAR;
3443 } else {
3444 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3445 realVal = GL_LINEAR_MIPMAP_LINEAR;
3448 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3449 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3450 checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
3452 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3454 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMIN) {
3455 glTexParameteri(This->stateBlock->textureDimensions[Stage],
3456 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3457 This->stateBlock->textureState[Stage][D3DTSS_MAXANISOTROPY]);
3458 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3461 break;
3463 case D3DTSS_MAGFILTER :
3465 DWORD ValueMAG = This->stateBlock->textureState[Stage][D3DTSS_MAGFILTER];
3466 GLint realVal = GL_NEAREST;
3468 if (ValueMAG == D3DTEXF_POINT) {
3469 realVal = GL_NEAREST;
3470 } else if (ValueMAG == D3DTEXF_LINEAR) {
3471 realVal = GL_LINEAR;
3472 } else if (ValueMAG == D3DTEXF_ANISOTROPIC) {
3473 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3474 realVal = GL_LINEAR;
3475 } else {
3476 FIXME("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MAGFILTER. But not supported by current OpenGL driver\n");
3477 realVal = GL_NEAREST;
3479 } else {
3480 FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", ValueMAG);
3481 realVal = GL_NEAREST;
3483 TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", ValueMAG, realVal);
3484 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, realVal);
3485 checkGLcall("glTexParameter GL_TEXTURE_MAG_FILTER, ...");
3487 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3489 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMAG) {
3490 glTexParameteri(This->stateBlock->textureDimensions[Stage],
3491 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3492 This->stateBlock->textureState[Stage][D3DTSS_MAXANISOTROPY]);
3493 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3496 break;
3498 case D3DTSS_MAXMIPLEVEL :
3501 * Not really the same, but the more apprioprate than nothing
3503 glTexParameteri(This->stateBlock->textureDimensions[Stage],
3504 GL_TEXTURE_BASE_LEVEL,
3505 This->stateBlock->textureState[Stage][D3DTSS_MAXMIPLEVEL]);
3506 checkGLcall("glTexParameteri GL_TEXTURE_BASE_LEVEL ...");
3508 break;
3510 case D3DTSS_MAXANISOTROPY :
3512 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3513 glTexParameteri(This->stateBlock->textureDimensions[Stage],
3514 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3515 This->stateBlock->textureState[Stage][D3DTSS_MAXANISOTROPY]);
3516 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3519 break;
3521 case D3DTSS_MIPMAPLODBIAS :
3523 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3524 tmpvalue.d = Value;
3525 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3526 GL_TEXTURE_LOD_BIAS_EXT,
3527 tmpvalue.f);
3528 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
3531 break;
3533 case D3DTSS_ALPHAOP :
3534 case D3DTSS_COLOROP :
3537 if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
3538 /* TODO: Disable by making this and all later levels disabled */
3539 glDisable(GL_TEXTURE_1D);
3540 checkGLcall("Disable GL_TEXTURE_1D");
3541 glDisable(GL_TEXTURE_2D);
3542 checkGLcall("Disable GL_TEXTURE_2D");
3543 glDisable(GL_TEXTURE_3D);
3544 checkGLcall("Disable GL_TEXTURE_3D");
3545 break; /* Don't bother setting the texture operations */
3546 } else {
3547 /* Enable only the appropriate texture dimension */
3548 if (Type == D3DTSS_COLOROP) {
3549 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3550 glEnable(GL_TEXTURE_1D);
3551 checkGLcall("Enable GL_TEXTURE_1D");
3552 } else {
3553 glDisable(GL_TEXTURE_1D);
3554 checkGLcall("Disable GL_TEXTURE_1D");
3556 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3557 if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
3558 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
3559 checkGLcall("Enable GL_TEXTURE_2D");
3560 } else {
3561 glEnable(GL_TEXTURE_2D);
3562 checkGLcall("Enable GL_TEXTURE_2D");
3564 } else {
3565 glDisable(GL_TEXTURE_2D);
3566 checkGLcall("Disable GL_TEXTURE_2D");
3568 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3569 glEnable(GL_TEXTURE_3D);
3570 checkGLcall("Enable GL_TEXTURE_3D");
3571 } else {
3572 glDisable(GL_TEXTURE_3D);
3573 checkGLcall("Disable GL_TEXTURE_3D");
3575 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3576 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3577 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3578 } else {
3579 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3580 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3584 /* Drop through... (Except disable case) */
3585 case D3DTSS_COLORARG0 :
3586 case D3DTSS_COLORARG1 :
3587 case D3DTSS_COLORARG2 :
3588 case D3DTSS_ALPHAARG0 :
3589 case D3DTSS_ALPHAARG1 :
3590 case D3DTSS_ALPHAARG2 :
3592 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 ||
3593 Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3594 if (isAlphaArg) {
3595 set_tex_op(iface, TRUE, Stage, This->stateBlock->textureState[Stage][D3DTSS_ALPHAOP],
3596 This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG1],
3597 This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG2],
3598 This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG0]);
3599 } else {
3600 set_tex_op(iface, FALSE, Stage, This->stateBlock->textureState[Stage][D3DTSS_COLOROP],
3601 This->stateBlock->textureState[Stage][D3DTSS_COLORARG1],
3602 This->stateBlock->textureState[Stage][D3DTSS_COLORARG2],
3603 This->stateBlock->textureState[Stage][D3DTSS_COLORARG0]);
3606 break;
3609 case D3DTSS_ADDRESSU :
3610 case D3DTSS_ADDRESSV :
3611 case D3DTSS_ADDRESSW :
3613 GLint wrapParm = GL_REPEAT;
3615 switch (Value) {
3616 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3617 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3618 case D3DTADDRESS_BORDER:
3620 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3621 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3622 } else {
3623 /* FIXME: Not right, but better */
3624 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3625 wrapParm = GL_REPEAT;
3628 break;
3629 case D3DTADDRESS_MIRROR:
3631 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3632 wrapParm = GL_MIRRORED_REPEAT_ARB;
3633 } else {
3634 /* Unsupported in OpenGL pre-1.4 */
3635 FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3636 wrapParm = GL_REPEAT;
3639 break;
3640 case D3DTADDRESS_MIRRORONCE:
3642 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3643 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3644 } else {
3645 FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3646 wrapParm = GL_REPEAT;
3649 break;
3651 default:
3652 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3653 wrapParm = GL_REPEAT;
3656 switch (Type) {
3657 case D3DTSS_ADDRESSU:
3658 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
3659 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3660 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3661 break;
3662 case D3DTSS_ADDRESSV:
3663 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
3664 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3665 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3666 break;
3667 case D3DTSS_ADDRESSW:
3668 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
3669 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3670 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3671 break;
3672 default: /* nop */
3673 break; /** stupic compilator */
3676 break;
3678 case D3DTSS_BORDERCOLOR :
3680 float col[4];
3681 D3DCOLORTOGLFLOAT4(Value, col);
3682 TRACE("Setting border color for %x to %lx\n", This->stateBlock->textureDimensions[Stage], Value);
3683 glTexParameterfv(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3684 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3686 break;
3688 case D3DTSS_TEXCOORDINDEX :
3690 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3692 /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include
3693 one flag, you can still specify an index value, which the system uses to
3694 determine the texture wrapping mode.
3695 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3696 means use the vertex position (camera-space) as the input texture coordinates
3697 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
3698 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3699 to the TEXCOORDINDEX value */
3701 /**
3702 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3704 switch (Value & 0xFFFF0000) {
3705 case D3DTSS_TCI_PASSTHRU:
3706 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3707 glDisable(GL_TEXTURE_GEN_S);
3708 glDisable(GL_TEXTURE_GEN_T);
3709 glDisable(GL_TEXTURE_GEN_R);
3710 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3711 break;
3713 case D3DTSS_TCI_CAMERASPACEPOSITION:
3714 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3715 as the input texture coordinates for this stage's texture transformation. This
3716 equates roughly to EYE_LINEAR */
3718 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3719 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3720 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3721 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3722 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3724 glMatrixMode(GL_MODELVIEW);
3725 glPushMatrix();
3726 glLoadIdentity();
3727 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3728 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3729 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3730 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3731 glPopMatrix();
3733 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3734 glEnable(GL_TEXTURE_GEN_S);
3735 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3736 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3737 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3738 glEnable(GL_TEXTURE_GEN_T);
3739 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3740 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3741 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3742 glEnable(GL_TEXTURE_GEN_R);
3743 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3744 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3745 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3747 break;
3749 case D3DTSS_TCI_CAMERASPACENORMAL:
3751 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3752 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3753 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3754 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3755 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3756 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3758 glMatrixMode(GL_MODELVIEW);
3759 glPushMatrix();
3760 glLoadIdentity();
3761 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3762 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3763 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3764 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3765 glPopMatrix();
3767 glEnable(GL_TEXTURE_GEN_S);
3768 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3769 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3770 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3771 glEnable(GL_TEXTURE_GEN_T);
3772 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3773 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3774 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3775 glEnable(GL_TEXTURE_GEN_R);
3776 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3777 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3778 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3781 break;
3783 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3785 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3786 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3787 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3788 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3789 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3790 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3792 glMatrixMode(GL_MODELVIEW);
3793 glPushMatrix();
3794 glLoadIdentity();
3795 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3796 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3797 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3798 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3799 glPopMatrix();
3801 glEnable(GL_TEXTURE_GEN_S);
3802 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3803 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3804 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3805 glEnable(GL_TEXTURE_GEN_T);
3806 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3807 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3808 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3809 glEnable(GL_TEXTURE_GEN_R);
3810 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3811 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3812 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3815 break;
3817 /* Unhandled types: */
3818 default:
3819 /* Todo: */
3820 /* ? disable GL_TEXTURE_GEN_n ? */
3821 glDisable(GL_TEXTURE_GEN_S);
3822 glDisable(GL_TEXTURE_GEN_T);
3823 glDisable(GL_TEXTURE_GEN_R);
3824 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
3825 break;
3828 break;
3830 /* Unhandled */
3831 case D3DTSS_TEXTURETRANSFORMFLAGS :
3832 set_texture_matrix((float *)&This->stateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
3833 break;
3835 case D3DTSS_BUMPENVMAT00 :
3836 case D3DTSS_BUMPENVMAT01 :
3837 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
3838 break;
3839 case D3DTSS_BUMPENVMAT10 :
3840 case D3DTSS_BUMPENVMAT11 :
3841 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
3842 break;
3844 case D3DTSS_BUMPENVLSCALE :
3845 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3846 break;
3848 case D3DTSS_BUMPENVLOFFSET :
3849 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3850 break;
3852 case D3DTSS_RESULTARG :
3853 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3854 break;
3856 default:
3857 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3858 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3861 LEAVE_GL();
3863 return D3D_OK;
3866 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
3867 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3868 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
3869 *pValue = This->updateStateBlock->textureState[Stage][Type];
3870 return D3D_OK;
3873 /*****
3874 * Get / Set Texture
3875 *****/
3876 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
3878 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3879 IWineD3DBaseTexture *oldTexture;
3880 BOOL reapplyStates = TRUE;
3881 DWORD reapplyFlags = 0;
3882 INT oldTextureDimensions = -1;
3883 D3DRESOURCETYPE textureType;
3885 oldTexture = This->updateStateBlock->textures[Stage];
3886 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3888 /* Reject invalid texture units */
3889 if (Stage >= GL_LIMITS(textures)) {
3890 TRACE("Attempt to access invalid texture rejected\n");
3891 return D3DERR_INVALIDCALL;
3894 This->updateStateBlock->set.textures[Stage] = TRUE;
3895 This->updateStateBlock->changed.textures[Stage] = TRUE;
3896 This->updateStateBlock->textures[Stage] = pTexture;
3898 /* Handle recording of state blocks */
3899 if (This->isRecordingState) {
3900 TRACE("Recording... not performing anything\n");
3901 return D3D_OK;
3904 oldTextureDimensions = This->updateStateBlock->textureDimensions[Stage];
3906 ENTER_GL();
3908 /* Make appropriate texture active */
3909 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3910 GLACTIVETEXTURE(Stage);
3912 } else if (Stage>0) {
3913 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3916 /** NOTE: MSDN says that setTexture increases the reference count,
3917 * and the the application nust set the texture back to null (or have a leaky application),
3918 * This means we should pass the refcount upto the parent
3919 *******************************/
3920 if (NULL != oldTexture) {
3922 IUnknown *textureParent;
3923 IWineD3DBaseTexture_GetParent(oldTexture, (IUnknown **)&textureParent);
3924 IUnknown_Release(textureParent);
3925 IUnknown_Release(textureParent); /** NOTE: Twice because GetParent adds a ref **/
3926 oldTexture = NULL;
3930 if (NULL != pTexture) {
3931 IUnknown *textureParent;
3932 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[Stage], (IUnknown **)&textureParent);
3933 /** NOTE: GetParent will increase the ref count for me, I won't clean up untill the texture is set to NULL **/
3935 /* Now setup the texture appropraitly */
3936 textureType = IWineD3DBaseTexture_GetType(pTexture);
3938 if (textureType == D3DRTYPE_TEXTURE) {
3940 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
3941 TRACE("Skipping setting texture as old == new\n");
3942 reapplyStates = FALSE;
3944 } else {
3946 /* Standard 2D texture */
3947 TRACE("Standard 2d texture\n");
3948 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3950 /* Load up the texture now */
3951 IWineD3DTexture_PreLoad((IWineD3DTexture *) pTexture);
3954 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3956 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
3957 TRACE("Skipping setting texture as old == new\n");
3958 reapplyStates = FALSE;
3960 } else {
3962 /* Standard 3D (volume) texture */
3963 TRACE("Standard 3d texture\n");
3964 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3966 /* Load up the texture now */
3967 IWineD3DVolumeTexture_PreLoad((IWineD3DVolumeTexture *) pTexture);
3970 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
3972 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
3973 TRACE("Skipping setting texture as old == new\n");
3974 reapplyStates = FALSE;
3976 } else {
3978 /* Standard Cube texture */
3979 TRACE("Standard Cube texture\n");
3980 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
3982 /* Load up the texture now */
3983 IWineD3DCubeTexture_PreLoad((IWineD3DCubeTexture *) pTexture);
3986 } else {
3987 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dresourcetype(textureType));
3990 } else {
3992 TRACE("Setting to no texture (ie default texture)\n");
3993 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3994 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3995 checkGLcall("glBindTexture");
3996 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3999 /* Disable the old texture binding and enable the new one (unless operations are disabled) */
4000 if (oldTextureDimensions != This->updateStateBlock->textureDimensions[Stage]) {
4002 glDisable(oldTextureDimensions);
4003 checkGLcall("Disable oldTextureDimensions");
4005 if (This->stateBlock->textureState[Stage][D3DTSS_COLOROP] != D3DTOP_DISABLE) {
4006 glEnable(This->updateStateBlock->textureDimensions[Stage]);
4007 checkGLcall("glEnable new texture dimensions");
4010 /* If Alpha arg1 is texture then handle the special case when there changes between a
4011 texture and no texture - See comments in set_tex_op */
4012 if ((This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
4013 (((oldTexture == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTexture != NULL))))
4015 reapplyFlags |= REAPPLY_ALPHAOP;
4020 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
4021 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
4022 if (reapplyStates) {
4023 IWineD3DDeviceImpl_SetupTextureStates(iface, Stage, reapplyFlags);
4026 LEAVE_GL();
4027 TRACE("Texture now fully setup\n");
4029 return D3D_OK;
4032 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4033 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4034 TRACE("(%p) : returning %p for stage %ld\n", This, This->updateStateBlock->textures[Stage], Stage);
4035 *ppTexture = (IWineD3DBaseTexture *) This->updateStateBlock->textures[Stage];
4036 if (*ppTexture)
4037 IWineD3DBaseTexture_AddRef(*ppTexture);
4038 return D3D_OK;
4041 /*****
4042 * Get Back Buffer
4043 *****/
4044 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type,
4045 IWineD3DSurface** ppBackBuffer) {
4046 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4047 IWineD3DSwapChain *swapChain;
4048 HRESULT hr;
4050 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4052 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4053 if(hr == D3D_OK){
4054 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4055 IWineD3DSwapChain_Release(swapChain);
4056 }else{
4057 *ppBackBuffer = NULL;
4059 return hr;
4062 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4063 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4064 WARN("(%p) : stub, calling idirect3d for now\n", This);
4065 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4068 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
4069 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4070 IWineD3DSwapChain *swapChain;
4071 HRESULT hr;
4073 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4074 if (hr == D3D_OK) {
4075 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4076 IWineD3DSwapChain_Release(swapChain);
4077 }else{
4078 FIXME("(%p) Error getting display mode\n", This);
4080 return hr;
4082 /*****
4083 * Stateblock related functions
4084 *****/
4086 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4087 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4088 IWineD3DStateBlockImpl *object;
4089 TRACE("(%p)", This);
4090 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4091 if(NULL == object ){
4092 FIXME("(%p)Error allocating memory for stateblock\n", This);
4093 return E_OUTOFMEMORY;
4095 TRACE("(%p) creted object %p\n", This, object);
4096 object->wineD3DDevice= This;
4097 /** FIXME: object->parent = parent; **/
4098 object->parent = NULL;
4099 object->blockType = D3DSBT_ALL;
4100 object->ref = 1;
4101 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
4103 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4104 This->updateStateBlock = object;
4105 This->isRecordingState = TRUE;
4107 TRACE("(%p) recording stateblock %p\n",This , object);
4108 return D3D_OK;
4111 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4112 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4114 if (!This->isRecordingState) {
4115 FIXME("(%p) not recording! returning error\n", This);
4116 *ppStateBlock = NULL;
4117 return D3DERR_INVALIDCALL;
4120 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4121 This->isRecordingState = FALSE;
4122 This->updateStateBlock = This->stateBlock;
4123 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4124 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4125 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4126 return D3D_OK;
4129 /*****
4130 * Scene related functions
4131 *****/
4132 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4133 /* At the moment we have no need for any functionality at the beginning
4134 of a scene */
4135 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4136 TRACE("(%p) : stub\n", This);
4137 return D3D_OK;
4140 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4141 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4142 TRACE("(%p)\n", This);
4143 ENTER_GL();
4144 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4145 glFlush();
4146 checkGLcall("glFlush");
4148 TRACE("End Scene\n");
4149 if(This->renderTarget != NULL){
4151 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4152 IUnknown *targetContainer = NULL;
4153 if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)) {
4154 TRACE("RenderTarget is either standalone of a texture.\n");
4155 /** always dirtify for now. we must find a better way to see that surface have been modified
4156 (Modifications should will only occur via draw-primitive, but we do need better locking
4157 switching to render-to-texture should remove the overhead though.
4159 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4160 IWineD3DBaseTexture_SetDirty((IWineD3DBaseTexture *)targetContainer, TRUE);
4161 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *)targetContainer);
4162 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4163 IUnknown_Release(targetContainer);
4168 LEAVE_GL();
4169 return D3D_OK;
4172 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4173 CONST RECT* pSourceRect, CONST RECT* pDestRect,
4174 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4175 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4176 IWineD3DSwapChain *swapChain = NULL;
4177 int i;
4178 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4180 TRACE("(%p) Presenting the frame\n", This);
4182 for(i = 0 ; i < swapchains ; i ++){
4184 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4185 TRACE("presentinng chain %d, %p\n", i, swapChain);
4186 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4187 IWineD3DSwapChain_Release(swapChain);
4190 return D3D_OK;
4193 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4194 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4195 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4197 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4198 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4199 when the depth-buffer format does not contain stencil buffer information, this method fails. */
4200 GLbitfield glMask = 0;
4201 GLboolean old_ztest;
4202 GLfloat old_z_clear_value;
4203 GLint old_stencil_clear_value;
4204 GLfloat old_color_clear_value[4];
4205 unsigned int i;
4206 CONST D3DRECT* curRect;
4208 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4209 Count, pRects, Flags, Z, Stencil);
4211 ENTER_GL();
4213 glEnable(GL_SCISSOR_TEST);
4214 checkGLcall("glEnable GL_SCISSOR_TEST");
4216 if (Count > 0 && pRects) {
4217 curRect = pRects;
4218 } else {
4219 curRect = NULL;
4222 /* Only set the values up once, as they are not changing */
4223 if (Flags & D3DCLEAR_STENCIL) {
4224 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4225 glClearStencil(Stencil);
4226 checkGLcall("glClearStencil");
4227 glMask = glMask | GL_STENCIL_BUFFER_BIT;
4228 glStencilMask(0xFFFFFFFF);
4231 if (Flags & D3DCLEAR_ZBUFFER) {
4232 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4233 glDepthMask(GL_TRUE);
4234 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4235 glClearDepth(Z);
4236 checkGLcall("glClearDepth");
4237 glMask = glMask | GL_DEPTH_BUFFER_BIT;
4240 if (Flags & D3DCLEAR_TARGET) {
4241 TRACE("Clearing screen with glClear to color %lx\n", Color);
4242 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4243 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
4244 ((Color >> 8) & 0xFF) / 255.0f,
4245 ((Color >> 0) & 0xFF) / 255.0f,
4246 ((Color >> 24) & 0xFF) / 255.0f);
4247 checkGLcall("glClearColor");
4249 /* Clear ALL colors! */
4250 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4251 glMask = glMask | GL_COLOR_BUFFER_BIT;
4254 /* Now process each rect in turn */
4255 for (i = 0; i < Count || i == 0; i++) {
4257 if (curRect) {
4258 /* Note gl uses lower left, width/height */
4259 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4260 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4261 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4262 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4263 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4264 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4265 checkGLcall("glScissor");
4266 } else {
4267 glScissor(This->stateBlock->viewport.X,
4268 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4269 This->stateBlock->viewport.Width,
4270 This->stateBlock->viewport.Height);
4271 checkGLcall("glScissor");
4274 /* Clear the selected rectangle (or full screen) */
4275 glClear(glMask);
4276 checkGLcall("glClear");
4278 /* Step to the next rectangle */
4279 if (curRect) curRect = curRect + sizeof(D3DRECT);
4282 /* Restore the old values (why..?) */
4283 if (Flags & D3DCLEAR_STENCIL) {
4284 glClearStencil(old_stencil_clear_value);
4285 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4287 if (Flags & D3DCLEAR_ZBUFFER) {
4288 glDepthMask(old_ztest);
4289 glClearDepth(old_z_clear_value);
4291 if (Flags & D3DCLEAR_TARGET) {
4292 glClearColor(old_color_clear_value[0],
4293 old_color_clear_value[1],
4294 old_color_clear_value[2],
4295 old_color_clear_value[3]);
4296 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4297 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4298 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4299 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4302 glDisable(GL_SCISSOR_TEST);
4303 checkGLcall("glDisable");
4304 LEAVE_GL();
4306 return D3D_OK;
4309 /*****
4310 * Drawing functions
4311 *****/
4312 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4313 UINT PrimitiveCount) {
4315 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4316 This->stateBlock->streamIsUP = FALSE;
4318 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4319 debug_d3dprimitivetype(PrimitiveType),
4320 StartVertex, PrimitiveCount);
4321 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
4323 return D3D_OK;
4326 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4327 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4328 D3DPRIMITIVETYPE PrimitiveType,
4329 INT baseVIndex, UINT minIndex,
4330 UINT NumVertices,UINT startIndex,UINT primCount) {
4332 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4333 UINT idxStride = 2;
4334 IWineD3DIndexBuffer *pIB;
4335 D3DINDEXBUFFER_DESC IdxBufDsc;
4337 pIB = This->stateBlock->pIndexData;
4338 This->stateBlock->streamIsUP = FALSE;
4340 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d \n", This,
4341 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4342 minIndex, NumVertices, startIndex, baseVIndex, primCount);
4344 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4345 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4346 idxStride = 2;
4347 } else {
4348 idxStride = 4;
4351 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex,
4352 startIndex, idxStride,
4353 ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory,
4354 minIndex);
4356 return D3D_OK;
4359 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4360 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4361 UINT VertexStreamZeroStride) {
4362 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4364 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4365 debug_d3dprimitivetype(PrimitiveType),
4366 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4368 if (This->stateBlock->stream_source[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->stream_source[0]);
4370 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4371 This->stateBlock->stream_source[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4372 This->stateBlock->stream_stride[0] = VertexStreamZeroStride;
4373 This->stateBlock->streamIsUP = TRUE;
4374 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
4375 This->stateBlock->stream_stride[0] = 0;
4376 This->stateBlock->stream_source[0] = NULL;
4378 /*stream zero settings set to null at end, as per the msdn */
4379 return D3D_OK;
4382 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4383 UINT MinVertexIndex,
4384 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
4385 WINED3DFORMAT IndexDataFormat, CONST void* pVertexStreamZeroData,
4386 UINT VertexStreamZeroStride) {
4387 int idxStride;
4388 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4390 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4391 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4392 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData,
4393 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4395 if (This->stateBlock->stream_source[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->stream_source[0]);
4397 if (IndexDataFormat == WINED3DFMT_INDEX16) {
4398 idxStride = 2;
4399 } else {
4400 idxStride = 4;
4403 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4404 This->stateBlock->stream_source[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4405 This->stateBlock->streamIsUP = TRUE;
4406 This->stateBlock->stream_stride[0] = VertexStreamZeroStride;
4408 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, idxStride, pIndexData, MinVertexIndex);
4410 /* stream zero settings set to null at end as per the msdn */
4411 This->stateBlock->stream_source[0] = NULL;
4412 This->stateBlock->stream_stride[0] = 0;
4413 IWineD3DDevice_SetIndices(iface, NULL, 0);
4415 return D3D_OK;
4418 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
4419 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4421 TRACE("(%p) : stub\n", This);
4422 return D3D_OK;
4425 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
4426 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
4427 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
4428 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4430 TRACE("(%p) : stub\n", This);
4431 return D3D_OK;
4433 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface){
4434 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4436 TRACE("(%p) : stub\n", This);
4437 return D3D_OK;
4440 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface){
4441 IWineD3DSwapChain *swapChain;
4442 HRESULT hr;
4443 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4444 if(hr == D3D_OK){
4445 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
4446 IWineD3DSwapChain_Release(swapChain);
4448 return hr;
4451 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4452 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4453 /* return a sensible default */
4454 *pNumPasses = 1;
4455 FIXME("(%p) : stub\n", This);
4456 return D3D_OK;
4459 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4460 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4461 FIXME("(%p) : stub\n", This);
4462 return D3D_OK;
4465 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4466 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4467 FIXME("(%p) : stub\n", This);
4468 return D3D_OK;
4471 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4472 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4473 FIXME("(%p) : stub\n", This);
4474 return D3D_OK;
4477 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4478 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4479 FIXME("(%p) : stub\n", This);
4480 return D3D_OK;
4483 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4484 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4485 FIXME("(%p) : stub\n", This);
4486 return D3D_OK;
4490 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4491 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4492 FIXME("(%p) : stub\n", This);
4493 return FALSE;
4497 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
4498 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4500 pRasterStatus->InVBlank = TRUE;
4501 pRasterStatus->ScanLine = 0;
4502 FIXME("(%p) : stub\n", This);
4503 return D3D_OK;
4507 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4508 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4509 static BOOL showfixmes = TRUE;
4510 if(nSegments != 0.0f){
4511 if( showfixmes){
4512 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4513 showfixmes = FALSE;
4516 return D3D_OK;
4519 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4520 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4521 static BOOL showfixmes = TRUE;
4522 if( showfixmes){
4523 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4524 showfixmes = FALSE;
4526 return 0.0f;
4530 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4531 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4532 FIXME("(%p) : stub\n", This);
4533 return D3D_OK;
4537 /* Implementation details at http://developer.nvidia.com/attach/6494
4539 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
4540 hmm.. no longer supported use
4541 OpenGL evaluators or tessellate surfaces within your application.
4544 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
4545 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo){
4546 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4547 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p) \n", This, Handle, pNumSegs, pRectPatchInfo);
4548 FIXME("(%p) : Stub\n", This);
4549 return D3D_OK;
4553 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
4554 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo){
4555 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4556 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p) \n", This, Handle, pNumSegs, pTriPatchInfo);
4557 FIXME("(%p) : Stub\n", This);
4558 return D3D_OK;
4561 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle){
4562 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4563 TRACE("(%p) Handle(%d)\n", This, Handle);
4564 FIXME("(%p) : Stub\n", This);
4565 return D3D_OK;
4568 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color){
4569 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4571 FIXME("(%p) : stub\n", This);
4572 return D3D_OK;
4575 /* rendertarget and deptth stencil functions */
4576 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget){
4577 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4579 /* FIXME: Implelent RenderTargetIndex >0 */
4580 if(RenderTargetIndex > 0)
4581 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
4583 *ppRenderTarget = (IWineD3DSurface *)This->renderTarget;
4584 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
4585 /* Note inc ref on returned surface */
4586 if(*ppRenderTarget != NULL)
4587 IWineD3DSurface_AddRef(*ppRenderTarget);
4588 return D3D_OK;
4591 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface){
4592 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4593 *ppZStencilSurface = (IWineD3DSurface *)This->depthStencilBuffer;
4594 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
4596 if(*ppZStencilSurface != NULL){
4597 /* Note inc ref on returned surface */
4598 IWineD3DSurface_AddRef(*ppZStencilSurface);
4600 return D3D_OK;
4603 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget){
4604 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4606 FIXME("(%p) : stub\n", This);
4607 return D3D_OK;
4610 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil){
4611 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4613 FIXME("(%p) : stub\n", This);
4614 return D3D_OK;
4617 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
4618 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
4619 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4620 /* TODO: the use of Impl is deprecated. */
4621 /* some basic validation checks */
4622 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
4624 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
4626 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
4627 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
4628 return D3DERR_INVALIDCALL;
4630 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
4631 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
4632 return D3DERR_INVALIDCALL;
4634 /* TODO: make the cursor 'real' */
4636 This->xHotSpot = XHotSpot;
4637 This->yHotSpot = YHotSpot;
4639 return D3D_OK;
4642 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
4643 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4644 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
4646 This->xScreenSpace = XScreenSpace;
4647 This->yScreenSpace = YScreenSpace;
4649 return;
4653 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
4654 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4655 TRACE("(%p) : visible(%d)\n", This, bShow);
4657 This->bCursorVisible = bShow;
4659 return D3D_OK;
4662 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
4663 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4664 FIXME("(%p) : stub\n", This); /* No way of notifying yet! */
4665 return D3D_OK;
4669 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
4670 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4671 /** FIXME: Resource tracking needs to be done,
4672 * The closes we can do to this is set the priorities of all managed textures low
4673 * and then reset them.
4674 ***********************************************************/
4675 FIXME("(%p) : stub\n", This);
4676 return D3D_OK;
4679 HRESULT WINAPI IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
4680 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4681 /** FIXME: Resource trascking needs to be done.
4682 * in effect this pulls all non only default
4683 * textures out of video memory and deletes all glTextures (glDeleteTextures)
4684 * and should clear down the context and set it up according to pPresentationParameters
4685 ***********************************************************/
4686 FIXME("(%p) : stub\n", This);
4687 return D3D_OK;
4690 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs){
4691 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4692 /** FIXME: always true at the moment **/
4693 if(bEnableDialogs == FALSE){
4694 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
4696 return D3D_OK;
4700 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
4701 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4703 FIXME("(%p) : stub\n", This);
4704 /* Setup some reasonable defaults */
4705 pParameters->AdapterOrdinal = 0; /* always for now */
4706 pParameters->DeviceType = D3DDEVTYPE_HAL; /* always for now */
4707 pParameters->hFocusWindow = 0;
4708 pParameters->BehaviorFlags =0;
4709 return D3D_OK;
4712 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
4713 IWineD3DSwapChain *swapchain;
4714 HRESULT hrc = D3D_OK;
4716 TRACE("Relaying to swapchain\n");
4718 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK){
4719 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (D3DGAMMARAMP *)pRamp);
4720 IWineD3DSwapChain_Release(swapchain);
4722 return;
4725 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
4726 IWineD3DSwapChain *swapchain;
4727 HRESULT hrc = D3D_OK;
4729 TRACE("Relaying to swapchain\n");
4731 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK){
4732 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
4733 IWineD3DSwapChain_Release(swapchain);
4735 return;
4738 /**********************************************************
4739 * IWineD3DDevice VTbl follows
4740 **********************************************************/
4742 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
4744 /*** IUnknown methods ***/
4745 IWineD3DDeviceImpl_QueryInterface,
4746 IWineD3DDeviceImpl_AddRef,
4747 IWineD3DDeviceImpl_Release,
4748 /*** IWineD3DDevice methods ***/
4749 IWineD3DDeviceImpl_GetParent,
4750 /*** Creation methods**/
4751 IWineD3DDeviceImpl_CreateVertexBuffer,
4752 IWineD3DDeviceImpl_CreateIndexBuffer,
4753 IWineD3DDeviceImpl_CreateStateBlock,
4754 IWineD3DDeviceImpl_CreateSurface,
4755 IWineD3DDeviceImpl_CreateTexture,
4756 IWineD3DDeviceImpl_CreateVolumeTexture,
4757 IWineD3DDeviceImpl_CreateVolume,
4758 IWineD3DDeviceImpl_CreateCubeTexture,
4759 IWineD3DDeviceImpl_CreateQuery,
4760 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
4761 IWineD3DDeviceImpl_CreateVertexDeclaration,
4762 IWineD3DDeviceImpl_CreateVertexShader,
4763 IWineD3DDeviceImpl_CreatePixelShader,
4765 /*** Odd functions **/
4766 IWineD3DDeviceImpl_EvictManagedResources,
4767 IWineD3DDeviceImpl_GetAvailableTextureMem,
4768 IWineD3DDeviceImpl_GetBackBuffer,
4769 IWineD3DDeviceImpl_GetCreationParameters,
4770 IWineD3DDeviceImpl_GetDeviceCaps,
4771 IWineD3DDeviceImpl_GetDirect3D,
4772 IWineD3DDeviceImpl_GetDisplayMode,
4773 IWineD3DDeviceImpl_GetNumberOfSwapChains,
4774 IWineD3DDeviceImpl_GetRasterStatus,
4775 IWineD3DDeviceImpl_GetSwapChain,
4776 IWineD3DDeviceImpl_Reset,
4777 IWineD3DDeviceImpl_SetDialogBoxMode,
4778 IWineD3DDeviceImpl_SetCursorProperties,
4779 IWineD3DDeviceImpl_SetCursorPosition,
4780 IWineD3DDeviceImpl_ShowCursor,
4781 IWineD3DDeviceImpl_TestCooperativeLevel,
4782 /*** Getters and setters **/
4783 IWineD3DDeviceImpl_SetClipPlane,
4784 IWineD3DDeviceImpl_GetClipPlane,
4785 IWineD3DDeviceImpl_SetClipStatus,
4786 IWineD3DDeviceImpl_GetClipStatus,
4787 IWineD3DDeviceImpl_SetCurrentTexturePalette,
4788 IWineD3DDeviceImpl_GetCurrentTexturePalette,
4789 IWineD3DDeviceImpl_SetDepthStencilSurface,
4790 IWineD3DDeviceImpl_GetDepthStencilSurface,
4791 IWineD3DDeviceImpl_SetFVF,
4792 IWineD3DDeviceImpl_GetFVF,
4793 IWineD3DDeviceImpl_SetGammaRamp,
4794 IWineD3DDeviceImpl_GetGammaRamp,
4795 IWineD3DDeviceImpl_SetIndices,
4796 IWineD3DDeviceImpl_GetIndices,
4797 IWineD3DDeviceImpl_SetLight,
4798 IWineD3DDeviceImpl_GetLight,
4799 IWineD3DDeviceImpl_SetLightEnable,
4800 IWineD3DDeviceImpl_GetLightEnable,
4801 IWineD3DDeviceImpl_SetMaterial,
4802 IWineD3DDeviceImpl_GetMaterial,
4803 IWineD3DDeviceImpl_SetNPatchMode,
4804 IWineD3DDeviceImpl_GetNPatchMode,
4805 IWineD3DDeviceImpl_SetPaletteEntries,
4806 IWineD3DDeviceImpl_GetPaletteEntries,
4807 IWineD3DDeviceImpl_SetPixelShader,
4808 IWineD3DDeviceImpl_GetPixelShader,
4809 IWineD3DDeviceImpl_SetPixelShaderConstantB,
4810 IWineD3DDeviceImpl_GetPixelShaderConstantB,
4811 IWineD3DDeviceImpl_SetPixelShaderConstantI,
4812 IWineD3DDeviceImpl_GetPixelShaderConstantI,
4813 IWineD3DDeviceImpl_SetPixelShaderConstantF,
4814 IWineD3DDeviceImpl_GetPixelShaderConstantF,
4815 IWineD3DDeviceImpl_SetRenderState,
4816 IWineD3DDeviceImpl_GetRenderState,
4817 IWineD3DDeviceImpl_SetRenderTarget,
4818 IWineD3DDeviceImpl_GetRenderTarget,
4819 IWineD3DDeviceImpl_SetSamplerState,
4820 IWineD3DDeviceImpl_GetSamplerState,
4821 IWineD3DDeviceImpl_SetScissorRect,
4822 IWineD3DDeviceImpl_GetScissorRect,
4823 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
4824 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
4825 IWineD3DDeviceImpl_SetStreamSource,
4826 IWineD3DDeviceImpl_GetStreamSource,
4827 IWineD3DDeviceImpl_SetStreamSourceFreq,
4828 IWineD3DDeviceImpl_GetStreamSourceFreq,
4829 IWineD3DDeviceImpl_SetTexture,
4830 IWineD3DDeviceImpl_GetTexture,
4831 IWineD3DDeviceImpl_SetTextureStageState,
4832 IWineD3DDeviceImpl_GetTextureStageState,
4833 IWineD3DDeviceImpl_SetTransform,
4834 IWineD3DDeviceImpl_GetTransform,
4835 IWineD3DDeviceImpl_SetVertexDeclaration,
4836 IWineD3DDeviceImpl_GetVertexDeclaration,
4837 IWineD3DDeviceImpl_SetVertexShader,
4838 IWineD3DDeviceImpl_GetVertexShader,
4839 IWineD3DDeviceImpl_SetVertexShaderConstantB,
4840 IWineD3DDeviceImpl_GetVertexShaderConstantB,
4841 IWineD3DDeviceImpl_SetVertexShaderConstantI,
4842 IWineD3DDeviceImpl_GetVertexShaderConstantI,
4843 IWineD3DDeviceImpl_SetVertexShaderConstantF,
4844 IWineD3DDeviceImpl_GetVertexShaderConstantF,
4845 IWineD3DDeviceImpl_SetViewport,
4846 IWineD3DDeviceImpl_GetViewport,
4847 IWineD3DDeviceImpl_MultiplyTransform,
4848 IWineD3DDeviceImpl_ValidateDevice,
4849 IWineD3DDeviceImpl_ProcessVertices,
4850 /*** State block ***/
4851 IWineD3DDeviceImpl_BeginStateBlock,
4852 IWineD3DDeviceImpl_EndStateBlock,
4853 /*** Scene management ***/
4854 IWineD3DDeviceImpl_BeginScene,
4855 IWineD3DDeviceImpl_EndScene,
4856 IWineD3DDeviceImpl_Present,
4857 IWineD3DDeviceImpl_Clear,
4858 /*** Drawing ***/
4859 IWineD3DDeviceImpl_DrawPrimitive,
4860 IWineD3DDeviceImpl_DrawIndexedPrimitive,
4861 IWineD3DDeviceImpl_DrawPrimitiveUP,
4862 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
4863 IWineD3DDeviceImpl_DrawRectPatch,
4864 IWineD3DDeviceImpl_DrawTriPatch,
4865 IWineD3DDeviceImpl_DeletePatch,
4866 IWineD3DDeviceImpl_ColorFill,
4867 IWineD3DDeviceImpl_UpdateTexture,
4868 IWineD3DDeviceImpl_UpdateSurface,
4869 IWineD3DDeviceImpl_StretchRect,
4870 IWineD3DDeviceImpl_GetRenderTargetData,
4871 IWineD3DDeviceImpl_GetFrontBufferData,
4872 /*** Internal use IWineD3DDevice methods ***/
4873 IWineD3DDeviceImpl_SetupTextureStates