Implement swapchains.
[wine/testsucceed.git] / dlls / wined3d / device.c
blobda38662c625d003288043be61931416bff4db0b2
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; \
88 /**********************************************************
89 * Global variable / Constants follow
90 **********************************************************/
91 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
93 /**********************************************************
94 * Utility functions follow
95 **********************************************************/
96 /* Convert the D3DLIGHT properties into equivalent gl lights */
97 void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
99 float quad_att;
100 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
101 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
103 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
104 glMatrixMode(GL_MODELVIEW);
105 glPushMatrix();
106 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
108 /* Diffuse: */
109 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
110 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
111 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
112 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
113 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
114 checkGLcall("glLightfv");
116 /* Specular */
117 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
118 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
119 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
120 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
121 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
122 checkGLcall("glLightfv");
124 /* Ambient */
125 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
126 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
127 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
128 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
129 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
130 checkGLcall("glLightfv");
132 /* Attenuation - Are these right? guessing... */
133 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
134 checkGLcall("glLightf");
135 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
136 checkGLcall("glLightf");
138 quad_att = 1.4/(lightInfo->OriginalParms.Range*lightInfo->OriginalParms.Range);
139 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
140 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
141 checkGLcall("glLightf");
143 switch (lightInfo->OriginalParms.Type) {
144 case D3DLIGHT_POINT:
145 /* Position */
146 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
147 checkGLcall("glLightfv");
148 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
149 checkGLcall("glLightf");
150 /* FIXME: Range */
151 break;
153 case D3DLIGHT_SPOT:
154 /* Position */
155 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
156 checkGLcall("glLightfv");
157 /* Direction */
158 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
159 checkGLcall("glLightfv");
160 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
161 checkGLcall("glLightf");
162 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
163 checkGLcall("glLightf");
164 /* FIXME: Range */
165 break;
167 case D3DLIGHT_DIRECTIONAL:
168 /* Direction */
169 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
170 checkGLcall("glLightfv");
171 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
172 checkGLcall("glLightf");
173 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
174 checkGLcall("glLightf");
175 break;
177 default:
178 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
181 /* Restore the modelview matrix */
182 glPopMatrix();
185 /* Apply the current values to the specified texture stage */
186 void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Stage, DWORD Flags) {
187 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
188 int i = 0;
189 float col[4];
190 BOOL changeTexture = TRUE;
192 TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
193 for (i = 1; i < HIGHEST_TEXTURE_STATE; i++) {
195 BOOL skip = FALSE;
197 switch (i) {
198 /* Performance: For texture states where multiples effect the outcome, only bother
199 applying the last one as it will pick up all the other values */
200 case D3DTSS_COLORARG0: /* Will be picked up when setting color op */
201 case D3DTSS_COLORARG1: /* Will be picked up when setting color op */
202 case D3DTSS_COLORARG2: /* Will be picked up when setting color op */
203 case D3DTSS_ALPHAARG0: /* Will be picked up when setting alpha op */
204 case D3DTSS_ALPHAARG1: /* Will be picked up when setting alpha op */
205 case D3DTSS_ALPHAARG2: /* Will be picked up when setting alpha op */
206 skip = TRUE;
207 break;
209 /* Performance: If the texture states only impact settings for the texture unit
210 (compared to the texture object) then there is no need to reapply them. The
211 only time they need applying is the first time, since we cheat and put the
212 values into the stateblock without applying.
213 Per-texture unit: texture function (eg. combine), ops and args
214 texture env color
215 texture generation settings
216 Note: Due to some special conditions there may be a need to do particular ones
217 of these, which is what the Flags allows */
218 case D3DTSS_COLOROP:
219 case D3DTSS_TEXCOORDINDEX:
220 if (!(Flags == REAPPLY_ALL)) skip=TRUE;
221 break;
223 case D3DTSS_ALPHAOP:
224 if (!(Flags & REAPPLY_ALPHAOP)) skip=TRUE;
225 break;
227 default:
228 skip = FALSE;
231 if (skip == FALSE) {
232 /* Performance: Only change to this texture if we have to */
233 if (changeTexture) {
234 /* Make appropriate texture active */
235 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
236 GLACTIVETEXTURE(Stage);
237 } else if (Stage > 0) {
238 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
240 changeTexture = FALSE;
243 /* Now apply the change */
244 IWineD3DDevice_SetTextureStageState(iface, Stage, i, This->stateBlock->textureState[Stage][i]);
248 /* Note the D3DRS value applies to all textures, but GL has one
249 * per texture, so apply it now ready to be used!
251 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
252 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
253 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
255 TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
258 /**********************************************************
259 * IUnknown parts follows
260 **********************************************************/
262 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
264 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
265 /* FIXME: This needs to extend an IWineD3DBaseObject */
267 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
268 if (IsEqualGUID(riid, &IID_IUnknown)
269 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
270 IUnknown_AddRef(iface);
271 *ppobj = This;
272 return D3D_OK;
275 return E_NOINTERFACE;
278 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
279 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
280 ULONG refCount = InterlockedIncrement(&This->ref);
282 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
283 return refCount;
286 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
287 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
288 ULONG refCount = InterlockedDecrement(&This->ref);
290 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
292 if (!refCount) {
293 /* TODO: Clean up all the surfaces and textures! */
294 /* FIXME: Create targets and state blocks in d3d8 */
295 if (((IWineD3DImpl *)This->wineD3D)->dxVersion > 8) { /*We don't create a state block in d3d8 yet*/
296 /* NOTE: You must release the parent if the objects was created via a callback
297 ** ***************************/
298 int i;
299 IUnknown* swapChainParent;
301 /* Release all of the swapchains, except the implicite swapchain (#0) */
302 for(i = 1; i < This->numberOfSwapChains; i++){
303 /* TODO: don't access swapchains[x] directly! */
304 IWineD3DSwapChain_Release(This->swapchains[i]);
307 if (This->stateBlock != NULL) {
308 IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->stateBlock);
311 if (This->swapchains[0] != NULL) {
312 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release it's parent now */
313 /* TODO: don't access swapchains[x] directly!, check that there are no-more swapchains left for this device! */
314 IWineD3DSwapChain_GetParent(This->swapchains[0], &swapChainParent);
315 IUnknown_Release(swapChainParent); /* once for the get parent */
316 if (IUnknown_Release(swapChainParent) > 0){ /* the second time for when it was created */
317 FIXME("(%p) Something's still holding the implicite swapchain\n",This);
322 IWineD3D_Release(This->wineD3D);
323 HeapFree(GetProcessHeap(), 0, This);
325 return refCount;
328 /**********************************************************
329 * IWineD3DDevice implementation follows
330 **********************************************************/
331 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
332 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
333 *pParent = This->parent;
334 IUnknown_AddRef(This->parent);
335 return D3D_OK;
338 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
339 DWORD FVF, D3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
340 IUnknown *parent) {
341 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
342 IWineD3DVertexBufferImpl *object;
343 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
344 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, D3DRTYPE_VERTEXBUFFER)
346 object->resource.size = Size;
347 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
348 object->FVF = FVF;
350 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
351 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
353 return D3D_OK;
356 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
357 WINED3DFORMAT Format, D3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
358 HANDLE *sharedHandle, IUnknown *parent) {
359 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
360 IWineD3DIndexBufferImpl *object;
361 TRACE("(%p) Creating index buffer\n", This);
363 /* Allocate the storage for the device */
364 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,D3DRTYPE_INDEXBUFFER)
366 object->resource.size = Length;
367 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
369 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
370 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
371 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
373 return D3D_OK;
376 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, D3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
378 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
379 IWineD3DStateBlockImpl *object;
381 D3DCREATEOBJECTINSTANCE(object, StateBlock)
382 object->blockType = Type;
384 /* Special case - Used during initialization to produce a placeholder stateblock
385 so other functions called can update a state block */
386 if (Type == (D3DSTATEBLOCKTYPE) 0) {
387 /* Don't bother increasing the reference count otherwise a device will never
388 be freed due to circular dependencies */
389 return D3D_OK;
392 /* Otherwise, might as well set the whole state block to the appropriate values */
393 IWineD3DDevice_AddRef(iface);
394 memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
395 FIXME("unfinished - needs to set up changed and set attributes\n");
396 return D3D_OK;
400 /* ************************************
401 MSDN:
402 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
404 Discard
405 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
407 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.
409 ******************************** */
411 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) {
412 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
413 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
414 unsigned int pow2Width, pow2Height;
416 TRACE("(%p) Create surface\n",This);
418 /** FIXME: Check ranges on the inputs are valid
419 * MSDN
420 * MultisampleQuality
421 * [in] Quality level. The valid range is between zero and one less than the level
422 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
423 * Passing a larger value returns the error D3DERR_INVALIDCALL. The MultisampleQuality
424 * values of paired render targets, depth stencil surfaces, and the MultiSample type
425 * must all match.
426 *******************************/
430 * TODO: Discard MSDN
431 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
433 * If this flag is set, the contents of the depth stencil buffer will be
434 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
435 * with a different depth surface.
437 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
438 ***************************/
440 if(MultisampleQuality < 0) {
441 FIXME("Invalid multisample level %ld \n", MultisampleQuality);
442 return D3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
445 if(MultisampleQuality > 0){
446 FIXME("MultisampleQuality set to %ld, bstituting 0 \n" , MultisampleQuality);
447 MultisampleQuality=0;
450 /* Non-power2 support */
452 /* Find the nearest pow2 match */
453 pow2Width = pow2Height = 1;
454 while (pow2Width < Width) pow2Width <<= 1;
455 while (pow2Height < Height) pow2Height <<= 1;
457 if((pow2Width > Width || pow2Height > Height) && !Usage & D3DUSAGE_RENDERTARGET) {
458 /** TODO: add support for non power two textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
459 FIXME("non-power-two textures unsupported\n");
460 return D3DERR_NOTAVAILABLE;
463 /** TODO: Check against the maximum texture sizes supported by the video card **/
465 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,D3DRTYPE_SURFACE)
466 object->container = (IUnknown*) This;
468 object->currentDesc.Width = Width;
469 object->currentDesc.Height = Height;
470 object->currentDesc.Level = Level;
471 object->currentDesc.MultiSampleType = MultiSample;
472 object->currentDesc.MultiSampleQuality = MultisampleQuality;
473 object->discard = Discard;
474 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
476 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
477 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
478 * space!
479 *********************************/
480 if (Format == WINED3DFMT_DXT1) {
481 /* DXT1 is half byte per pixel */
482 object->resource.size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4)) / 2;
484 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
485 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
486 object->resource.size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4));
487 } else {
488 object->resource.size = (Width * object->bytesPerPixel) * Height;
491 TRACE("Pool %d %d %d %d",Pool, D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM);
493 #if 0
494 /* TODO: Check that we have enough video ram left */
495 if(Pool == D3DPOOL_DEFAULT && IWineD3DDevice_GetAvailableTextureMem(iface) <= object->currentDesc.Size){
496 TRACE("Out of 'bogus' video memory\n");
497 HeapFree(GetProcessHeap(),0,object);
498 *ppSurface = NULL;
499 return D3DERR_OUTOFVIDEOMEMORY;
501 #endif
503 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
504 * this function is too deap to need to care about things like this.
505 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
506 * ****************************************/
507 switch(Pool) {
508 case D3DPOOL_SCRATCH:
509 if(Lockable == FALSE)
510 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
511 which are mutually exclusive, setting lockable to true\n");
512 Lockable = TRUE;
513 break;
514 case D3DPOOL_SYSTEMMEM:
515 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
516 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
517 case D3DPOOL_MANAGED:
518 if(Usage == D3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
519 Usage of DYNAMIC which are mutually exclusive, not doing \
520 anything just telling you.\n");
521 break;
522 case D3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
523 if(!(Usage & D3DUSAGE_DYNAMIC) && !(Usage & D3DUSAGE_RENDERTARGET)
524 && !(Usage && D3DUSAGE_DEPTHSTENCIL ) && Lockable == TRUE)
525 FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
526 break;
527 default:
528 FIXME("(%p) Unknown pool %d\n", This, Pool);
529 break;
532 if (Usage & D3DUSAGE_RENDERTARGET && Pool != D3DPOOL_DEFAULT){
533 FIXME("Trying to create a render target that isn't in the default pool\n");
537 object->locked = FALSE;
538 object->lockable = (WINED3DFMT_D16_LOCKABLE == Format) ? TRUE : Lockable;
539 /* TODO: memory management */
540 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
541 if(object->resource.allocatedMemory == NULL ) {
542 FIXME("Out of memory!\n");
543 HeapFree(GetProcessHeap(),0,object);
544 *ppSurface = NULL;
545 return D3DERR_OUTOFVIDEOMEMORY;
549 IWineD3DSurface_CleanDirtyRect(*ppSurface);
550 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
551 This, Width, Height, Format, debug_d3dformat(Format),
552 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
553 return D3D_OK;
557 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
558 DWORD Usage, WINED3DFORMAT Format, D3DPOOL Pool,
559 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
560 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
562 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
563 IWineD3DTextureImpl *object;
564 unsigned int i;
565 UINT tmpW;
566 UINT tmpH;
567 HRESULT hr;
569 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) .... \n", This, Width, Height, Levels, Usage);
571 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, D3DRTYPE_TEXTURE);
572 D3DINITILIZEBASETEXTURE(object->baseTexture);
573 object->width = Width;
574 object->height = Height;
576 /* Calculate levels for mip mapping */
577 if (Levels == 0) {
578 TRACE("calculating levels %d\n", object->baseTexture.levels);
579 object->baseTexture.levels++;
580 tmpW = Width;
581 tmpH = Height;
582 while (tmpW > 1 && tmpH > 1) {
583 tmpW = max(1, tmpW >> 1);
584 tmpH = max(1, tmpH >> 1);
585 object->baseTexture.levels++;
587 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
590 /* Generate all the surfaces */
591 tmpW = Width;
592 tmpH = Height;
593 for (i = 0; i < object->baseTexture.levels; i++)
595 /* use the callback to create the texture surface */
596 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
597 if(hr!= D3D_OK){
598 int j;
599 FIXME("Failed to create surface %p \n",object);
600 /* clean up */
601 for(j=0;j<i;j++){
602 IWineD3DSurface_Release(object->surfaces[j]);
604 /* heap free object */
605 HeapFree(GetProcessHeap(),0,object);
607 *ppTexture = NULL;
608 return hr;
611 IWineD3DSurface_SetContainer(object->surfaces[i], (IUnknown *)object);
612 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
613 /* calculate the next mipmap level */
614 tmpW = max(1, tmpW >> 1);
615 tmpH = max(1, tmpH >> 1);
618 TRACE("(%p) : Created texture %p\n", This, object);
619 return D3D_OK;
622 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
623 UINT Width, UINT Height, UINT Depth,
624 UINT Levels, DWORD Usage,
625 WINED3DFORMAT Format, D3DPOOL Pool,
626 IWineD3DVolumeTexture** ppVolumeTexture,
627 HANDLE* pSharedHandle, IUnknown *parent,
628 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
630 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
631 IWineD3DVolumeTextureImpl *object;
632 unsigned int i;
633 UINT tmpW;
634 UINT tmpH;
635 UINT tmpD;
637 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, D3DRTYPE_VOLUMETEXTURE);
638 D3DINITILIZEBASETEXTURE(object->baseTexture);
640 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
641 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
643 object->width = Width;
644 object->height = Height;
645 object->depth = Depth;
647 /* Calculate levels for mip mapping */
648 if (Levels == 0) {
649 object->baseTexture.levels++;
650 tmpW = Width;
651 tmpH = Height;
652 tmpD = Depth;
653 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
654 tmpW = max(1, tmpW >> 1);
655 tmpH = max(1, tmpH >> 1);
656 tmpD = max(1, tmpD >> 1);
657 object->baseTexture.levels++;
659 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
662 /* Generate all the surfaces */
663 tmpW = Width;
664 tmpH = Height;
665 tmpD = Depth;
667 for (i = 0; i < object->baseTexture.levels; i++)
669 /* Create the volume */
670 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
671 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
672 IWineD3DVolume_SetContainer(object->volumes[i], (IUnknown *)object);
674 tmpW = max(1, tmpW >> 1);
675 tmpH = max(1, tmpH >> 1);
676 tmpD = max(1, tmpD >> 1);
679 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
680 TRACE("(%p) : Created volume texture %p\n", This, object);
681 return D3D_OK;
684 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
685 UINT Width, UINT Height, UINT Depth,
686 DWORD Usage,
687 WINED3DFORMAT Format, D3DPOOL Pool,
688 IWineD3DVolume** ppVolume,
689 HANDLE* pSharedHandle, IUnknown *parent) {
691 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
692 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
694 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, D3DRTYPE_VOLUME)
696 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
697 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
699 object->currentDesc.Width = Width;
700 object->currentDesc.Height = Height;
701 object->currentDesc.Depth = Depth;
702 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
704 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
705 object->resource.size = (Width * object->bytesPerPixel) * Height * Depth;
706 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
707 object->lockable = TRUE;
708 object->locked = FALSE;
709 memset(&object->lockedBox, 0, sizeof(D3DBOX));
710 object->dirty = FALSE;
711 return IWineD3DVolume_CleanDirtyBox((IWineD3DVolume *) object);
714 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
715 UINT Levels, DWORD Usage,
716 WINED3DFORMAT Format, D3DPOOL Pool,
717 IWineD3DCubeTexture** ppCubeTexture,
718 HANDLE* pSharedHandle, IUnknown *parent,
719 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
721 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
722 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
723 unsigned int i,j;
724 UINT tmpW;
725 HRESULT hr;
727 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, D3DRTYPE_CUBETEXTURE);
728 D3DINITILIZEBASETEXTURE(object->baseTexture);
730 TRACE("(%p) Create Cube Texture \n", This);
732 object->edgeLength = EdgeLength;
734 /* Calculate levels for mip mapping */
735 if (Levels == 0) {
736 object->baseTexture.levels++;
737 tmpW = EdgeLength;
738 while (tmpW > 1) {
739 tmpW = max(1, tmpW / 2);
740 object->baseTexture.levels++;
742 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
745 /* Generate all the surfaces */
746 tmpW = EdgeLength;
747 for (i = 0; i < object->baseTexture.levels; i++) {
749 /* Create the 6 faces */
750 for (j = 0; j < 6; j++) {
752 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
753 i /* Level */, &object->surfaces[j][i],pSharedHandle);
755 if(hr!= D3D_OK){
756 /* clean up */
757 int k;
758 int l;
759 for (l=0;l<j;l++) {
760 IWineD3DSurface_Release(object->surfaces[j][i]);
762 for (k=0;k<i;k++) {
763 for (l=0;l<6;l++) {
764 IWineD3DSurface_Release(object->surfaces[l][j]);
768 FIXME("(%p) Failed to create surface\n",object);
769 HeapFree(GetProcessHeap(),0,object);
770 *ppCubeTexture = NULL;
771 return hr;
773 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IUnknown *)object);
774 TRACE("Created surface level %d @ %p, \n", i, object->surfaces[j][i]);
776 tmpW = max(1, tmpW >> 1);
779 TRACE("(%p) : Created Cube Texture %p\n", This, object);
780 *ppCubeTexture = (IWineD3DCubeTexture *) object;
781 return D3D_OK;
784 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent){
785 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
786 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
788 if(NULL == ppQuery){
789 /* Just a check to see if we support this type of query */
790 HRESULT hr = D3DERR_NOTAVAILABLE;
791 /* Lie and say everything is good (we can return ok fake data from a stub) */
792 switch(Type){
793 case WINED3DQUERYTYPE_VCACHE:
794 case WINED3DQUERYTYPE_RESOURCEMANAGER:
795 case WINED3DQUERYTYPE_VERTEXSTATS:
796 case WINED3DQUERYTYPE_EVENT:
797 case WINED3DQUERYTYPE_OCCLUSION:
798 case WINED3DQUERYTYPE_TIMESTAMP:
799 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
800 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
801 case WINED3DQUERYTYPE_PIPELINETIMINGS:
802 case WINED3DQUERYTYPE_INTERFACETIMINGS:
803 case WINED3DQUERYTYPE_VERTEXTIMINGS:
804 case WINED3DQUERYTYPE_PIXELTIMINGS:
805 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
806 case WINED3DQUERYTYPE_CACHEUTILIZATION:
807 hr = D3D_OK;
808 break;
809 default:
810 FIXME("(%p) Unhandled query type %d\n",This , Type);
812 FIXME("(%p) : Stub request for query type %d returned %ld\n", This, Type, hr);
813 return hr;
816 D3DCREATEOBJECTINSTANCE(object, Query)
817 object->type = Type;
818 object->extendedData = 0;
819 TRACE("(%p) : Created Query %p\n", This, object);
820 return D3D_OK;
823 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
824 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
825 IUnknown* parent,
826 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
827 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil){
828 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
830 HDC hDc;
831 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
832 int num;
833 XVisualInfo template;
834 GLXContext oldContext;
835 Drawable oldDrawable;
836 HRESULT hr = D3D_OK;
838 TRACE("(%p) : Created Aditional Swap Chain\n", This);
840 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
841 * does a device hold a reference to a swap chain giving them a lifetime of the device
842 * or does the swap chain notify the device of it'd destruction.
843 *******************************/
845 D3DCREATEOBJECTINSTANCE(object, SwapChain)
847 /* Initialize other useful values */
848 object->presentParms.BackBufferCount = 1; /* TODO:? support for gl_aux buffers */
850 /*********************
851 * Lookup the window Handle and the relating X window handle
852 ********************/
854 /* Setup hwnd we are using, plus which display this equates to */
855 object->win_handle = *(pPresentationParameters->hDeviceWindow);
856 if (!object->win_handle) {
857 object->win_handle = This->createParms.hFocusWindow;
860 object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window" );
861 hDc = GetDC(object->win_handle);
862 object->display = get_display(hDc);
863 ReleaseDC(object->win_handle, hDc);
864 TRACE("Using a display of %p %p \n", object->display, hDc);
866 if (NULL == object->display || NULL == hDc) {
867 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
868 return D3DERR_NOTAVAILABLE;
871 if (object->win == 0) {
872 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
873 return D3DERR_NOTAVAILABLE;
876 * Create an opengl context for the display visual
877 * NOTE: the visual is chosen as the window is created and the glcontext cannot
878 * use different properties after that point in time. FIXME: How to handle when requested format
879 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
880 * it chooses is identical to the one already being used!
881 **********************************/
883 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
884 ENTER_GL();
886 /* Create a new context for this swapchain */
887 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
888 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
889 (or the best possible if none is requested) */
890 TRACE("Found x visual ID : %ld\n", template.visualid);
892 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
893 if (NULL == object->visInfo) {
894 ERR("cannot really get XVisual\n");
895 LEAVE_GL();
896 return D3DERR_NOTAVAILABLE;
897 } else {
898 int n, value;
899 /* Write out some debug info about the visual/s */
900 TRACE("Using x visual ID : %ld\n", template.visualid);
901 TRACE(" visual info: %p\n", object->visInfo);
902 TRACE(" num items : %d\n", num);
903 for(n = 0;n < num; n++){
904 TRACE("=====item=====: %d\n", n + 1);
905 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
906 TRACE(" screen : %d\n", object->visInfo[n].screen);
907 TRACE(" depth : %u\n", object->visInfo[n].depth);
908 TRACE(" class : %d\n", object->visInfo[n].class);
909 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
910 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
911 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
912 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
913 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
914 /* log some extra glx info */
915 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
916 TRACE(" gl_aux_buffers : %d\n", value);
917 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
918 TRACE(" gl_buffer_size : %d\n", value);
919 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
920 TRACE(" gl_red_size : %d\n", value);
921 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
922 TRACE(" gl_green_size : %d\n", value);
923 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
924 TRACE(" gl_blue_size : %d\n", value);
925 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
926 TRACE(" gl_alpha_size : %d\n", value);
927 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
928 TRACE(" gl_depth_size : %d\n", value);
929 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
930 TRACE(" gl_stencil_size : %d\n", value);
932 /* Now choose a simila visual ID*/
934 #ifdef USE_CONTEXT_MANAGER
936 /** TODO: use a context mamager **/
937 #endif
940 IWineD3DSwapChain *implSwapChain;
941 if (D3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
942 /* The first time around we create the context that is shared with all other swapchians and render targets */
943 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
944 TRACE("Creating implicite context for vis %p, hwnd %p\n", object->display, object->visInfo);
945 } else {
947 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
948 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
949 /* and create a new context with the implicit swapchains context as the shared context */
950 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
951 IWineD3DSwapChain_Release(implSwapChain);
955 /* Cleanup */
956 XFree(object->visInfo);
957 object->visInfo = NULL;
959 if (NULL == object->glCtx) {
960 ERR("cannot create glxContext\n");
961 LEAVE_GL();
962 return D3DERR_NOTAVAILABLE;
965 LEAVE_GL();
966 if (object->glCtx == NULL) {
967 ERR("Error in context creation !\n");
968 return D3DERR_INVALIDCALL;
969 } else {
970 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
971 object->win_handle, object->glCtx, object->win, object->visInfo);
974 /*********************
975 * Windowed / Fullscreen
976 *******************/
979 * TODO: MSDNsays that we are only allowed one fullscreen swapchain per device,
980 * so we should really check to see if their is a fullscreen swapchain already
981 * I think Windows and X have differnt ideas about fullscreen, does a single head count as full screen?
982 **************************************/
984 if (!*(pPresentationParameters->Windowed)) {
986 DEVMODEW devmode;
987 HDC hdc;
988 int bpp = 0;
990 /* Get info on the current display setup */
991 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
992 bpp = GetDeviceCaps(hdc, BITSPIXEL);
993 DeleteDC(hdc);
995 /* Change the display settings */
996 memset(&devmode, 0, sizeof(DEVMODEW));
997 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
998 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
999 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1000 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1001 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1002 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1004 /* Make popup window */
1005 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1006 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1007 *(pPresentationParameters->BackBufferWidth),
1008 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1014 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1015 * then the corresponding dimension of the client area of the hDeviceWindow
1016 * (or the focus window, if hDeviceWindow is NULL) is taken.
1017 **********************/
1019 if (*(pPresentationParameters->Windowed) &&
1020 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1021 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1023 RECT Rect;
1024 GetClientRect(object->win_handle, &Rect);
1026 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1027 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1028 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1030 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1031 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1032 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1036 /*********************
1037 * finish off parameter initialization
1038 *******************/
1040 /* Put the correct figures in the presentation parameters */
1041 TRACE("Coppying accross presentaion paraneters\n");
1042 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1043 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1044 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1045 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1046 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1047 object->presentParms.MultiSampleQuality = *(pPresentationParameters->MultiSampleQuality);
1048 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1049 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1050 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1051 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1052 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1053 object->presentParms.Flags = *(pPresentationParameters->Flags);
1054 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1055 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1058 /* FIXME: check for any failures */
1059 /*********************
1060 * Create the back, front and stencil buffers
1061 *******************/
1062 TRACE("calling rendertarget CB\n");
1063 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1064 object->presentParms.BackBufferWidth,
1065 object->presentParms.BackBufferHeight,
1066 object->presentParms.BackBufferFormat,
1067 object->presentParms.MultiSampleType,
1068 object->presentParms.MultiSampleQuality,
1069 TRUE /* Lockable */,
1070 &object->frontBuffer,
1071 NULL /* pShared (always null)*/);
1072 if (object->frontBuffer != NULL)
1073 IWineD3DSurface_SetContainer(object->frontBuffer, (IUnknown *)object);
1074 TRACE("calling rendertarget CB\n");
1075 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1076 object->presentParms.BackBufferWidth,
1077 object->presentParms.BackBufferHeight,
1078 object->presentParms.BackBufferFormat,
1079 object->presentParms.MultiSampleType,
1080 object->presentParms.MultiSampleQuality,
1081 TRUE /* Lockable */,
1082 &object->backBuffer,
1083 NULL /* pShared (always null)*/);
1084 if (object->backBuffer != NULL)
1085 IWineD3DSurface_SetContainer(object->backBuffer, (IUnknown *)object);
1087 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1088 if (pPresentationParameters->EnableAutoDepthStencil) {
1089 TRACE("Creating depth stencil buffer\n");
1090 if (This->depthStencilBuffer == NULL ) {
1091 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1092 object->presentParms.BackBufferWidth,
1093 object->presentParms.BackBufferHeight,
1094 object->presentParms.AutoDepthStencilFormat,
1095 object->presentParms.MultiSampleType,
1096 object->presentParms.MultiSampleQuality,
1097 FALSE /* FIXME: Discard */,
1098 &This->depthStencilBuffer,
1099 NULL /* pShared (always null)*/ );
1100 if (This->depthStencilBuffer != NULL)
1101 IWineD3DSurface_SetContainer(This->depthStencilBuffer, (IUnknown *)iface);
1104 /** TODO: A check on width, height and multisample types
1105 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1106 ****************************/
1107 object->wantsDepthStencilBuffer = TRUE;
1108 } else {
1109 object->wantsDepthStencilBuffer = FALSE;
1112 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1115 /*********************
1116 * init the default renderTarget management
1117 *******************/
1118 object->drawable = object->win;
1119 object->render_ctx = object->glCtx;
1121 if(hr == D3D_OK){
1122 /*********************
1123 * Setup some defaults and clear down the buffers
1124 *******************/
1125 ENTER_GL();
1126 /** save current context and drawable **/
1127 oldContext = glXGetCurrentContext();
1128 oldDrawable = glXGetCurrentDrawable();
1130 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1131 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1132 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1134 checkGLcall("glXMakeCurrent");
1136 TRACE("Setting up the screen\n");
1137 /* Clear the screen */
1138 glClearColor(0.0, 0.0, 0.0, 0.0);
1139 checkGLcall("glClearColor");
1140 glClearIndex(0);
1141 glClearDepth(1);
1142 glClearStencil(0xffff);
1144 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1145 checkGLcall("glClear");
1147 glColor3f(1.0, 1.0, 1.0);
1148 checkGLcall("glColor3f");
1150 glEnable(GL_LIGHTING);
1151 checkGLcall("glEnable");
1153 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1154 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1156 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1157 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1159 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1160 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1162 /* switch back to the original context (unless it was zero)*/
1163 if (This->numberOfSwapChains != 0) {
1164 /** TODO: restore the context and drawable **/
1165 glXMakeCurrent(object->display, oldDrawable, oldContext);
1168 LEAVE_GL();
1170 /* TODO: move this off into a linked list implementation! (add swapchain, remove swapchain or something along those lines) */
1171 #if 0
1172 IListOperator *listOperator;
1173 IListStore_CreateListOperator(This->swapchainStore, &listOperator);
1174 IListOperator_Append(listOperator, (void *)object);
1175 IListOperator_Release(listOperator);
1176 #endif
1178 This->swapchains[This->numberOfSwapChains++] = (IWineD3DSwapChain *)object;
1179 TRACE("Set swapchain to %p\n", object);
1180 } else { /* something went wrong so clean up */
1181 IUnknown* bufferParent;
1182 if (object->frontBuffer) {
1183 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1184 IUnknown_Release(bufferParent); /* once for the get parent */
1185 if(IUnknown_Release(bufferParent) > 0){
1186 FIXME("(%p) Something's still holding the front buffer\n",This);
1189 if (object->backBuffer) {
1190 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1191 IUnknown_Release(bufferParent); /* once for the get parent */
1192 if(IUnknown_Release(bufferParent) > 0){
1193 FIXME("(%p) Something's still holding the back buffer\n",This);
1196 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1197 /* Clean up the context */
1198 /* check that we are the current context first (we shouldn't be though!) */
1199 if (object->glCtx != 0) {
1200 if(glXGetCurrentContext() == object->glCtx){
1201 glXMakeCurrent(object->display, None, NULL);
1203 glXDestroyContext(object->display, object->glCtx);
1205 HeapFree(GetProcessHeap(), 0, object);
1208 return hr;
1211 /** NOTE: These are ahead of the other getters and setters to save using a forward declartion **/
1212 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1213 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1215 /* TODO: move over to using a linked list. */
1216 TRACE("(%p) returning %d\n", This, This->numberOfSwapChains);
1217 return This->numberOfSwapChains;
1220 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1221 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1222 TRACE("(%p) : swapchain %d \n", This, iSwapChain);
1224 if(iSwapChain >= IWineD3DDeviceImpl_GetNumberOfSwapChains(iface) || iSwapChain < 0){
1225 *pSwapChain = NULL;
1226 return D3DERR_INVALIDCALL;
1227 }else{
1228 /** TODO: move off to a linked list implementation **/
1229 *pSwapChain = This->swapchains[iSwapChain];
1232 /* TODO: move over to using stores and linked lists. */
1234 IWineD3DSwapChain_AddRef(*pSwapChain);
1235 TRACE("(%p) returning %p\n", This, *pSwapChain);
1236 return D3D_OK;
1239 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters){
1240 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1242 FIXME("(%p) : Stub\n",This);
1243 return D3D_OK;
1247 /*****
1248 * Vertex Declaration
1249 *****/
1250 /* TODO: Get ridd of thease and put the functions in the IWineD3DVertexDeclaration interface */
1251 #if 1
1252 extern HRESULT IWineD3DVertexDeclarationImpl_ParseDeclaration8(IWineD3DDeviceImpl * This, const DWORD* pDecl, IWineD3DVertexDeclarationImpl * object);
1253 extern HRESULT IWineD3DVertexDeclarationImpl_ParseDeclaration9(IWineD3DDeviceImpl * This, const D3DVERTEXELEMENT9* pDecl, IWineD3DVertexDeclarationImpl * object);
1256 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1257 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1258 IWineD3DVertexDeclarationImpl *object = NULL;
1259 HRESULT hr = D3D_OK;
1261 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1262 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1263 object->allFVF = 0;
1265 if (8 == ((IWineD3DImpl *)This->wineD3D)->dxVersion) {
1266 /** @TODO */
1267 hr = IWineD3DVertexDeclarationImpl_ParseDeclaration8(This, (const DWORD*) pDeclaration, object);
1268 } else {
1269 hr = IWineD3DVertexDeclarationImpl_ParseDeclaration9(This, (const D3DVERTEXELEMENT9*) pDeclaration, object);
1272 return hr;
1276 #else
1277 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration8(IWineD3DDevice* iface, const DWORD* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent){
1278 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1279 IWineD3DVertexDeclarationImpl *object = NULL; /* NOTE: impl allowed, this is a create */
1280 HRESULT hr = D3D_OK;
1281 /* TODO: replace impl usage with a call to Version*/
1282 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1283 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1284 object->allFVF = 0;
1285 /* TODO: get ridd of the impl usage, we should only be using interfaces */
1286 hr = IWineD3DVertexDeclarationImpl_ParseDeclaration8(This, pDeclaration, object);
1288 return hr;
1291 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration9(IWineD3DDevice* iface, const D3DVERTEXELEMENT9* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent){
1292 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1293 IWineD3DVertexDeclarationImpl *object = NULL; /* NOTE: impl allowed, this is a create */
1294 HRESULT hr = D3D_OK;
1295 /* TODO: replace impl usage with a call to Version*/
1296 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1297 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1298 object->allFVF = 0;
1299 /* TODO: get ridd of the impl usage, we should only be using interfaces */
1300 hr = IWineD3DVertexDeclarationImpl_ParseDeclaration9(This, pDeclaration, object);
1302 return hr;
1304 #endif
1306 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1307 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DVertexShader** ppVertexShader, IUnknown *parent){
1308 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1309 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1310 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1311 object->function = pFunction;
1312 FIXME("(%p) : STUB: Created Vertex shader %p\n", This, ppVertexShader);
1313 return D3D_OK;
1317 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DPixelShader** ppPixelShader, IUnknown *parent){
1318 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1319 FIXME("(%p) : Stub\n", This);
1320 return D3D_OK;
1323 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice* iface, IWineD3D** ppD3D){
1324 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1325 *ppD3D= This->wineD3D;
1326 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1327 IWineD3D_AddRef(*ppD3D);
1328 return D3D_OK;
1332 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1333 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1334 FIXME("Stub :(%p) returning 64Mib\n", This);
1335 return 64*1024*1024;
1339 /*****
1340 * Get / Set FVF
1341 *****/
1342 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1343 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1345 /* Update the current state block */
1346 This->updateStateBlock->fvf = fvf;
1347 This->updateStateBlock->changed.fvf = TRUE;
1348 This->updateStateBlock->set.fvf = TRUE;
1350 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1352 /* No difference if recording or not */
1353 return D3D_OK;
1355 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1356 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1357 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1358 *pfvf = This->stateBlock->fvf;
1359 return D3D_OK;
1362 /*****
1363 * Get / Set Stream Source
1364 *****/
1365 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1366 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1367 IWineD3DVertexBuffer *oldSrc;
1369 oldSrc = This->stateBlock->stream_source[StreamNumber];
1370 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1372 This->updateStateBlock->changed.stream_source[StreamNumber] = TRUE;
1373 This->updateStateBlock->set.stream_source[StreamNumber] = TRUE;
1374 This->updateStateBlock->stream_stride[StreamNumber] = Stride;
1375 This->updateStateBlock->stream_source[StreamNumber] = pStreamData;
1376 This->updateStateBlock->stream_offset[StreamNumber] = OffsetInBytes;
1378 /* Handle recording of state blocks */
1379 if (This->isRecordingState) {
1380 TRACE("Recording... not performing anything\n");
1381 return D3D_OK;
1384 /* Not recording... */
1385 if (oldSrc != NULL) IWineD3DVertexBuffer_Release(oldSrc);
1386 if (pStreamData != NULL) IWineD3DVertexBuffer_AddRef(pStreamData);
1388 return D3D_OK;
1391 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
1392 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1394 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->stateBlock->stream_source[StreamNumber], This->stateBlock->stream_stride[StreamNumber]);
1395 *pStream = This->stateBlock->stream_source[StreamNumber];
1396 *pStride = This->stateBlock->stream_stride[StreamNumber];
1397 *pOffset = This->stateBlock->stream_offset[StreamNumber];
1398 if (*pStream != NULL) IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
1399 return D3D_OK;
1402 /*Should be quite easy, just an extension of vertexdata
1403 ref...
1404 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1406 The divider is a bit odd though
1408 VertexOffset = StartVertex / Divider * StreamStride +
1409 VertexIndex / Divider * StreamStride + StreamOffset
1412 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider){
1413 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1415 FIXME("(%p) : stub\n", This);
1416 return D3D_OK;
1419 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider){
1420 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1422 FIXME("(%p) : stub\n", This);
1423 return D3D_OK;
1427 /*****
1428 * Get / Set & Multipy Transform
1429 *****/
1430 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1431 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1433 /* Most of this routine, comments included copied from ddraw tree initially: */
1434 TRACE("(%p) : Transform State=%d\n", This, d3dts);
1436 /* Handle recording of state blocks */
1437 if (This->isRecordingState) {
1438 TRACE("Recording... not performing anything\n");
1439 This->updateStateBlock->changed.transform[d3dts] = TRUE;
1440 This->updateStateBlock->set.transform[d3dts] = TRUE;
1441 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1442 return D3D_OK;
1446 * If the new matrix is the same as the current one,
1447 * we cut off any further processing. this seems to be a reasonable
1448 * optimization because as was noticed, some apps (warcraft3 for example)
1449 * tend towards setting the same matrix repeatedly for some reason.
1451 * From here on we assume that the new matrix is different, wherever it matters.
1453 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1454 TRACE("The app is setting the same matrix over again\n");
1455 return D3D_OK;
1456 } else {
1457 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1461 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1462 where ViewMat = Camera space, WorldMat = world space.
1464 In OpenGL, camera and world space is combined into GL_MODELVIEW
1465 matrix. The Projection matrix stay projection matrix.
1468 /* Capture the times we can just ignore the change for now */
1469 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1470 This->modelview_valid = FALSE;
1471 return D3D_OK;
1473 } else if (d3dts == D3DTS_PROJECTION) {
1474 This->proj_valid = FALSE;
1475 return D3D_OK;
1477 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1478 /* Indexed Vertex Blending Matrices 256 -> 511 */
1479 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1480 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1481 return D3D_OK;
1484 /* Now we really are going to have to change a matrix */
1485 ENTER_GL();
1487 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1488 if (d3dts < GL_LIMITS(textures)) {
1489 int tex = d3dts - D3DTS_TEXTURE0;
1490 GLACTIVETEXTURE(tex);
1491 set_texture_matrix((float *)lpmatrix,
1492 This->updateStateBlock->textureState[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
1495 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1496 unsigned int k;
1498 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1499 * NOTE: We have to reset the positions even if the light/plane is not currently
1500 * enabled, since the call to enable it will not reset the position.
1501 * NOTE2: Apparently texture transforms do NOT need reapplying
1504 PLIGHTINFOEL *lightChain = NULL;
1505 This->modelview_valid = FALSE;
1506 This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
1508 glMatrixMode(GL_MODELVIEW);
1509 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1510 glPushMatrix();
1511 glLoadMatrixf((float *)lpmatrix);
1512 checkGLcall("glLoadMatrixf(...)");
1514 /* Reset lights */
1515 lightChain = This->stateBlock->lights;
1516 while (lightChain && lightChain->glIndex != -1) {
1517 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1518 checkGLcall("glLightfv posn");
1519 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1520 checkGLcall("glLightfv dirn");
1521 lightChain = lightChain->next;
1524 /* Reset Clipping Planes if clipping is enabled */
1525 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1526 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1527 checkGLcall("glClipPlane");
1529 glPopMatrix();
1531 } else { /* What was requested!?? */
1532 WARN("invalid matrix specified: %i\n", d3dts);
1535 /* Release lock, all done */
1536 LEAVE_GL();
1537 return D3D_OK;
1540 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1541 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1542 TRACE("(%p) : for Transform State %d\n", This, State);
1543 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1544 return D3D_OK;
1547 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1548 D3DMATRIX *mat = NULL;
1549 D3DMATRIX temp;
1551 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1552 * below means it will be recorded in a state block change, but it
1553 * works regardless where it is recorded.
1554 * If this is found to be wrong, change to StateBlock.
1556 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1557 TRACE("(%p) : For state %u\n", This, State);
1559 if (State < HIGHEST_TRANSFORMSTATE)
1561 mat = &This->updateStateBlock->transforms[State];
1562 } else {
1563 FIXME("Unhandled transform state!!\n");
1566 /* Copied from ddraw code: */
1567 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);
1568 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);
1569 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);
1570 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);
1572 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);
1573 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);
1574 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);
1575 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);
1577 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);
1578 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);
1579 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);
1580 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);
1582 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);
1583 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);
1584 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);
1585 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);
1587 /* Apply change via set transform - will reapply to eg. lights this way */
1588 IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
1589 return D3D_OK;
1592 /*****
1593 * Get / Set Light
1594 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
1595 *****/
1596 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1597 you can reference any indexes you want as long as that number max are enabled at any
1598 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1599 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1600 but when recording, just build a chain pretty much of commands to be replayed. */
1602 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
1603 float rho;
1604 PLIGHTINFOEL *object, *temp;
1606 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1607 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1609 /* If recording state block, just add to end of lights chain */
1610 if (This->isRecordingState) {
1611 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1612 if (NULL == object) {
1613 return D3DERR_OUTOFVIDEOMEMORY;
1615 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1616 object->OriginalIndex = Index;
1617 object->glIndex = -1;
1618 object->changed = TRUE;
1620 /* Add to the END of the chain of lights changes to be replayed */
1621 if (This->updateStateBlock->lights == NULL) {
1622 This->updateStateBlock->lights = object;
1623 } else {
1624 temp = This->updateStateBlock->lights;
1625 while (temp->next != NULL) temp=temp->next;
1626 temp->next = object;
1628 TRACE("Recording... not performing anything more\n");
1629 return D3D_OK;
1632 /* Ok, not recording any longer so do real work */
1633 object = This->stateBlock->lights;
1634 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1636 /* If we didn't find it in the list of lights, time to add it */
1637 if (object == NULL) {
1638 PLIGHTINFOEL *insertAt,*prevPos;
1640 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1641 if (NULL == object) {
1642 return D3DERR_OUTOFVIDEOMEMORY;
1644 object->OriginalIndex = Index;
1645 object->glIndex = -1;
1647 /* Add it to the front of list with the idea that lights will be changed as needed
1648 BUT after any lights currently assigned GL indexes */
1649 insertAt = This->stateBlock->lights;
1650 prevPos = NULL;
1651 while (insertAt != NULL && insertAt->glIndex != -1) {
1652 prevPos = insertAt;
1653 insertAt = insertAt->next;
1656 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1657 This->stateBlock->lights = object;
1658 } else if (insertAt == NULL) { /* End of list */
1659 prevPos->next = object;
1660 object->prev = prevPos;
1661 } else { /* Middle of chain */
1662 if (prevPos == NULL) {
1663 This->stateBlock->lights = object;
1664 } else {
1665 prevPos->next = object;
1667 object->prev = prevPos;
1668 object->next = insertAt;
1669 insertAt->prev = object;
1673 /* Initialze the object */
1674 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,
1675 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1676 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1677 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1678 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1679 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1680 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1682 /* Save away the information */
1683 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1685 switch (pLight->Type) {
1686 case D3DLIGHT_POINT:
1687 /* Position */
1688 object->lightPosn[0] = pLight->Position.x;
1689 object->lightPosn[1] = pLight->Position.y;
1690 object->lightPosn[2] = pLight->Position.z;
1691 object->lightPosn[3] = 1.0f;
1692 object->cutoff = 180.0f;
1693 /* FIXME: Range */
1694 break;
1696 case D3DLIGHT_DIRECTIONAL:
1697 /* Direction */
1698 object->lightPosn[0] = -pLight->Direction.x;
1699 object->lightPosn[1] = -pLight->Direction.y;
1700 object->lightPosn[2] = -pLight->Direction.z;
1701 object->lightPosn[3] = 0.0;
1702 object->exponent = 0.0f;
1703 object->cutoff = 180.0f;
1704 break;
1706 case D3DLIGHT_SPOT:
1707 /* Position */
1708 object->lightPosn[0] = pLight->Position.x;
1709 object->lightPosn[1] = pLight->Position.y;
1710 object->lightPosn[2] = pLight->Position.z;
1711 object->lightPosn[3] = 1.0;
1713 /* Direction */
1714 object->lightDirn[0] = pLight->Direction.x;
1715 object->lightDirn[1] = pLight->Direction.y;
1716 object->lightDirn[2] = pLight->Direction.z;
1717 object->lightDirn[3] = 1.0;
1720 * opengl-ish and d3d-ish spot lights use too different models for the
1721 * light "intensity" as a function of the angle towards the main light direction,
1722 * so we only can approximate very roughly.
1723 * however spot lights are rather rarely used in games (if ever used at all).
1724 * furthermore if still used, probably nobody pays attention to such details.
1726 if (pLight->Falloff == 0) {
1727 rho = 6.28f;
1728 } else {
1729 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1731 if (rho < 0.0001) rho = 0.0001f;
1732 object->exponent = -0.3/log(cos(rho/2));
1733 object->cutoff = pLight->Phi*90/M_PI;
1735 /* FIXME: Range */
1736 break;
1738 default:
1739 FIXME("Unrecognized light type %d\n", pLight->Type);
1742 /* Update the live definitions if the light is currently assigned a glIndex */
1743 if (object->glIndex != -1) {
1744 setup_light(iface, object->glIndex, object);
1746 return D3D_OK;
1749 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
1750 PLIGHTINFOEL *lightInfo = NULL;
1751 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1752 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1754 /* Locate the light in the live lights */
1755 lightInfo = This->stateBlock->lights;
1756 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1758 if (lightInfo == NULL) {
1759 TRACE("Light information requested but light not defined\n");
1760 return D3DERR_INVALIDCALL;
1763 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
1764 return D3D_OK;
1767 /*****
1768 * Get / Set Light Enable
1769 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
1770 *****/
1771 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
1772 PLIGHTINFOEL *lightInfo = NULL;
1773 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1774 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1776 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1777 if (This->isRecordingState) {
1778 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1779 if (NULL == lightInfo) {
1780 return D3DERR_OUTOFVIDEOMEMORY;
1782 lightInfo->OriginalIndex = Index;
1783 lightInfo->glIndex = -1;
1784 lightInfo->enabledChanged = TRUE;
1786 /* Add to the END of the chain of lights changes to be replayed */
1787 if (This->updateStateBlock->lights == NULL) {
1788 This->updateStateBlock->lights = lightInfo;
1789 } else {
1790 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
1791 while (temp->next != NULL) temp=temp->next;
1792 temp->next = lightInfo;
1794 TRACE("Recording... not performing anything more\n");
1795 return D3D_OK;
1798 /* Not recording... So, locate the light in the live lights */
1799 lightInfo = This->stateBlock->lights;
1800 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1802 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1803 if (lightInfo == NULL) {
1804 D3DLIGHT9 lightParms;
1805 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1806 wait until someone confirms it seems to work! */
1807 TRACE("Light enabled requested but light not defined, so defining one!\n");
1808 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1809 lightParms.Diffuse.r = 1.0;
1810 lightParms.Diffuse.g = 1.0;
1811 lightParms.Diffuse.b = 1.0;
1812 lightParms.Diffuse.a = 0.0;
1813 lightParms.Specular.r = 0.0;
1814 lightParms.Specular.g = 0.0;
1815 lightParms.Specular.b = 0.0;
1816 lightParms.Specular.a = 0.0;
1817 lightParms.Ambient.r = 0.0;
1818 lightParms.Ambient.g = 0.0;
1819 lightParms.Ambient.b = 0.0;
1820 lightParms.Ambient.a = 0.0;
1821 lightParms.Position.x = 0.0;
1822 lightParms.Position.y = 0.0;
1823 lightParms.Position.z = 0.0;
1824 lightParms.Direction.x = 0.0;
1825 lightParms.Direction.y = 0.0;
1826 lightParms.Direction.z = 1.0;
1827 lightParms.Range = 0.0;
1828 lightParms.Falloff = 0.0;
1829 lightParms.Attenuation0 = 0.0;
1830 lightParms.Attenuation1 = 0.0;
1831 lightParms.Attenuation2 = 0.0;
1832 lightParms.Theta = 0.0;
1833 lightParms.Phi = 0.0;
1834 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
1836 /* Search for it again! Should be fairly quick as near head of list */
1837 lightInfo = This->stateBlock->lights;
1838 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1839 if (lightInfo == NULL) {
1840 FIXME("Adding default lights has failed dismally\n");
1841 return D3DERR_INVALIDCALL;
1845 /* OK, we now have a light... */
1846 if (Enable == FALSE) {
1848 /* If we are disabling it, check it was enabled, and
1849 still only do something if it has assigned a glIndex (which it should have!) */
1850 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
1851 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1852 ENTER_GL();
1853 glDisable(GL_LIGHT0 + lightInfo->glIndex);
1854 checkGLcall("glDisable GL_LIGHT0+Index");
1855 LEAVE_GL();
1856 } else {
1857 TRACE("Nothing to do as light was not enabled\n");
1859 lightInfo->lightEnabled = FALSE;
1860 } else {
1862 /* We are enabling it. If it is enabled, it's really simple */
1863 if (lightInfo->lightEnabled) {
1864 /* nop */
1865 TRACE("Nothing to do as light was enabled\n");
1867 /* If it already has a glIndex, it's still simple */
1868 } else if (lightInfo->glIndex != -1) {
1869 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
1870 lightInfo->lightEnabled = TRUE;
1871 ENTER_GL();
1872 glEnable(GL_LIGHT0 + lightInfo->glIndex);
1873 checkGLcall("glEnable GL_LIGHT0+Index already setup");
1874 LEAVE_GL();
1876 /* Otherwise got to find space - lights are ordered gl indexes first */
1877 } else {
1878 PLIGHTINFOEL *bsf = NULL;
1879 PLIGHTINFOEL *pos = This->stateBlock->lights;
1880 PLIGHTINFOEL *prev = NULL;
1881 int Index= 0;
1882 int glIndex = -1;
1884 /* Try to minimize changes as much as possible */
1885 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
1887 /* Try to remember which index can be replaced if necessary */
1888 if (bsf==NULL && pos->lightEnabled == FALSE) {
1889 /* Found a light we can replace, save as best replacement */
1890 bsf = pos;
1893 /* Step to next space */
1894 prev = pos;
1895 pos = pos->next;
1896 Index ++;
1899 /* If we have too many active lights, fail the call */
1900 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
1901 FIXME("Program requests too many concurrent lights\n");
1902 return D3DERR_INVALIDCALL;
1904 /* If we have allocated all lights, but not all are enabled,
1905 reuse one which is not enabled */
1906 } else if (Index == This->maxConcurrentLights) {
1907 /* use bsf - Simply swap the new light and the BSF one */
1908 PLIGHTINFOEL *bsfNext = bsf->next;
1909 PLIGHTINFOEL *bsfPrev = bsf->prev;
1911 /* Sort out ends */
1912 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
1913 if (bsf->prev != NULL) {
1914 bsf->prev->next = lightInfo;
1915 } else {
1916 This->stateBlock->lights = lightInfo;
1919 /* If not side by side, lots of chains to update */
1920 if (bsf->next != lightInfo) {
1921 lightInfo->prev->next = bsf;
1922 bsf->next->prev = lightInfo;
1923 bsf->next = lightInfo->next;
1924 bsf->prev = lightInfo->prev;
1925 lightInfo->next = bsfNext;
1926 lightInfo->prev = bsfPrev;
1928 } else {
1929 /* Simple swaps */
1930 bsf->prev = lightInfo;
1931 bsf->next = lightInfo->next;
1932 lightInfo->next = bsf;
1933 lightInfo->prev = bsfPrev;
1937 /* Update states */
1938 glIndex = bsf->glIndex;
1939 bsf->glIndex = -1;
1940 lightInfo->glIndex = glIndex;
1941 lightInfo->lightEnabled = TRUE;
1943 /* Finally set up the light in gl itself */
1944 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
1945 ENTER_GL();
1946 setup_light(iface, glIndex, lightInfo);
1947 glEnable(GL_LIGHT0 + glIndex);
1948 checkGLcall("glEnable GL_LIGHT0 new setup");
1949 LEAVE_GL();
1951 /* If we reached the end of the allocated lights, with space in the
1952 gl lights, setup a new light */
1953 } else if (pos->glIndex == -1) {
1955 /* We reached the end of the allocated gl lights, so already
1956 know the index of the next one! */
1957 glIndex = Index;
1958 lightInfo->glIndex = glIndex;
1959 lightInfo->lightEnabled = TRUE;
1961 /* In an ideal world, it's already in the right place */
1962 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
1963 /* No need to move it */
1964 } else {
1965 /* Remove this light from the list */
1966 lightInfo->prev->next = lightInfo->next;
1967 if (lightInfo->next != NULL) {
1968 lightInfo->next->prev = lightInfo->prev;
1971 /* Add in at appropriate place (inbetween prev and pos) */
1972 lightInfo->prev = prev;
1973 lightInfo->next = pos;
1974 if (prev == NULL) {
1975 This->stateBlock->lights = lightInfo;
1976 } else {
1977 prev->next = lightInfo;
1979 if (pos != NULL) {
1980 pos->prev = lightInfo;
1984 /* Finally set up the light in gl itself */
1985 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
1986 ENTER_GL();
1987 setup_light(iface, glIndex, lightInfo);
1988 glEnable(GL_LIGHT0 + glIndex);
1989 checkGLcall("glEnable GL_LIGHT0 new setup");
1990 LEAVE_GL();
1995 return D3D_OK;
1998 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2000 PLIGHTINFOEL *lightInfo = NULL;
2001 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2002 TRACE("(%p) : for idx(%ld)\n", This, Index);
2004 /* Locate the light in the live lights */
2005 lightInfo = This->stateBlock->lights;
2006 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2008 if (lightInfo == NULL) {
2009 TRACE("Light enabled state requested but light not defined\n");
2010 return D3DERR_INVALIDCALL;
2012 *pEnable = lightInfo->lightEnabled;
2013 return D3D_OK;
2016 /*****
2017 * Get / Set Clip Planes
2018 *****/
2019 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2020 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2021 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2023 /* Validate Index */
2024 if (Index >= GL_LIMITS(clipplanes)) {
2025 TRACE("Application has requested clipplane this device doesn't support\n");
2026 return D3DERR_INVALIDCALL;
2029 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2030 This->updateStateBlock->set.clipplane[Index] = TRUE;
2031 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2032 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2033 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2034 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2036 /* Handle recording of state blocks */
2037 if (This->isRecordingState) {
2038 TRACE("Recording... not performing anything\n");
2039 return D3D_OK;
2042 /* Apply it */
2044 ENTER_GL();
2046 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2047 glMatrixMode(GL_MODELVIEW);
2048 glPushMatrix();
2049 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2051 TRACE("Clipplane [%f,%f,%f,%f]\n",
2052 This->updateStateBlock->clipplane[Index][0],
2053 This->updateStateBlock->clipplane[Index][1],
2054 This->updateStateBlock->clipplane[Index][2],
2055 This->updateStateBlock->clipplane[Index][3]);
2056 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2057 checkGLcall("glClipPlane");
2059 glPopMatrix();
2060 LEAVE_GL();
2062 return D3D_OK;
2065 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2066 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2067 TRACE("(%p) : for idx %ld\n", This, Index);
2069 /* Validate Index */
2070 if (Index >= GL_LIMITS(clipplanes)) {
2071 TRACE("Application has requested clipplane this device doesn't support\n");
2072 return D3DERR_INVALIDCALL;
2075 pPlane[0] = This->stateBlock->clipplane[Index][0];
2076 pPlane[1] = This->stateBlock->clipplane[Index][1];
2077 pPlane[2] = This->stateBlock->clipplane[Index][2];
2078 pPlane[3] = This->stateBlock->clipplane[Index][3];
2079 return D3D_OK;
2082 /*****
2083 * Get / Set Clip Plane Status
2084 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2085 *****/
2086 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2087 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2088 FIXME("(%p) : stub\n", This);
2089 if (NULL == pClipStatus) {
2090 return D3DERR_INVALIDCALL;
2092 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2093 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2094 return D3D_OK;
2097 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2098 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2099 FIXME("(%p) : stub\n", This);
2100 if (NULL == pClipStatus) {
2101 return D3DERR_INVALIDCALL;
2103 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2104 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2105 return D3D_OK;
2108 /*****
2109 * Get / Set Material
2110 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2111 *****/
2112 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2113 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2115 This->updateStateBlock->changed.material = TRUE;
2116 This->updateStateBlock->set.material = TRUE;
2117 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2119 /* Handle recording of state blocks */
2120 if (This->isRecordingState) {
2121 TRACE("Recording... not performing anything\n");
2122 return D3D_OK;
2125 ENTER_GL();
2126 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2127 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2128 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2129 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2130 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2132 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2133 checkGLcall("glMaterialfv");
2134 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2135 checkGLcall("glMaterialfv");
2137 /* Only change material color if specular is enabled, otherwise it is set to black */
2138 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2139 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2140 checkGLcall("glMaterialfv");
2141 } else {
2142 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2143 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2144 checkGLcall("glMaterialfv");
2146 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2147 checkGLcall("glMaterialfv");
2148 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2149 checkGLcall("glMaterialf");
2151 LEAVE_GL();
2152 return D3D_OK;
2155 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2156 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2157 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2158 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2159 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2160 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2161 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2162 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2163 return D3D_OK;
2166 /*****
2167 * Get / Set Indices
2168 *****/
2169 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2170 UINT BaseVertexIndex) {
2171 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2172 IWineD3DIndexBuffer *oldIdxs;
2174 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2175 oldIdxs = This->updateStateBlock->pIndexData;
2177 This->updateStateBlock->changed.indices = TRUE;
2178 This->updateStateBlock->set.indices = TRUE;
2179 This->updateStateBlock->pIndexData = pIndexData;
2180 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2182 /* Handle recording of state blocks */
2183 if (This->isRecordingState) {
2184 TRACE("Recording... not performing anything\n");
2185 return D3D_OK;
2188 if (oldIdxs) IWineD3DIndexBuffer_Release(oldIdxs);
2189 if (pIndexData) IWineD3DIndexBuffer_AddRef(This->stateBlock->pIndexData);
2190 return D3D_OK;
2193 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2194 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2196 *ppIndexData = This->stateBlock->pIndexData;
2198 /* up ref count on ppindexdata */
2199 if (*ppIndexData) IWineD3DIndexBuffer_AddRef(*ppIndexData);
2200 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2202 return D3D_OK;
2205 /*****
2206 * Get / Set Viewports
2207 *****/
2208 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2209 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2211 TRACE("(%p)\n", This);
2212 This->updateStateBlock->changed.viewport = TRUE;
2213 This->updateStateBlock->set.viewport = TRUE;
2214 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2216 /* Handle recording of state blocks */
2217 if (This->isRecordingState) {
2218 TRACE("Recording... not performing anything\n");
2219 return D3D_OK;
2222 ENTER_GL();
2224 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2225 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2227 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2228 checkGLcall("glDepthRange");
2229 /* Note: GL requires lower left, DirectX supplies upper left */
2230 /* TODO: replace usage of renderTarget with context management */
2231 glViewport(pViewport->X, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2232 pViewport->Width, pViewport->Height);
2233 checkGLcall("glViewport");
2235 LEAVE_GL();
2237 return D3D_OK;
2241 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2242 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2243 TRACE("(%p)\n", This);
2244 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2245 return D3D_OK;
2248 /*****
2249 * Get / Set Render States
2250 * TODO: Verify against dx9 definitions
2251 *****/
2252 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2254 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2255 DWORD OldValue = This->stateBlock->renderState[State];
2257 /* Simple way of referring to either a DWORD or a 4 byte float */
2258 union {
2259 DWORD d;
2260 float f;
2261 } tmpvalue;
2263 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2264 This->updateStateBlock->changed.renderState[State] = TRUE;
2265 This->updateStateBlock->set.renderState[State] = TRUE;
2266 This->updateStateBlock->renderState[State] = Value;
2268 /* Handle recording of state blocks */
2269 if (This->isRecordingState) {
2270 TRACE("Recording... not performing anything\n");
2271 return D3D_OK;
2274 ENTER_GL();
2276 switch (State) {
2277 case WINED3DRS_FILLMODE :
2278 switch ((D3DFILLMODE) Value) {
2279 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2280 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2281 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2282 default:
2283 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
2285 checkGLcall("glPolygonMode (fillmode)");
2286 break;
2288 case WINED3DRS_LIGHTING :
2289 if (Value) {
2290 glEnable(GL_LIGHTING);
2291 checkGLcall("glEnable GL_LIGHTING");
2292 } else {
2293 glDisable(GL_LIGHTING);
2294 checkGLcall("glDisable GL_LIGHTING");
2296 break;
2298 case WINED3DRS_ZENABLE :
2299 switch ((D3DZBUFFERTYPE) Value) {
2300 case D3DZB_FALSE:
2301 glDisable(GL_DEPTH_TEST);
2302 checkGLcall("glDisable GL_DEPTH_TEST");
2303 break;
2304 case D3DZB_TRUE:
2305 glEnable(GL_DEPTH_TEST);
2306 checkGLcall("glEnable GL_DEPTH_TEST");
2307 break;
2308 case D3DZB_USEW:
2309 glEnable(GL_DEPTH_TEST);
2310 checkGLcall("glEnable GL_DEPTH_TEST");
2311 FIXME("W buffer is not well handled\n");
2312 break;
2313 default:
2314 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2316 break;
2318 case WINED3DRS_CULLMODE :
2320 /* If we are culling "back faces with clockwise vertices" then
2321 set front faces to be counter clockwise and enable culling
2322 of back faces */
2323 switch ((D3DCULL) Value) {
2324 case D3DCULL_NONE:
2325 glDisable(GL_CULL_FACE);
2326 checkGLcall("glDisable GL_CULL_FACE");
2327 break;
2328 case D3DCULL_CW:
2329 glEnable(GL_CULL_FACE);
2330 checkGLcall("glEnable GL_CULL_FACE");
2331 if (This->renderUpsideDown) {
2332 glFrontFace(GL_CW);
2333 checkGLcall("glFrontFace GL_CW");
2334 } else {
2335 glFrontFace(GL_CCW);
2336 checkGLcall("glFrontFace GL_CCW");
2338 glCullFace(GL_BACK);
2339 break;
2340 case D3DCULL_CCW:
2341 glEnable(GL_CULL_FACE);
2342 checkGLcall("glEnable GL_CULL_FACE");
2343 if (This->renderUpsideDown) {
2344 glFrontFace(GL_CCW);
2345 checkGLcall("glFrontFace GL_CCW");
2346 } else {
2347 glFrontFace(GL_CW);
2348 checkGLcall("glFrontFace GL_CW");
2350 glCullFace(GL_BACK);
2351 break;
2352 default:
2353 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2355 break;
2357 case WINED3DRS_SHADEMODE :
2358 switch ((D3DSHADEMODE) Value) {
2359 case D3DSHADE_FLAT:
2360 glShadeModel(GL_FLAT);
2361 checkGLcall("glShadeModel");
2362 break;
2363 case D3DSHADE_GOURAUD:
2364 glShadeModel(GL_SMOOTH);
2365 checkGLcall("glShadeModel");
2366 break;
2367 case D3DSHADE_PHONG:
2368 FIXME("D3DSHADE_PHONG isn't supported?\n");
2370 LEAVE_GL();
2371 return D3DERR_INVALIDCALL;
2372 default:
2373 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2375 break;
2377 case WINED3DRS_DITHERENABLE :
2378 if (Value) {
2379 glEnable(GL_DITHER);
2380 checkGLcall("glEnable GL_DITHER");
2381 } else {
2382 glDisable(GL_DITHER);
2383 checkGLcall("glDisable GL_DITHER");
2385 break;
2387 case WINED3DRS_ZWRITEENABLE :
2388 if (Value) {
2389 glDepthMask(1);
2390 checkGLcall("glDepthMask");
2391 } else {
2392 glDepthMask(0);
2393 checkGLcall("glDepthMask");
2395 break;
2397 case WINED3DRS_ZFUNC :
2399 int glParm = GL_LESS;
2401 switch ((D3DCMPFUNC) Value) {
2402 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2403 case D3DCMP_LESS: glParm=GL_LESS; break;
2404 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2405 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2406 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2407 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2408 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2409 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2410 default:
2411 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2413 glDepthFunc(glParm);
2414 checkGLcall("glDepthFunc");
2416 break;
2418 case WINED3DRS_AMBIENT :
2420 float col[4];
2421 D3DCOLORTOGLFLOAT4(Value, col);
2422 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2423 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2424 checkGLcall("glLightModel for MODEL_AMBIENT");
2427 break;
2429 case WINED3DRS_ALPHABLENDENABLE :
2430 if (Value) {
2431 glEnable(GL_BLEND);
2432 checkGLcall("glEnable GL_BLEND");
2433 } else {
2434 glDisable(GL_BLEND);
2435 checkGLcall("glDisable GL_BLEND");
2437 break;
2439 case WINED3DRS_SRCBLEND :
2440 case WINED3DRS_DESTBLEND :
2442 int newVal = GL_ZERO;
2443 switch (Value) {
2444 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2445 case D3DBLEND_ONE : newVal = GL_ONE; break;
2446 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2447 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2448 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2449 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2450 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2451 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2452 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2453 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2454 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2456 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2457 This->srcBlend = newVal;
2458 This->dstBlend = newVal;
2459 break;
2461 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2462 This->srcBlend = newVal;
2463 This->dstBlend = newVal;
2464 break;
2465 default:
2466 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2469 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2470 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2471 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2472 glBlendFunc(This->srcBlend, This->dstBlend);
2474 checkGLcall("glBlendFunc");
2476 break;
2478 case WINED3DRS_ALPHATESTENABLE :
2479 if (Value) {
2480 glEnable(GL_ALPHA_TEST);
2481 checkGLcall("glEnable GL_ALPHA_TEST");
2482 } else {
2483 glDisable(GL_ALPHA_TEST);
2484 checkGLcall("glDisable GL_ALPHA_TEST");
2486 break;
2488 case WINED3DRS_ALPHAFUNC :
2490 int glParm = GL_LESS;
2491 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2493 switch ((D3DCMPFUNC) Value) {
2494 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2495 case D3DCMP_LESS: glParm = GL_LESS; break;
2496 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2497 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2498 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2499 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2500 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2501 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2502 default:
2503 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2505 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2506 glAlphaFunc(glParm, ref);
2507 This->alphafunc = glParm;
2508 checkGLcall("glAlphaFunc");
2510 break;
2512 case WINED3DRS_ALPHAREF :
2514 int glParm = This->alphafunc;
2515 float ref = 1.0f;
2517 ref = ((float) Value) / 255.0f;
2518 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2519 glAlphaFunc(glParm, ref);
2520 checkGLcall("glAlphaFunc");
2522 break;
2524 case WINED3DRS_CLIPPLANEENABLE :
2525 case WINED3DRS_CLIPPING :
2527 /* Ensure we only do the changed clip planes */
2528 DWORD enable = 0xFFFFFFFF;
2529 DWORD disable = 0x00000000;
2531 /* If enabling / disabling all */
2532 if (State == WINED3DRS_CLIPPING) {
2533 if (Value) {
2534 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2535 disable = 0x00;
2536 } else {
2537 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2538 enable = 0x00;
2540 } else {
2541 enable = Value & ~OldValue;
2542 disable = ~Value & OldValue;
2545 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2546 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2547 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2548 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2549 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2550 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2552 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2553 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2554 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2555 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2556 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2557 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2559 /** update clipping status */
2560 if (enable) {
2561 This->stateBlock->clip_status.ClipUnion = 0;
2562 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
2563 } else {
2564 This->stateBlock->clip_status.ClipUnion = 0;
2565 This->stateBlock->clip_status.ClipIntersection = 0;
2568 break;
2570 case WINED3DRS_BLENDOP :
2572 int glParm = GL_FUNC_ADD;
2574 switch ((D3DBLENDOP) Value) {
2575 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2576 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2577 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2578 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2579 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2580 default:
2581 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2583 TRACE("glBlendEquation(%x)\n", glParm);
2584 glBlendEquation(glParm);
2585 checkGLcall("glBlendEquation");
2587 break;
2589 case WINED3DRS_TEXTUREFACTOR :
2591 unsigned int i;
2593 /* Note the texture color applies to all textures whereas
2594 GL_TEXTURE_ENV_COLOR applies to active only */
2595 float col[4];
2596 D3DCOLORTOGLFLOAT4(Value, col);
2597 /* Set the default alpha blend color */
2598 glBlendColor(col[0], col[1], col[2], col[3]);
2599 checkGLcall("glBlendColor");
2601 /* And now the default texture color as well */
2602 for (i = 0; i < GL_LIMITS(textures); i++) {
2604 /* Note the D3DRS value applies to all textures, but GL has one
2605 per texture, so apply it now ready to be used! */
2606 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2607 GLACTIVETEXTURE(i);
2608 } else if (i>0) {
2609 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2612 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2613 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2616 break;
2618 case WINED3DRS_SPECULARENABLE :
2620 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2621 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2622 specular color. This is wrong:
2623 Separate specular color means the specular colour is maintained separately, whereas
2624 single color means it is merged in. However in both cases they are being used to
2625 some extent.
2626 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2627 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2628 running 1.4 yet!
2630 if (Value) {
2631 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2632 checkGLcall("glMaterialfv");
2633 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2634 glEnable(GL_COLOR_SUM_EXT);
2635 } else {
2636 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2638 checkGLcall("glEnable(GL_COLOR_SUM)");
2639 } else {
2640 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2642 /* for the case of enabled lighting: */
2643 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2644 checkGLcall("glMaterialfv");
2646 /* for the case of disabled lighting: */
2647 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2648 glDisable(GL_COLOR_SUM_EXT);
2649 } else {
2650 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2652 checkGLcall("glDisable(GL_COLOR_SUM)");
2655 break;
2657 case WINED3DRS_STENCILENABLE :
2658 if (Value) {
2659 glEnable(GL_STENCIL_TEST);
2660 checkGLcall("glEnable GL_STENCIL_TEST");
2661 } else {
2662 glDisable(GL_STENCIL_TEST);
2663 checkGLcall("glDisable GL_STENCIL_TEST");
2665 break;
2667 case WINED3DRS_STENCILFUNC :
2669 int glParm = GL_ALWAYS;
2670 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2671 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2673 switch ((D3DCMPFUNC) Value) {
2674 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2675 case D3DCMP_LESS: glParm=GL_LESS; break;
2676 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2677 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2678 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2679 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2680 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2681 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2682 default:
2683 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2685 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2686 This->stencilfunc = glParm;
2687 glStencilFunc(glParm, ref, mask);
2688 checkGLcall("glStencilFunc");
2690 break;
2692 case WINED3DRS_STENCILREF :
2694 int glParm = This->stencilfunc;
2695 int ref = 0;
2696 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2698 ref = Value;
2699 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2700 glStencilFunc(glParm, ref, mask);
2701 checkGLcall("glStencilFunc");
2703 break;
2705 case WINED3DRS_STENCILMASK :
2707 int glParm = This->stencilfunc;
2708 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2709 GLuint mask = Value;
2711 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2712 glStencilFunc(glParm, ref, mask);
2713 checkGLcall("glStencilFunc");
2715 break;
2717 case WINED3DRS_STENCILFAIL :
2719 GLenum fail ;
2720 GLenum zpass ;
2721 GLenum zfail ;
2723 fail = StencilOp(Value);
2724 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2725 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2726 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2727 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2729 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2730 glStencilOp(fail, zfail, zpass);
2731 checkGLcall("glStencilOp(fail, zfail, zpass);");
2733 break;
2734 case WINED3DRS_STENCILZFAIL :
2736 GLenum fail ;
2737 GLenum zpass ;
2738 GLenum zfail ;
2740 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2741 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2742 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2743 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2744 zfail = StencilOp(Value);
2746 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2747 glStencilOp(fail, zfail, zpass);
2748 checkGLcall("glStencilOp(fail, zfail, zpass);");
2750 break;
2751 case WINED3DRS_STENCILPASS :
2753 GLenum fail ;
2754 GLenum zpass ;
2755 GLenum zfail ;
2757 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2758 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2759 zpass = StencilOp(Value);
2760 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2761 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2763 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2764 glStencilOp(fail, zfail, zpass);
2765 checkGLcall("glStencilOp(fail, zfail, zpass);");
2767 break;
2769 case WINED3DRS_STENCILWRITEMASK :
2771 glStencilMask(Value);
2772 TRACE("glStencilMask(%lu)\n", Value);
2773 checkGLcall("glStencilMask");
2775 break;
2777 case WINED3DRS_FOGENABLE :
2779 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2780 glEnable(GL_FOG);
2781 checkGLcall("glEnable GL_FOG");
2782 } else {
2783 glDisable(GL_FOG);
2784 checkGLcall("glDisable GL_FOG");
2787 break;
2789 case WINED3DRS_RANGEFOGENABLE :
2791 if (Value) {
2792 TRACE("Enabled RANGEFOG");
2793 } else {
2794 TRACE("Disabled RANGEFOG");
2797 break;
2799 case WINED3DRS_FOGCOLOR :
2801 float col[4];
2802 D3DCOLORTOGLFLOAT4(Value, col);
2803 /* Set the default alpha blend color */
2804 glFogfv(GL_FOG_COLOR, &col[0]);
2805 checkGLcall("glFog GL_FOG_COLOR");
2807 break;
2809 case WINED3DRS_FOGTABLEMODE :
2811 glHint(GL_FOG_HINT, GL_NICEST);
2812 switch (Value) {
2813 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2814 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2815 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2816 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2817 default:
2818 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
2820 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2821 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
2824 break;
2826 case WINED3DRS_FOGVERTEXMODE :
2828 glHint(GL_FOG_HINT, GL_FASTEST);
2829 switch (Value) {
2830 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2831 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2832 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2833 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2834 default:
2835 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
2837 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2838 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
2841 break;
2843 case WINED3DRS_FOGSTART :
2845 tmpvalue.d = Value;
2846 glFogfv(GL_FOG_START, &tmpvalue.f);
2847 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2848 TRACE("Fog Start == %f\n", tmpvalue.f);
2850 break;
2852 case WINED3DRS_FOGEND :
2854 tmpvalue.d = Value;
2855 glFogfv(GL_FOG_END, &tmpvalue.f);
2856 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2857 TRACE("Fog End == %f\n", tmpvalue.f);
2859 break;
2861 case WINED3DRS_FOGDENSITY :
2863 tmpvalue.d = Value;
2864 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
2865 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2867 break;
2869 case WINED3DRS_VERTEXBLEND :
2871 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2872 TRACE("Vertex Blending state to %ld\n", Value);
2874 break;
2876 case WINED3DRS_TWEENFACTOR :
2878 tmpvalue.d = Value;
2879 This->updateStateBlock->tween_factor = tmpvalue.f;
2880 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
2882 break;
2884 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
2886 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2888 break;
2890 case WINED3DRS_COLORVERTEX :
2891 case WINED3DRS_DIFFUSEMATERIALSOURCE :
2892 case WINED3DRS_SPECULARMATERIALSOURCE :
2893 case WINED3DRS_AMBIENTMATERIALSOURCE :
2894 case WINED3DRS_EMISSIVEMATERIALSOURCE :
2896 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2898 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
2899 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2900 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
2901 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
2902 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
2903 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
2905 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2906 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2907 Parm = GL_AMBIENT_AND_DIFFUSE;
2908 } else {
2909 Parm = GL_DIFFUSE;
2911 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2912 Parm = GL_AMBIENT;
2913 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2914 Parm = GL_EMISSION;
2915 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2916 Parm = GL_SPECULAR;
2917 } else {
2918 Parm = -1;
2921 if (Parm == -1) {
2922 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2923 } else {
2924 This->tracking_color = NEEDS_TRACKING;
2925 This->tracking_parm = Parm;
2928 } else {
2929 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2932 break;
2934 case WINED3DRS_LINEPATTERN :
2936 union {
2937 DWORD d;
2938 D3DLINEPATTERN lp;
2939 } tmppattern;
2940 tmppattern.d = Value;
2942 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2944 if (tmppattern.lp.wRepeatFactor) {
2945 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2946 checkGLcall("glLineStipple(repeat, linepattern)");
2947 glEnable(GL_LINE_STIPPLE);
2948 checkGLcall("glEnable(GL_LINE_STIPPLE);");
2949 } else {
2950 glDisable(GL_LINE_STIPPLE);
2951 checkGLcall("glDisable(GL_LINE_STIPPLE);");
2954 break;
2956 case WINED3DRS_ZBIAS :
2958 if (Value) {
2959 tmpvalue.d = Value;
2960 TRACE("ZBias value %f\n", tmpvalue.f);
2961 glPolygonOffset(0, -tmpvalue.f);
2962 checkGLcall("glPolygonOffset(0, -Value)");
2963 glEnable(GL_POLYGON_OFFSET_FILL);
2964 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
2965 glEnable(GL_POLYGON_OFFSET_LINE);
2966 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
2967 glEnable(GL_POLYGON_OFFSET_POINT);
2968 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
2969 } else {
2970 glDisable(GL_POLYGON_OFFSET_FILL);
2971 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
2972 glDisable(GL_POLYGON_OFFSET_LINE);
2973 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
2974 glDisable(GL_POLYGON_OFFSET_POINT);
2975 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
2978 break;
2980 case WINED3DRS_NORMALIZENORMALS :
2981 if (Value) {
2982 glEnable(GL_NORMALIZE);
2983 checkGLcall("glEnable(GL_NORMALIZE);");
2984 } else {
2985 glDisable(GL_NORMALIZE);
2986 checkGLcall("glDisable(GL_NORMALIZE);");
2988 break;
2990 case WINED3DRS_POINTSIZE :
2991 tmpvalue.d = Value;
2992 TRACE("Set point size to %f\n", tmpvalue.f);
2993 glPointSize(tmpvalue.f);
2994 checkGLcall("glPointSize(...);");
2995 break;
2997 case WINED3DRS_POINTSIZE_MIN :
2998 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2999 tmpvalue.d = Value;
3000 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3001 checkGLcall("glPointParameterfEXT(...);");
3002 } else {
3003 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3005 break;
3007 case WINED3DRS_POINTSIZE_MAX :
3008 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3009 tmpvalue.d = Value;
3010 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3011 checkGLcall("glPointParameterfEXT(...);");
3012 } else {
3013 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3015 break;
3017 case WINED3DRS_POINTSCALE_A :
3018 case WINED3DRS_POINTSCALE_B :
3019 case WINED3DRS_POINTSCALE_C :
3020 case WINED3DRS_POINTSCALEENABLE :
3022 /* If enabled, supply the parameters, otherwise fall back to defaults */
3023 if (This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3024 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3025 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]);
3026 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]);
3027 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]);
3029 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3030 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3031 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3032 } else {
3033 TRACE("WINED3DRS_POINTSCALEENABLE not supported on this opengl\n");
3035 } else {
3036 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3037 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3038 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3039 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3040 } else {
3041 TRACE("WINED3DRS_POINTSCALEENABLE not supported, but not on either\n");
3044 break;
3047 case WINED3DRS_COLORWRITEENABLE :
3049 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3050 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3051 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3052 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3053 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3054 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3055 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3056 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3057 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3058 checkGLcall("glColorMask(...)");
3060 break;
3062 case WINED3DRS_LOCALVIEWER :
3064 GLint state = (Value) ? 1 : 0;
3065 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3066 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3068 break;
3070 case WINED3DRS_LASTPIXEL :
3072 if (Value) {
3073 TRACE("Last Pixel Drawing Enabled\n");
3074 } else {
3075 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3078 break;
3080 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3082 if (Value) {
3083 TRACE("Software Processing Enabled\n");
3084 } else {
3085 TRACE("Software Processing Disabled\n");
3088 break;
3090 /** not supported */
3091 case WINED3DRS_ZVISIBLE :
3093 LEAVE_GL();
3094 return D3DERR_INVALIDCALL;
3097 /* Unhandled yet...! */
3098 case WINED3DRS_EDGEANTIALIAS :
3099 case WINED3DRS_WRAP0 :
3100 case WINED3DRS_WRAP1 :
3101 case WINED3DRS_WRAP2 :
3102 case WINED3DRS_WRAP3 :
3103 case WINED3DRS_WRAP4 :
3104 case WINED3DRS_WRAP5 :
3105 case WINED3DRS_WRAP6 :
3106 case WINED3DRS_WRAP7 :
3107 case WINED3DRS_POINTSPRITEENABLE :
3108 case WINED3DRS_MULTISAMPLEANTIALIAS :
3109 case WINED3DRS_MULTISAMPLEMASK :
3110 case WINED3DRS_PATCHEDGESTYLE :
3111 case WINED3DRS_PATCHSEGMENTS :
3112 case WINED3DRS_DEBUGMONITORTOKEN :
3113 case WINED3DRS_POSITIONORDER :
3114 case WINED3DRS_NORMALORDER :
3115 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3116 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3117 break;
3118 default:
3119 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3122 LEAVE_GL();
3124 return D3D_OK;
3127 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3128 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3129 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3130 *pValue = This->stateBlock->renderState[State];
3131 return D3D_OK;
3134 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value){
3135 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3137 FIXME("(%p) : stub\n", This);
3138 return D3D_OK;
3141 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value){
3142 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3144 FIXME("(%p) : stub\n", This);
3145 return D3D_OK;
3149 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect){
3150 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3151 ENTER_GL();
3153 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3154 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3155 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3156 LEAVE_GL();
3157 return D3D_OK;
3160 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect){
3161 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3162 GLint scissorBox[4];
3164 ENTER_GL();
3165 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3166 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
3167 pRect->left = scissorBox[1];
3168 pRect->top = scissorBox[2];
3169 pRect->right = scissorBox[1] + scissorBox[3];
3170 pRect->bottom = scissorBox[2] + scissorBox[4];
3171 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3172 LEAVE_GL();
3173 return D3D_OK;
3176 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3177 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3179 TRACE("(%p) : pDecl=%p\n", This, pDecl);
3181 IWineD3DVertexDeclaration_AddRef(pDecl);
3182 if (NULL != This->updateStateBlock->vertexDecl) {
3183 IWineD3DVertexDeclaration_Release(This->updateStateBlock->vertexDecl);
3185 This->updateStateBlock->vertexDecl = pDecl;
3186 This->updateStateBlock->changed.vertexDecl = TRUE;
3187 This->updateStateBlock->set.vertexDecl = TRUE;
3188 return D3D_OK;
3191 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3192 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3194 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3196 *ppDecl = This->updateStateBlock->vertexDecl;
3197 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3198 return D3D_OK;
3201 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader){
3202 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3204 static BOOL showFixmes = TRUE;
3206 This->updateStateBlock->vertexShader = pShader;
3207 This->updateStateBlock->changed.vertexShader = TRUE;
3208 This->updateStateBlock->set.vertexShader = TRUE;
3210 if(pShader == NULL){
3211 /* clear down the shader */
3212 TRACE("Clear down the shader\n");
3213 }else{
3214 if(showFixmes){
3215 FIXME("(%p) : stub pShader(%p)\n", This, pShader);
3216 showFixmes = FALSE;
3220 return D3D_OK;
3222 /** FIXME: refernece counting? **/
3223 if (pShader == NULL) { /* only valid with non FVF shaders */
3224 TRACE_(d3d_shader)("(%p) : FVF Shader, pShader=%p\n", This, pShader);
3225 This->updateStateBlock->vertexShader = NULL;
3226 } else {
3227 TRACE_(d3d_shader)("(%p) : Created shader, pShader=%p\n", This, pShader);
3228 This->updateStateBlock->vertexShader = pShader;
3231 This->updateStateBlock->changed.vertexShader = TRUE;
3232 This->updateStateBlock->set.vertexShader = TRUE;
3234 /* Handle recording of state blocks */
3235 if (This->isRecordingState) {
3236 TRACE("Recording... not performing anything\n");
3237 return D3D_OK;
3240 * TODO: merge HAL shaders context switching from prototype
3242 return D3D_OK;
3246 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader){
3247 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3248 *ppShader = This->stateBlock->vertexShader;
3249 if(*ppShader != NULL)
3250 IWineD3DVertexShader_AddRef(*ppShader);
3251 TRACE("(%p) : returning %p\n", This, *ppShader);
3252 return D3D_OK;
3255 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
3256 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3258 TRACE("(%p) : stub\n", This);
3259 return D3D_OK;
3262 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
3263 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3264 TRACE("(%p) : stub\n", This);
3265 return D3D_OK;
3268 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
3269 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3270 TRACE("(%p) : stub\n", This);
3271 return D3D_OK;
3274 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
3275 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3276 TRACE("(%p) : stub\n", This);
3277 return D3D_OK;
3280 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
3281 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3282 TRACE("(%p) : stub\n", This);
3283 return D3D_OK;
3286 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
3287 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3288 TRACE("(%p) : stub\n", This);
3289 return D3D_OK;
3292 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader){
3293 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3294 TRACE("(%p) : stub\n", This);
3295 return D3D_OK;
3298 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader){
3299 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3300 TRACE("(%p) : stub\n", This);
3301 return D3D_OK;
3305 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
3306 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3307 TRACE("(%p) : stub\n", This);
3308 return D3D_OK;
3311 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
3312 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3313 TRACE("(%p) : stub\n", This);
3314 return D3D_OK;
3317 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
3318 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3319 TRACE("(%p) : stub\n", This);
3320 return D3D_OK;
3323 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
3324 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3325 TRACE("(%p) : stub\n", This);
3326 return D3D_OK;
3329 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
3330 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3331 TRACE("(%p) : stub\n", This);
3332 return D3D_OK;
3335 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
3336 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3337 TRACE("(%p) : stub\n", This);
3338 return D3D_OK;
3341 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags){
3342 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3343 FIXME("(%p) : stub\n", This);
3344 return D3D_OK;
3347 /*****
3348 * Get / Set Texture Stage States
3349 * TODO: Verify against dx9 definitions
3350 *****/
3351 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3352 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3353 union {
3354 float f;
3355 DWORD d;
3356 } tmpvalue;
3358 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3360 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3362 /* Reject invalid texture units */
3363 if (Stage >= GL_LIMITS(textures)) {
3364 TRACE("Attempt to access invalid texture rejected\n");
3365 return D3DERR_INVALIDCALL;
3368 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
3369 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
3370 This->updateStateBlock->textureState[Stage][Type] = Value;
3372 /* Handle recording of state blocks */
3373 if (This->isRecordingState) {
3374 TRACE("Recording... not performing anything\n");
3375 return D3D_OK;
3378 ENTER_GL();
3380 /* Make appropriate texture active */
3381 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3382 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3383 GLACTIVETEXTURE(Stage);
3384 } else if (Stage > 0) {
3385 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3388 switch (Type) {
3390 case D3DTSS_MINFILTER :
3391 case D3DTSS_MIPFILTER :
3393 DWORD ValueMIN = This->stateBlock->textureState[Stage][D3DTSS_MINFILTER];
3394 DWORD ValueMIP = This->stateBlock->textureState[Stage][D3DTSS_MIPFILTER];
3395 GLint realVal = GL_LINEAR;
3397 if (ValueMIN == D3DTEXF_NONE) {
3398 /* Doesn't really make sense - Windows just seems to disable
3399 mipmapping when this occurs */
3400 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3401 realVal = GL_LINEAR;
3402 } else if (ValueMIN == D3DTEXF_POINT) {
3403 /* GL_NEAREST_* */
3404 if (ValueMIP == D3DTEXF_NONE) {
3405 realVal = GL_NEAREST;
3406 } else if (ValueMIP == D3DTEXF_POINT) {
3407 realVal = GL_NEAREST_MIPMAP_NEAREST;
3408 } else if (ValueMIP == D3DTEXF_LINEAR) {
3409 realVal = GL_NEAREST_MIPMAP_LINEAR;
3410 } else {
3411 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3412 realVal = GL_NEAREST;
3414 } else if (ValueMIN == D3DTEXF_LINEAR) {
3415 /* GL_LINEAR_* */
3416 if (ValueMIP == D3DTEXF_NONE) {
3417 realVal = GL_LINEAR;
3418 } else if (ValueMIP == D3DTEXF_POINT) {
3419 realVal = GL_LINEAR_MIPMAP_NEAREST;
3420 } else if (ValueMIP == D3DTEXF_LINEAR) {
3421 realVal = GL_LINEAR_MIPMAP_LINEAR;
3422 } else {
3423 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3424 realVal = GL_LINEAR;
3426 } else if (ValueMIN == D3DTEXF_ANISOTROPIC) {
3427 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3428 if (ValueMIP == D3DTEXF_NONE) {
3429 realVal = GL_LINEAR_MIPMAP_LINEAR;
3430 } else if (ValueMIP == D3DTEXF_POINT) {
3431 realVal = GL_LINEAR_MIPMAP_NEAREST;
3432 } else if (ValueMIP == D3DTEXF_LINEAR) {
3433 realVal = GL_LINEAR_MIPMAP_LINEAR;
3434 } else {
3435 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3436 realVal = GL_LINEAR;
3438 } else {
3439 WARN("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MINFILTER. But not supported by OpenGL driver\n");
3440 realVal = GL_LINEAR;
3442 } else {
3443 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3444 realVal = GL_LINEAR_MIPMAP_LINEAR;
3447 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3448 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3449 checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
3451 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3453 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMIN) {
3454 glTexParameteri(This->stateBlock->textureDimensions[Stage],
3455 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3456 This->stateBlock->textureState[Stage][D3DTSS_MAXANISOTROPY]);
3457 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3460 break;
3462 case D3DTSS_MAGFILTER :
3464 DWORD ValueMAG = This->stateBlock->textureState[Stage][D3DTSS_MAGFILTER];
3465 GLint realVal = GL_NEAREST;
3467 if (ValueMAG == D3DTEXF_POINT) {
3468 realVal = GL_NEAREST;
3469 } else if (ValueMAG == D3DTEXF_LINEAR) {
3470 realVal = GL_LINEAR;
3471 } else if (ValueMAG == D3DTEXF_ANISOTROPIC) {
3472 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3473 realVal = GL_LINEAR;
3474 } else {
3475 FIXME("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MAGFILTER. But not supported by current OpenGL driver\n");
3476 realVal = GL_NEAREST;
3478 } else {
3479 FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", ValueMAG);
3480 realVal = GL_NEAREST;
3482 TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", ValueMAG, realVal);
3483 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, realVal);
3484 checkGLcall("glTexParameter GL_TEXTURE_MAG_FILTER, ...");
3486 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3488 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMAG) {
3489 glTexParameteri(This->stateBlock->textureDimensions[Stage],
3490 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3491 This->stateBlock->textureState[Stage][D3DTSS_MAXANISOTROPY]);
3492 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3495 break;
3497 case D3DTSS_MAXMIPLEVEL :
3500 * Not really the same, but the more apprioprate than nothing
3502 glTexParameteri(This->stateBlock->textureDimensions[Stage],
3503 GL_TEXTURE_BASE_LEVEL,
3504 This->stateBlock->textureState[Stage][D3DTSS_MAXMIPLEVEL]);
3505 checkGLcall("glTexParameteri GL_TEXTURE_BASE_LEVEL ...");
3507 break;
3509 case D3DTSS_MAXANISOTROPY :
3511 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3512 glTexParameteri(This->stateBlock->textureDimensions[Stage],
3513 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3514 This->stateBlock->textureState[Stage][D3DTSS_MAXANISOTROPY]);
3515 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3518 break;
3520 case D3DTSS_MIPMAPLODBIAS :
3522 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3523 tmpvalue.d = Value;
3524 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3525 GL_TEXTURE_LOD_BIAS_EXT,
3526 tmpvalue.f);
3527 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
3530 break;
3532 case D3DTSS_ALPHAOP :
3533 case D3DTSS_COLOROP :
3536 if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
3537 /* TODO: Disable by making this and all later levels disabled */
3538 glDisable(GL_TEXTURE_1D);
3539 checkGLcall("Disable GL_TEXTURE_1D");
3540 glDisable(GL_TEXTURE_2D);
3541 checkGLcall("Disable GL_TEXTURE_2D");
3542 glDisable(GL_TEXTURE_3D);
3543 checkGLcall("Disable GL_TEXTURE_3D");
3544 break; /* Don't bother setting the texture operations */
3545 } else {
3546 /* Enable only the appropriate texture dimension */
3547 if (Type == D3DTSS_COLOROP) {
3548 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3549 glEnable(GL_TEXTURE_1D);
3550 checkGLcall("Enable GL_TEXTURE_1D");
3551 } else {
3552 glDisable(GL_TEXTURE_1D);
3553 checkGLcall("Disable GL_TEXTURE_1D");
3555 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3556 if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
3557 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
3558 checkGLcall("Enable GL_TEXTURE_2D");
3559 } else {
3560 glEnable(GL_TEXTURE_2D);
3561 checkGLcall("Enable GL_TEXTURE_2D");
3563 } else {
3564 glDisable(GL_TEXTURE_2D);
3565 checkGLcall("Disable GL_TEXTURE_2D");
3567 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3568 glEnable(GL_TEXTURE_3D);
3569 checkGLcall("Enable GL_TEXTURE_3D");
3570 } else {
3571 glDisable(GL_TEXTURE_3D);
3572 checkGLcall("Disable GL_TEXTURE_3D");
3574 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3575 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3576 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3577 } else {
3578 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3579 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3583 /* Drop through... (Except disable case) */
3584 case D3DTSS_COLORARG0 :
3585 case D3DTSS_COLORARG1 :
3586 case D3DTSS_COLORARG2 :
3587 case D3DTSS_ALPHAARG0 :
3588 case D3DTSS_ALPHAARG1 :
3589 case D3DTSS_ALPHAARG2 :
3591 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 ||
3592 Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3593 if (isAlphaArg) {
3594 set_tex_op(iface, TRUE, Stage, This->stateBlock->textureState[Stage][D3DTSS_ALPHAOP],
3595 This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG1],
3596 This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG2],
3597 This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG0]);
3598 } else {
3599 set_tex_op(iface, FALSE, Stage, This->stateBlock->textureState[Stage][D3DTSS_COLOROP],
3600 This->stateBlock->textureState[Stage][D3DTSS_COLORARG1],
3601 This->stateBlock->textureState[Stage][D3DTSS_COLORARG2],
3602 This->stateBlock->textureState[Stage][D3DTSS_COLORARG0]);
3605 break;
3608 case D3DTSS_ADDRESSU :
3609 case D3DTSS_ADDRESSV :
3610 case D3DTSS_ADDRESSW :
3612 GLint wrapParm = GL_REPEAT;
3614 switch (Value) {
3615 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3616 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3617 case D3DTADDRESS_BORDER:
3619 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3620 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3621 } else {
3622 /* FIXME: Not right, but better */
3623 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3624 wrapParm = GL_REPEAT;
3627 break;
3628 case D3DTADDRESS_MIRROR:
3630 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3631 wrapParm = GL_MIRRORED_REPEAT_ARB;
3632 } else {
3633 /* Unsupported in OpenGL pre-1.4 */
3634 FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3635 wrapParm = GL_REPEAT;
3638 break;
3639 case D3DTADDRESS_MIRRORONCE:
3641 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3642 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3643 } else {
3644 FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3645 wrapParm = GL_REPEAT;
3648 break;
3650 default:
3651 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3652 wrapParm = GL_REPEAT;
3655 switch (Type) {
3656 case D3DTSS_ADDRESSU:
3657 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
3658 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3659 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3660 break;
3661 case D3DTSS_ADDRESSV:
3662 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
3663 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3664 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3665 break;
3666 case D3DTSS_ADDRESSW:
3667 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
3668 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3669 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3670 break;
3671 default: /* nop */
3672 break; /** stupic compilator */
3675 break;
3677 case D3DTSS_BORDERCOLOR :
3679 float col[4];
3680 D3DCOLORTOGLFLOAT4(Value, col);
3681 TRACE("Setting border color for %x to %lx\n", This->stateBlock->textureDimensions[Stage], Value);
3682 glTexParameterfv(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3683 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3685 break;
3687 case D3DTSS_TEXCOORDINDEX :
3689 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3691 /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include
3692 one flag, you can still specify an index value, which the system uses to
3693 determine the texture wrapping mode.
3694 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3695 means use the vertex position (camera-space) as the input texture coordinates
3696 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
3697 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3698 to the TEXCOORDINDEX value */
3700 /**
3701 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3703 switch (Value & 0xFFFF0000) {
3704 case D3DTSS_TCI_PASSTHRU:
3705 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3706 glDisable(GL_TEXTURE_GEN_S);
3707 glDisable(GL_TEXTURE_GEN_T);
3708 glDisable(GL_TEXTURE_GEN_R);
3709 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3710 break;
3712 case D3DTSS_TCI_CAMERASPACEPOSITION:
3713 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3714 as the input texture coordinates for this stage's texture transformation. This
3715 equates roughly to EYE_LINEAR */
3717 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3718 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3719 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3720 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3721 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3723 glMatrixMode(GL_MODELVIEW);
3724 glPushMatrix();
3725 glLoadIdentity();
3726 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3727 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3728 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3729 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3730 glPopMatrix();
3732 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3733 glEnable(GL_TEXTURE_GEN_S);
3734 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3735 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3736 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3737 glEnable(GL_TEXTURE_GEN_T);
3738 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3739 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3740 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3741 glEnable(GL_TEXTURE_GEN_R);
3742 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3743 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3744 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3746 break;
3748 case D3DTSS_TCI_CAMERASPACENORMAL:
3750 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3751 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3752 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3753 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3754 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3755 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3757 glMatrixMode(GL_MODELVIEW);
3758 glPushMatrix();
3759 glLoadIdentity();
3760 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3761 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3762 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3763 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3764 glPopMatrix();
3766 glEnable(GL_TEXTURE_GEN_S);
3767 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3768 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3769 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3770 glEnable(GL_TEXTURE_GEN_T);
3771 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3772 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3773 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3774 glEnable(GL_TEXTURE_GEN_R);
3775 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3776 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3777 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3780 break;
3782 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3784 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3785 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3786 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3787 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3788 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3789 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3791 glMatrixMode(GL_MODELVIEW);
3792 glPushMatrix();
3793 glLoadIdentity();
3794 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3795 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3796 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3797 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3798 glPopMatrix();
3800 glEnable(GL_TEXTURE_GEN_S);
3801 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3802 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3803 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3804 glEnable(GL_TEXTURE_GEN_T);
3805 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3806 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3807 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3808 glEnable(GL_TEXTURE_GEN_R);
3809 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3810 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3811 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3814 break;
3816 /* Unhandled types: */
3817 default:
3818 /* Todo: */
3819 /* ? disable GL_TEXTURE_GEN_n ? */
3820 glDisable(GL_TEXTURE_GEN_S);
3821 glDisable(GL_TEXTURE_GEN_T);
3822 glDisable(GL_TEXTURE_GEN_R);
3823 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
3824 break;
3827 break;
3829 /* Unhandled */
3830 case D3DTSS_TEXTURETRANSFORMFLAGS :
3831 set_texture_matrix((float *)&This->stateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
3832 break;
3834 case D3DTSS_BUMPENVMAT00 :
3835 case D3DTSS_BUMPENVMAT01 :
3836 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
3837 break;
3838 case D3DTSS_BUMPENVMAT10 :
3839 case D3DTSS_BUMPENVMAT11 :
3840 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
3841 break;
3843 case D3DTSS_BUMPENVLSCALE :
3844 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3845 break;
3847 case D3DTSS_BUMPENVLOFFSET :
3848 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3849 break;
3851 case D3DTSS_RESULTARG :
3852 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3853 break;
3855 default:
3856 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3857 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3860 LEAVE_GL();
3862 return D3D_OK;
3865 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
3866 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3867 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
3868 *pValue = This->updateStateBlock->textureState[Stage][Type];
3869 return D3D_OK;
3872 /*****
3873 * Get / Set Texture
3874 *****/
3875 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
3877 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3878 IWineD3DBaseTexture *oldTexture;
3879 BOOL reapplyStates = TRUE;
3880 DWORD reapplyFlags = 0;
3881 INT oldTextureDimensions = -1;
3882 D3DRESOURCETYPE textureType;
3884 oldTexture = This->updateStateBlock->textures[Stage];
3885 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3887 /* Reject invalid texture units */
3888 if (Stage >= GL_LIMITS(textures)) {
3889 TRACE("Attempt to access invalid texture rejected\n");
3890 return D3DERR_INVALIDCALL;
3893 This->updateStateBlock->set.textures[Stage] = TRUE;
3894 This->updateStateBlock->changed.textures[Stage] = TRUE;
3895 This->updateStateBlock->textures[Stage] = pTexture;
3897 /* Handle recording of state blocks */
3898 if (This->isRecordingState) {
3899 TRACE("Recording... not performing anything\n");
3900 return D3D_OK;
3903 oldTextureDimensions = This->updateStateBlock->textureDimensions[Stage];
3905 ENTER_GL();
3907 /* Make appropriate texture active */
3908 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3909 GLACTIVETEXTURE(Stage);
3911 } else if (Stage>0) {
3912 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3915 /** NOTE: MSDN says that setTexture increases the reference count,
3916 * and the the application nust set the texture back to null (or have a leaky application),
3917 * This means we should pass the refcount upto the parent
3918 *******************************/
3919 if (NULL != oldTexture) {
3921 IUnknown *textureParent;
3922 IWineD3DBaseTexture_GetParent(oldTexture, (IUnknown **)&textureParent);
3923 IUnknown_Release(textureParent);
3924 IUnknown_Release(textureParent); /** NOTE: Twice because GetParent adds a ref **/
3925 oldTexture = NULL;
3929 if (NULL != pTexture) {
3930 IUnknown *textureParent;
3931 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[Stage], (IUnknown **)&textureParent);
3932 /** NOTE: GetParent will increase the ref count for me, I won't clean up untill the texture is set to NULL **/
3934 /* Now setup the texture appropraitly */
3935 textureType = IWineD3DBaseTexture_GetType(pTexture);
3937 if (textureType == D3DRTYPE_TEXTURE) {
3939 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
3940 TRACE("Skipping setting texture as old == new\n");
3941 reapplyStates = FALSE;
3943 } else {
3945 /* Standard 2D texture */
3946 TRACE("Standard 2d texture\n");
3947 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3949 /* Load up the texture now */
3950 IWineD3DTexture_PreLoad((IWineD3DTexture *) pTexture);
3953 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3955 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
3956 TRACE("Skipping setting texture as old == new\n");
3957 reapplyStates = FALSE;
3959 } else {
3961 /* Standard 3D (volume) texture */
3962 TRACE("Standard 3d texture\n");
3963 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3965 /* Load up the texture now */
3966 IWineD3DVolumeTexture_PreLoad((IWineD3DVolumeTexture *) pTexture);
3969 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
3971 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
3972 TRACE("Skipping setting texture as old == new\n");
3973 reapplyStates = FALSE;
3975 } else {
3977 /* Standard Cube texture */
3978 TRACE("Standard Cube texture\n");
3979 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
3981 /* Load up the texture now */
3982 IWineD3DCubeTexture_PreLoad((IWineD3DCubeTexture *) pTexture);
3985 } else {
3986 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dresourcetype(textureType));
3989 } else {
3991 TRACE("Setting to no texture (ie default texture)\n");
3992 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3993 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3994 checkGLcall("glBindTexture");
3995 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3998 /* Disable the old texture binding and enable the new one (unless operations are disabled) */
3999 if (oldTextureDimensions != This->updateStateBlock->textureDimensions[Stage]) {
4001 glDisable(oldTextureDimensions);
4002 checkGLcall("Disable oldTextureDimensions");
4004 if (This->stateBlock->textureState[Stage][D3DTSS_COLOROP] != D3DTOP_DISABLE) {
4005 glEnable(This->updateStateBlock->textureDimensions[Stage]);
4006 checkGLcall("glEnable new texture dimensions");
4009 /* If Alpha arg1 is texture then handle the special case when there changes between a
4010 texture and no texture - See comments in set_tex_op */
4011 if ((This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
4012 (((oldTexture == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTexture != NULL))))
4014 reapplyFlags |= REAPPLY_ALPHAOP;
4019 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
4020 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
4021 if (reapplyStates) {
4022 IWineD3DDeviceImpl_SetupTextureStates(iface, Stage, reapplyFlags);
4025 LEAVE_GL();
4026 TRACE("Texture now fully setup\n");
4028 return D3D_OK;
4031 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4032 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4033 TRACE("(%p) : returning %p for stage %ld\n", This, This->updateStateBlock->textures[Stage], Stage);
4034 *ppTexture = (IWineD3DBaseTexture *) This->updateStateBlock->textures[Stage];
4035 if (*ppTexture)
4036 IWineD3DBaseTexture_AddRef(*ppTexture);
4037 return D3D_OK;
4040 /*****
4041 * Get Back Buffer
4042 *****/
4043 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type,
4044 IWineD3DSurface** ppBackBuffer) {
4045 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4046 IWineD3DSwapChain *swapChain;
4047 HRESULT hr;
4049 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4051 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4052 if(hr == D3D_OK){
4053 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4054 IWineD3DSwapChain_Release(swapChain);
4055 }else{
4056 *ppBackBuffer = NULL;
4058 return hr;
4061 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4062 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4063 WARN("(%p) : stub, calling idirect3d for now\n", This);
4064 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4067 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
4068 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4069 IWineD3DSwapChain *swapChain;
4070 HRESULT hr;
4072 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4073 if (hr == D3D_OK) {
4074 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4075 IWineD3DSwapChain_Release(swapChain);
4076 }else{
4077 FIXME("(%p) Error getting display mode\n", This);
4079 return hr;
4081 /*****
4082 * Stateblock related functions
4083 *****/
4085 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4086 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4087 IWineD3DStateBlockImpl *object;
4088 TRACE("(%p)", This);
4089 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4090 if(NULL == object ){
4091 FIXME("(%p)Error allocating memory for stateblock\n", This);
4092 return E_OUTOFMEMORY;
4094 TRACE("(%p) creted object %p\n", This, object);
4095 object->wineD3DDevice= This;
4096 /** FIXME: object->parent = parent; **/
4097 object->parent = NULL;
4098 object->blockType = D3DSBT_ALL;
4099 object->ref = 1;
4100 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
4102 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4103 This->updateStateBlock = object;
4104 This->isRecordingState = TRUE;
4106 TRACE("(%p) recording stateblock %p\n",This , object);
4107 return D3D_OK;
4110 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4111 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4113 if (!This->isRecordingState) {
4114 FIXME("(%p) not recording! returning error\n", This);
4115 *ppStateBlock = NULL;
4116 return D3DERR_INVALIDCALL;
4119 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4120 This->isRecordingState = FALSE;
4121 This->updateStateBlock = This->stateBlock;
4122 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4123 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4124 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4125 return D3D_OK;
4128 /*****
4129 * Scene related functions
4130 *****/
4131 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4132 /* At the moment we have no need for any functionality at the beginning
4133 of a scene */
4134 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4135 TRACE("(%p) : stub\n", This);
4136 return D3D_OK;
4139 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4140 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4141 TRACE("(%p)\n", This);
4142 ENTER_GL();
4143 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4144 glFlush();
4145 checkGLcall("glFlush");
4147 TRACE("End Scene\n");
4148 if(This->renderTarget != NULL){
4150 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4151 IUnknown *targetContainer = NULL;
4152 if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)) {
4153 TRACE("RenderTarget is either standalone of a texture.\n");
4154 /** always dirtify for now. we must find a better way to see that surface have been modified
4155 (Modifications should will only occur via draw-primitive, but we do need better locking
4156 switching to render-to-texture should remove the overhead though.
4158 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4159 IWineD3DBaseTexture_SetDirty((IWineD3DBaseTexture *)targetContainer, TRUE);
4160 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *)targetContainer);
4161 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4162 IUnknown_Release(targetContainer);
4167 LEAVE_GL();
4168 return D3D_OK;
4171 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4172 CONST RECT* pSourceRect, CONST RECT* pDestRect,
4173 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4174 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4175 IWineD3DSwapChain *swapChain = NULL;
4176 int i;
4177 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4179 TRACE("(%p) Presenting the frame\n", This);
4181 for(i = 0 ; i < swapchains ; i ++){
4183 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4184 TRACE("presentinng chain %d, %p\n", i, swapChain);
4185 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4186 IWineD3DSwapChain_Release(swapChain);
4189 return D3D_OK;
4192 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4193 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4194 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4196 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4197 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4198 when the depth-buffer format does not contain stencil buffer information, this method fails. */
4199 GLbitfield glMask = 0;
4200 GLboolean old_ztest;
4201 GLfloat old_z_clear_value;
4202 GLint old_stencil_clear_value;
4203 GLfloat old_color_clear_value[4];
4204 unsigned int i;
4205 CONST D3DRECT* curRect;
4207 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4208 Count, pRects, Flags, Z, Stencil);
4210 ENTER_GL();
4212 glEnable(GL_SCISSOR_TEST);
4213 checkGLcall("glEnable GL_SCISSOR_TEST");
4215 if (Count > 0 && pRects) {
4216 curRect = pRects;
4217 } else {
4218 curRect = NULL;
4221 /* Only set the values up once, as they are not changing */
4222 if (Flags & D3DCLEAR_STENCIL) {
4223 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4224 glClearStencil(Stencil);
4225 checkGLcall("glClearStencil");
4226 glMask = glMask | GL_STENCIL_BUFFER_BIT;
4227 glStencilMask(0xFFFFFFFF);
4230 if (Flags & D3DCLEAR_ZBUFFER) {
4231 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4232 glDepthMask(GL_TRUE);
4233 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4234 glClearDepth(Z);
4235 checkGLcall("glClearDepth");
4236 glMask = glMask | GL_DEPTH_BUFFER_BIT;
4239 if (Flags & D3DCLEAR_TARGET) {
4240 TRACE("Clearing screen with glClear to color %lx\n", Color);
4241 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4242 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
4243 ((Color >> 8) & 0xFF) / 255.0f,
4244 ((Color >> 0) & 0xFF) / 255.0f,
4245 ((Color >> 24) & 0xFF) / 255.0f);
4246 checkGLcall("glClearColor");
4248 /* Clear ALL colors! */
4249 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4250 glMask = glMask | GL_COLOR_BUFFER_BIT;
4253 /* Now process each rect in turn */
4254 for (i = 0; i < Count || i == 0; i++) {
4256 if (curRect) {
4257 /* Note gl uses lower left, width/height */
4258 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4259 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4260 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4261 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4262 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4263 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4264 checkGLcall("glScissor");
4265 } else {
4266 glScissor(This->stateBlock->viewport.X,
4267 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4268 This->stateBlock->viewport.Width,
4269 This->stateBlock->viewport.Height);
4270 checkGLcall("glScissor");
4273 /* Clear the selected rectangle (or full screen) */
4274 glClear(glMask);
4275 checkGLcall("glClear");
4277 /* Step to the next rectangle */
4278 if (curRect) curRect = curRect + sizeof(D3DRECT);
4281 /* Restore the old values (why..?) */
4282 if (Flags & D3DCLEAR_STENCIL) {
4283 glClearStencil(old_stencil_clear_value);
4284 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4286 if (Flags & D3DCLEAR_ZBUFFER) {
4287 glDepthMask(old_ztest);
4288 glClearDepth(old_z_clear_value);
4290 if (Flags & D3DCLEAR_TARGET) {
4291 glClearColor(old_color_clear_value[0],
4292 old_color_clear_value[1],
4293 old_color_clear_value[2],
4294 old_color_clear_value[3]);
4295 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4296 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4297 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4298 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4301 glDisable(GL_SCISSOR_TEST);
4302 checkGLcall("glDisable");
4303 LEAVE_GL();
4305 return D3D_OK;
4308 /*****
4309 * Drawing functions
4310 *****/
4311 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4312 UINT PrimitiveCount) {
4314 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4315 This->stateBlock->streamIsUP = FALSE;
4317 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4318 debug_d3dprimitivetype(PrimitiveType),
4319 StartVertex, PrimitiveCount);
4320 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
4322 return D3D_OK;
4325 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4326 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4327 D3DPRIMITIVETYPE PrimitiveType,
4328 INT baseVIndex, UINT minIndex,
4329 UINT NumVertices,UINT startIndex,UINT primCount) {
4331 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4332 UINT idxStride = 2;
4333 IWineD3DIndexBuffer *pIB;
4334 D3DINDEXBUFFER_DESC IdxBufDsc;
4336 pIB = This->stateBlock->pIndexData;
4337 This->stateBlock->streamIsUP = FALSE;
4339 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d \n", This,
4340 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4341 minIndex, NumVertices, startIndex, baseVIndex, primCount);
4343 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4344 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4345 idxStride = 2;
4346 } else {
4347 idxStride = 4;
4350 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex,
4351 startIndex, idxStride,
4352 ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory,
4353 minIndex);
4355 return D3D_OK;
4358 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4359 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4360 UINT VertexStreamZeroStride) {
4361 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4363 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4364 debug_d3dprimitivetype(PrimitiveType),
4365 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4367 if (This->stateBlock->stream_source[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->stream_source[0]);
4369 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4370 This->stateBlock->stream_source[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4371 This->stateBlock->stream_stride[0] = VertexStreamZeroStride;
4372 This->stateBlock->streamIsUP = TRUE;
4373 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
4374 This->stateBlock->stream_stride[0] = 0;
4375 This->stateBlock->stream_source[0] = NULL;
4377 /*stream zero settings set to null at end, as per the msdn */
4378 return D3D_OK;
4381 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4382 UINT MinVertexIndex,
4383 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
4384 WINED3DFORMAT IndexDataFormat, CONST void* pVertexStreamZeroData,
4385 UINT VertexStreamZeroStride) {
4386 int idxStride;
4387 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4389 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4390 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4391 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData,
4392 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4394 if (This->stateBlock->stream_source[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->stream_source[0]);
4396 if (IndexDataFormat == WINED3DFMT_INDEX16) {
4397 idxStride = 2;
4398 } else {
4399 idxStride = 4;
4402 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4403 This->stateBlock->stream_source[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4404 This->stateBlock->streamIsUP = TRUE;
4405 This->stateBlock->stream_stride[0] = VertexStreamZeroStride;
4407 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, idxStride, pIndexData, MinVertexIndex);
4409 /* stream zero settings set to null at end as per the msdn */
4410 This->stateBlock->stream_source[0] = NULL;
4411 This->stateBlock->stream_stride[0] = 0;
4412 IWineD3DDevice_SetIndices(iface, NULL, 0);
4414 return D3D_OK;
4417 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
4418 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4420 TRACE("(%p) : stub\n", This);
4421 return D3D_OK;
4424 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
4425 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
4426 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
4427 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4429 TRACE("(%p) : stub\n", This);
4430 return D3D_OK;
4432 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface){
4433 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4435 TRACE("(%p) : stub\n", This);
4436 return D3D_OK;
4439 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface){
4440 IWineD3DSwapChain *swapChain;
4441 HRESULT hr;
4442 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4443 if(hr == D3D_OK){
4444 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
4445 IWineD3DSwapChain_Release(swapChain);
4447 return hr;
4450 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4451 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4452 /* return a sensible default */
4453 *pNumPasses = 1;
4454 FIXME("(%p) : stub\n", This);
4455 return D3D_OK;
4458 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4459 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4460 FIXME("(%p) : stub\n", This);
4461 return D3D_OK;
4464 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4465 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4466 FIXME("(%p) : stub\n", This);
4467 return D3D_OK;
4470 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4471 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4472 FIXME("(%p) : stub\n", This);
4473 return D3D_OK;
4476 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4477 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4478 FIXME("(%p) : stub\n", This);
4479 return D3D_OK;
4482 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4483 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4484 FIXME("(%p) : stub\n", This);
4485 return D3D_OK;
4489 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4490 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4491 FIXME("(%p) : stub\n", This);
4492 return FALSE;
4496 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
4497 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4499 pRasterStatus->InVBlank = TRUE;
4500 pRasterStatus->ScanLine = 0;
4501 FIXME("(%p) : stub\n", This);
4502 return D3D_OK;
4506 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4507 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4508 static BOOL showfixmes = TRUE;
4509 if(nSegments != 0.0f){
4510 if( showfixmes){
4511 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4512 showfixmes = FALSE;
4515 return D3D_OK;
4518 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4519 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4520 static BOOL showfixmes = TRUE;
4521 if( showfixmes){
4522 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4523 showfixmes = FALSE;
4525 return 0.0f;
4529 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4530 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4531 FIXME("(%p) : stub\n", This);
4532 return D3D_OK;
4536 /* Implementation details at http://developer.nvidia.com/attach/6494
4538 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
4539 hmm.. no longer supported use
4540 OpenGL evaluators or tessellate surfaces within your application.
4543 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
4544 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo){
4545 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4546 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p) \n", This, Handle, pNumSegs, pRectPatchInfo);
4547 FIXME("(%p) : Stub\n", This);
4548 return D3D_OK;
4552 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
4553 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo){
4554 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4555 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p) \n", This, Handle, pNumSegs, pTriPatchInfo);
4556 FIXME("(%p) : Stub\n", This);
4557 return D3D_OK;
4560 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle){
4561 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4562 TRACE("(%p) Handle(%d)\n", This, Handle);
4563 FIXME("(%p) : Stub\n", This);
4564 return D3D_OK;
4567 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color){
4568 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4570 FIXME("(%p) : stub\n", This);
4571 return D3D_OK;
4574 /* rendertarget and deptth stencil functions */
4575 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget){
4576 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4578 /* FIXME: Implelent RenderTargetIndex >0 */
4579 if(RenderTargetIndex > 0)
4580 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
4582 *ppRenderTarget = (IWineD3DSurface *)This->renderTarget;
4583 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
4584 /* Note inc ref on returned surface */
4585 if(*ppRenderTarget != NULL)
4586 IWineD3DSurface_AddRef(*ppRenderTarget);
4587 return D3D_OK;
4590 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface){
4591 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4592 *ppZStencilSurface = (IWineD3DSurface *)This->depthStencilBuffer;
4593 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
4595 if(*ppZStencilSurface != NULL){
4596 /* Note inc ref on returned surface */
4597 IWineD3DSurface_AddRef(*ppZStencilSurface);
4599 return D3D_OK;
4602 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget){
4603 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4605 FIXME("(%p) : stub\n", This);
4606 return D3D_OK;
4609 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil){
4610 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4612 FIXME("(%p) : stub\n", This);
4613 return D3D_OK;
4616 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
4617 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
4618 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4619 /* TODO: the use of Impl is deprecated. */
4620 /* some basic validation checks */
4621 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
4623 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
4625 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
4626 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
4627 return D3DERR_INVALIDCALL;
4629 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
4630 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
4631 return D3DERR_INVALIDCALL;
4633 /* TODO: make the cursor 'real' */
4635 This->xHotSpot = XHotSpot;
4636 This->yHotSpot = YHotSpot;
4638 return D3D_OK;
4641 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
4642 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4643 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
4645 This->xScreenSpace = XScreenSpace;
4646 This->yScreenSpace = YScreenSpace;
4648 return;
4652 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
4653 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4654 TRACE("(%p) : visible(%d)\n", This, bShow);
4656 This->bCursorVisible = bShow;
4658 return D3D_OK;
4661 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
4662 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4663 FIXME("(%p) : stub\n", This); /* No way of notifying yet! */
4664 return D3D_OK;
4668 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
4669 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4670 /** FIXME: Resource tracking needs to be done,
4671 * The closes we can do to this is set the priorities of all managed textures low
4672 * and then reset them.
4673 ***********************************************************/
4674 FIXME("(%p) : stub\n", This);
4675 return D3D_OK;
4678 HRESULT WINAPI IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
4679 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4680 /** FIXME: Resource trascking needs to be done.
4681 * in effect this pulls all non only default
4682 * textures out of video memory and deletes all glTextures (glDeleteTextures)
4683 * and should clear down the context and set it up according to pPresentationParameters
4684 ***********************************************************/
4685 FIXME("(%p) : stub\n", This);
4686 return D3D_OK;
4689 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs){
4690 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4691 /** FIXME: always true at the moment **/
4692 if(bEnableDialogs == FALSE){
4693 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
4695 return D3D_OK;
4699 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
4700 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4702 FIXME("(%p) : stub\n", This);
4703 /* Setup some reasonable defaults */
4704 pParameters->AdapterOrdinal = 0; /* always for now */
4705 pParameters->DeviceType = D3DDEVTYPE_HAL; /* always for now */
4706 pParameters->hFocusWindow = 0;
4707 pParameters->BehaviorFlags =0;
4708 return D3D_OK;
4711 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
4712 IWineD3DSwapChain *swapchain;
4713 HRESULT hrc = D3D_OK;
4715 TRACE("Relaying to swapchain\n");
4717 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK){
4718 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (D3DGAMMARAMP *)pRamp);
4719 IWineD3DSwapChain_Release(swapchain);
4721 return;
4724 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
4725 IWineD3DSwapChain *swapchain;
4726 HRESULT hrc = D3D_OK;
4728 TRACE("Relaying to swapchain\n");
4730 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK){
4731 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
4732 IWineD3DSwapChain_Release(swapchain);
4734 return;
4737 /**********************************************************
4738 * IWineD3DDevice VTbl follows
4739 **********************************************************/
4741 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
4743 /*** IUnknown methods ***/
4744 IWineD3DDeviceImpl_QueryInterface,
4745 IWineD3DDeviceImpl_AddRef,
4746 IWineD3DDeviceImpl_Release,
4747 /*** IWineD3DDevice methods ***/
4748 IWineD3DDeviceImpl_GetParent,
4749 /*** Creation methods**/
4750 IWineD3DDeviceImpl_CreateVertexBuffer,
4751 IWineD3DDeviceImpl_CreateIndexBuffer,
4752 IWineD3DDeviceImpl_CreateStateBlock,
4753 IWineD3DDeviceImpl_CreateSurface,
4754 IWineD3DDeviceImpl_CreateTexture,
4755 IWineD3DDeviceImpl_CreateVolumeTexture,
4756 IWineD3DDeviceImpl_CreateVolume,
4757 IWineD3DDeviceImpl_CreateCubeTexture,
4758 IWineD3DDeviceImpl_CreateQuery,
4759 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
4760 IWineD3DDeviceImpl_CreateVertexDeclaration,
4761 IWineD3DDeviceImpl_CreateVertexShader,
4762 IWineD3DDeviceImpl_CreatePixelShader,
4764 /*** Odd functions **/
4765 IWineD3DDeviceImpl_EvictManagedResources,
4766 IWineD3DDeviceImpl_GetAvailableTextureMem,
4767 IWineD3DDeviceImpl_GetBackBuffer,
4768 IWineD3DDeviceImpl_GetCreationParameters,
4769 IWineD3DDeviceImpl_GetDeviceCaps,
4770 IWineD3DDeviceImpl_GetDirect3D,
4771 IWineD3DDeviceImpl_GetDisplayMode,
4772 IWineD3DDeviceImpl_GetNumberOfSwapChains,
4773 IWineD3DDeviceImpl_GetRasterStatus,
4774 IWineD3DDeviceImpl_GetSwapChain,
4775 IWineD3DDeviceImpl_Reset,
4776 IWineD3DDeviceImpl_SetDialogBoxMode,
4777 IWineD3DDeviceImpl_SetCursorProperties,
4778 IWineD3DDeviceImpl_SetCursorPosition,
4779 IWineD3DDeviceImpl_ShowCursor,
4780 IWineD3DDeviceImpl_TestCooperativeLevel,
4781 /*** Getters and setters **/
4782 IWineD3DDeviceImpl_SetClipPlane,
4783 IWineD3DDeviceImpl_GetClipPlane,
4784 IWineD3DDeviceImpl_SetClipStatus,
4785 IWineD3DDeviceImpl_GetClipStatus,
4786 IWineD3DDeviceImpl_SetCurrentTexturePalette,
4787 IWineD3DDeviceImpl_GetCurrentTexturePalette,
4788 IWineD3DDeviceImpl_SetDepthStencilSurface,
4789 IWineD3DDeviceImpl_GetDepthStencilSurface,
4790 IWineD3DDeviceImpl_SetFVF,
4791 IWineD3DDeviceImpl_GetFVF,
4792 IWineD3DDeviceImpl_SetGammaRamp,
4793 IWineD3DDeviceImpl_GetGammaRamp,
4794 IWineD3DDeviceImpl_SetIndices,
4795 IWineD3DDeviceImpl_GetIndices,
4796 IWineD3DDeviceImpl_SetLight,
4797 IWineD3DDeviceImpl_GetLight,
4798 IWineD3DDeviceImpl_SetLightEnable,
4799 IWineD3DDeviceImpl_GetLightEnable,
4800 IWineD3DDeviceImpl_SetMaterial,
4801 IWineD3DDeviceImpl_GetMaterial,
4802 IWineD3DDeviceImpl_SetNPatchMode,
4803 IWineD3DDeviceImpl_GetNPatchMode,
4804 IWineD3DDeviceImpl_SetPaletteEntries,
4805 IWineD3DDeviceImpl_GetPaletteEntries,
4806 IWineD3DDeviceImpl_SetPixelShader,
4807 IWineD3DDeviceImpl_GetPixelShader,
4808 IWineD3DDeviceImpl_SetPixelShaderConstantB,
4809 IWineD3DDeviceImpl_GetPixelShaderConstantB,
4810 IWineD3DDeviceImpl_SetPixelShaderConstantI,
4811 IWineD3DDeviceImpl_GetPixelShaderConstantI,
4812 IWineD3DDeviceImpl_SetPixelShaderConstantF,
4813 IWineD3DDeviceImpl_GetPixelShaderConstantF,
4814 IWineD3DDeviceImpl_SetRenderState,
4815 IWineD3DDeviceImpl_GetRenderState,
4816 IWineD3DDeviceImpl_SetRenderTarget,
4817 IWineD3DDeviceImpl_GetRenderTarget,
4818 IWineD3DDeviceImpl_SetSamplerState,
4819 IWineD3DDeviceImpl_GetSamplerState,
4820 IWineD3DDeviceImpl_SetScissorRect,
4821 IWineD3DDeviceImpl_GetScissorRect,
4822 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
4823 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
4824 IWineD3DDeviceImpl_SetStreamSource,
4825 IWineD3DDeviceImpl_GetStreamSource,
4826 IWineD3DDeviceImpl_SetStreamSourceFreq,
4827 IWineD3DDeviceImpl_GetStreamSourceFreq,
4828 IWineD3DDeviceImpl_SetTexture,
4829 IWineD3DDeviceImpl_GetTexture,
4830 IWineD3DDeviceImpl_SetTextureStageState,
4831 IWineD3DDeviceImpl_GetTextureStageState,
4832 IWineD3DDeviceImpl_SetTransform,
4833 IWineD3DDeviceImpl_GetTransform,
4834 IWineD3DDeviceImpl_SetVertexDeclaration,
4835 IWineD3DDeviceImpl_GetVertexDeclaration,
4836 IWineD3DDeviceImpl_SetVertexShader,
4837 IWineD3DDeviceImpl_GetVertexShader,
4838 IWineD3DDeviceImpl_SetVertexShaderConstantB,
4839 IWineD3DDeviceImpl_GetVertexShaderConstantB,
4840 IWineD3DDeviceImpl_SetVertexShaderConstantI,
4841 IWineD3DDeviceImpl_GetVertexShaderConstantI,
4842 IWineD3DDeviceImpl_SetVertexShaderConstantF,
4843 IWineD3DDeviceImpl_GetVertexShaderConstantF,
4844 IWineD3DDeviceImpl_SetViewport,
4845 IWineD3DDeviceImpl_GetViewport,
4846 IWineD3DDeviceImpl_MultiplyTransform,
4847 IWineD3DDeviceImpl_ValidateDevice,
4848 IWineD3DDeviceImpl_ProcessVertices,
4849 /*** State block ***/
4850 IWineD3DDeviceImpl_BeginStateBlock,
4851 IWineD3DDeviceImpl_EndStateBlock,
4852 /*** Scene management ***/
4853 IWineD3DDeviceImpl_BeginScene,
4854 IWineD3DDeviceImpl_EndScene,
4855 IWineD3DDeviceImpl_Present,
4856 IWineD3DDeviceImpl_Clear,
4857 /*** Drawing ***/
4858 IWineD3DDeviceImpl_DrawPrimitive,
4859 IWineD3DDeviceImpl_DrawIndexedPrimitive,
4860 IWineD3DDeviceImpl_DrawPrimitiveUP,
4861 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
4862 IWineD3DDeviceImpl_DrawRectPatch,
4863 IWineD3DDeviceImpl_DrawTriPatch,
4864 IWineD3DDeviceImpl_DeletePatch,
4865 IWineD3DDeviceImpl_ColorFill,
4866 IWineD3DDeviceImpl_UpdateTexture,
4867 IWineD3DDeviceImpl_UpdateSurface,
4868 IWineD3DDeviceImpl_StretchRect,
4869 IWineD3DDeviceImpl_GetRenderTargetData,
4870 IWineD3DDeviceImpl_GetFrontBufferData,
4871 /*** Internal use IWineD3DDevice methods ***/
4872 IWineD3DDeviceImpl_SetupTextureStates