Added support for vertex declarations to wined3d, it's the last patch
[wine/multimedia.git] / dlls / wined3d / device.c
blob3bd4f375610972007688a8c477c1bc69e4125f81
1 /*
2 * IWineD3DDevice implementation
4 * Copyright 2002-2005 Jason Edmeades
5 * Copyright 2003-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "config.h"
25 #include "wined3d_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
28 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
29 WINE_DECLARE_DEBUG_CHANNEL(d3d_fps);
30 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
31 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
33 /* x11drv GDI escapes */
34 #define X11DRV_ESCAPE 6789
35 enum x11drv_escape_codes
37 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
38 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
39 X11DRV_GET_FONT, /* get current X font for a DC */
42 /* retrieve the X display to use on a given DC */
43 inline static Display *get_display( HDC hdc )
45 Display *display;
46 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
48 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
49 sizeof(display), (LPSTR)&display )) display = NULL;
50 return display;
53 /* helper macros */
54 #define D3DMEMCHECK(object, ppResult) if(NULL == object){ *ppResult = NULL; WARN("Out of memory\n"); return D3DERR_OUTOFVIDEOMEMORY;}
56 #define D3DCREATEOBJECTINSTANCE(object, type){ \
57 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
58 D3DMEMCHECK(object, pp##type); \
59 object->lpVtbl = &IWineD3D##type##_Vtbl; \
60 object->wineD3DDevice = This; \
61 object->parent = parent; \
62 object->ref = 1; \
63 *pp##type = (IWineD3D##type *) object; \
66 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype){ \
67 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
68 D3DMEMCHECK(object, pp##type); \
69 object->lpVtbl = &IWineD3D##type##_Vtbl; \
70 object->resource.wineD3DDevice = This; \
71 object->resource.parent = parent; \
72 object->resource.resourceType = d3dtype; \
73 object->resource.ref = 1; \
74 object->resource.pool = Pool; \
75 object->resource.format = Format; \
76 object->resource.usage = Usage; \
77 object->resource.size = 0; \
78 object->resource.allocatedMemory = 0; \
79 *pp##type = (IWineD3D##type *) object; \
82 #define D3DINITILIZEBASETEXTURE(_basetexture) { \
83 _basetexture.levels = Levels; \
84 _basetexture.filterType = (Usage & D3DUSAGE_AUTOGENMIPMAP) ? D3DTEXF_LINEAR : D3DTEXF_NONE; \
85 _basetexture.LOD = 0; \
86 _basetexture.dirty = TRUE; \
89 /**********************************************************
90 * Global variable / Constants follow
91 **********************************************************/
92 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
94 /**********************************************************
95 * Utility functions follow
96 **********************************************************/
97 /* Convert the D3DLIGHT properties into equivalent gl lights */
98 void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
100 float quad_att;
101 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
102 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
104 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
105 glMatrixMode(GL_MODELVIEW);
106 glPushMatrix();
107 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
109 /* Diffuse: */
110 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
111 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
112 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
113 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
114 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
115 checkGLcall("glLightfv");
117 /* Specular */
118 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
119 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
120 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
121 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
122 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
123 checkGLcall("glLightfv");
125 /* Ambient */
126 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
127 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
128 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
129 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
130 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
131 checkGLcall("glLightfv");
133 /* Attenuation - Are these right? guessing... */
134 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
135 checkGLcall("glLightf");
136 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
137 checkGLcall("glLightf");
139 quad_att = 1.4/(lightInfo->OriginalParms.Range*lightInfo->OriginalParms.Range);
140 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
141 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
142 checkGLcall("glLightf");
144 switch (lightInfo->OriginalParms.Type) {
145 case D3DLIGHT_POINT:
146 /* Position */
147 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
148 checkGLcall("glLightfv");
149 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
150 checkGLcall("glLightf");
151 /* FIXME: Range */
152 break;
154 case D3DLIGHT_SPOT:
155 /* Position */
156 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
157 checkGLcall("glLightfv");
158 /* Direction */
159 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
160 checkGLcall("glLightfv");
161 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
162 checkGLcall("glLightf");
163 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
164 checkGLcall("glLightf");
165 /* FIXME: Range */
166 break;
168 case D3DLIGHT_DIRECTIONAL:
169 /* Direction */
170 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
171 checkGLcall("glLightfv");
172 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
173 checkGLcall("glLightf");
174 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
175 checkGLcall("glLightf");
176 break;
178 default:
179 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
182 /* Restore the modelview matrix */
183 glPopMatrix();
186 /* Apply the current values to the specified texture stage */
187 void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Stage, DWORD Flags) {
188 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
189 int i = 0;
190 float col[4];
191 BOOL changeTexture = TRUE;
193 TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
194 for (i = 1; i < HIGHEST_TEXTURE_STATE; i++) {
196 BOOL skip = FALSE;
198 switch (i) {
199 /* Performance: For texture states where multiples effect the outcome, only bother
200 applying the last one as it will pick up all the other values */
201 case WINED3DTSS_COLORARG0: /* Will be picked up when setting color op */
202 case WINED3DTSS_COLORARG1: /* Will be picked up when setting color op */
203 case WINED3DTSS_COLORARG2: /* Will be picked up when setting color op */
204 case WINED3DTSS_ALPHAARG0: /* Will be picked up when setting alpha op */
205 case WINED3DTSS_ALPHAARG1: /* Will be picked up when setting alpha op */
206 case WINED3DTSS_ALPHAARG2: /* Will be picked up when setting alpha op */
207 skip = TRUE;
208 break;
210 /* Performance: If the texture states only impact settings for the texture unit
211 (compared to the texture object) then there is no need to reapply them. The
212 only time they need applying is the first time, since we cheat and put the
213 values into the stateblock without applying.
214 Per-texture unit: texture function (eg. combine), ops and args
215 texture env color
216 texture generation settings
217 Note: Due to some special conditions there may be a need to do particular ones
218 of these, which is what the Flags allows */
219 case WINED3DTSS_COLOROP:
220 case WINED3DTSS_TEXCOORDINDEX:
221 if (!(Flags == REAPPLY_ALL)) skip=TRUE;
222 break;
224 case WINED3DTSS_ALPHAOP:
225 if (!(Flags & REAPPLY_ALPHAOP)) skip=TRUE;
226 break;
228 default:
229 skip = FALSE;
232 if (skip == FALSE) {
233 /* Performance: Only change to this texture if we have to */
234 if (changeTexture) {
235 /* Make appropriate texture active */
236 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
237 GLACTIVETEXTURE(Stage);
238 } else if (Stage > 0) {
239 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
241 changeTexture = FALSE;
244 /* Now apply the change */
245 IWineD3DDevice_SetTextureStageState(iface, Stage, i, This->stateBlock->textureState[Stage][i]);
249 /* apply the sampler states to the texture */
250 for (i = 1; i <= HIGHEST_SAMPLER_STATE;i++) {
251 IWineD3DDevice_SetSamplerState(iface, Stage, i, This->stateBlock->samplerState[Stage][i]);
254 /* Note the D3DRS value applies to all textures, but GL has one
255 * per texture, so apply it now ready to be used!
257 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
258 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
259 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
261 TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
264 /**********************************************************
265 * IUnknown parts follows
266 **********************************************************/
268 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
270 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
271 /* FIXME: This needs to extend an IWineD3DBaseObject */
273 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
274 if (IsEqualGUID(riid, &IID_IUnknown)
275 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
276 IUnknown_AddRef(iface);
277 *ppobj = This;
278 return D3D_OK;
281 return E_NOINTERFACE;
284 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
285 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
286 ULONG refCount = InterlockedIncrement(&This->ref);
288 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
289 return refCount;
292 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
293 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
294 ULONG refCount = InterlockedDecrement(&This->ref);
296 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
298 if (!refCount) {
299 /* TODO: Clean up all the surfaces and textures! */
300 /* FIXME: Create targets and state blocks in d3d8 */
301 if (((IWineD3DImpl *)This->wineD3D)->dxVersion > 8) { /*We don't create a state block in d3d8 yet*/
302 /* NOTE: You must release the parent if the objects was created via a callback
303 ** ***************************/
304 int i;
305 IUnknown* swapChainParent;
307 /* Release all of the swapchains, except the implicite swapchain (#0) */
308 for(i = 1; i < This->numberOfSwapChains; i++){
309 /* TODO: don't access swapchains[x] directly! */
310 IWineD3DSwapChain_Release(This->swapchains[i]);
313 if (This->stateBlock != NULL) {
314 IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->stateBlock);
317 if (This->swapchains[0] != NULL) {
318 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release it's parent now */
319 /* TODO: don't access swapchains[x] directly!, check that there are no-more swapchains left for this device! */
320 IWineD3DSwapChain_GetParent(This->swapchains[0], &swapChainParent);
321 IUnknown_Release(swapChainParent); /* once for the get parent */
322 if (IUnknown_Release(swapChainParent) > 0){ /* the second time for when it was created */
323 FIXME("(%p) Something's still holding the implicite swapchain\n",This);
328 IWineD3D_Release(This->wineD3D);
329 HeapFree(GetProcessHeap(), 0, This);
331 return refCount;
334 /**********************************************************
335 * IWineD3DDevice implementation follows
336 **********************************************************/
337 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
338 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
339 *pParent = This->parent;
340 IUnknown_AddRef(This->parent);
341 return D3D_OK;
344 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
345 DWORD FVF, D3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
346 IUnknown *parent) {
347 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
348 IWineD3DVertexBufferImpl *object;
349 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
350 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, D3DRTYPE_VERTEXBUFFER)
352 object->resource.size = Size;
353 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
354 object->FVF = FVF;
356 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
357 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
359 return D3D_OK;
362 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
363 WINED3DFORMAT Format, D3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
364 HANDLE *sharedHandle, IUnknown *parent) {
365 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
366 IWineD3DIndexBufferImpl *object;
367 TRACE("(%p) Creating index buffer\n", This);
369 /* Allocate the storage for the device */
370 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,D3DRTYPE_INDEXBUFFER)
372 object->resource.size = Length;
373 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
375 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
376 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
377 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
379 return D3D_OK;
382 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, D3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
384 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
385 IWineD3DStateBlockImpl *object;
386 int i,j;
388 D3DCREATEOBJECTINSTANCE(object, StateBlock)
389 object->blockType = Type;
391 /* Special case - Used during initialization to produce a placeholder stateblock
392 so other functions called can update a state block */
393 if (Type == (D3DSTATEBLOCKTYPE) 0) {
394 /* Don't bother increasing the reference count otherwise a device will never
395 be freed due to circular dependencies */
396 return D3D_OK;
399 /* Otherwise, might as well set the whole state block to the appropriate values */
400 IWineD3DDevice_AddRef(iface);
401 /* Otherwise, might as well set the whole state block to the appropriate values */
402 if ( This->stateBlock != NULL){
403 memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
404 } else {
405 memset(object->streamFreq, 1, sizeof(object->streamFreq));
408 /* Reset the ref and type after kluging it */
409 object->wineD3DDevice = This;
410 object->ref = 1;
411 object->blockType = Type;
413 TRACE("Updating changed flags appropriate for type %d\n", Type);
415 if (Type == D3DSBT_ALL) {
416 TRACE("ALL => Pretend everything has changed\n");
417 memset(&object->changed, TRUE, sizeof(This->stateBlock->changed));
418 } else if (Type == D3DSBT_PIXELSTATE) {
420 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
421 /* TODO: Pixel Shader Constants */
422 object->changed.pixelShader = TRUE;
423 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
424 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
426 for (j = 0; j < GL_LIMITS(textures); i++) {
427 for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
428 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
431 /* Setting sampler block changes states */
432 for (j = 0 ; j < GL_LIMITS(samplers); j++){
433 for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++){
435 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
438 } else if (Type == D3DSBT_VERTEXSTATE) {
440 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
442 /* TODO: Vertex Shader Constants */
443 object->changed.vertexShader = TRUE;
444 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
445 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
447 for (j = 0; j < GL_LIMITS(textures); i++) {
448 for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
449 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
452 /* Setting sampler block changes states */
453 for (j = 0 ; j < GL_LIMITS(samplers); j++){
454 for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++){
455 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
459 /* Duplicate light chain */
461 PLIGHTINFOEL *src = NULL;
462 PLIGHTINFOEL *dst = NULL;
463 PLIGHTINFOEL *newEl = NULL;
464 src = This->stateBlock->lights;
465 object->lights = NULL;
468 while (src) {
469 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
470 if (newEl == NULL) return D3DERR_OUTOFVIDEOMEMORY;
471 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
472 newEl->prev = dst;
473 newEl->changed = TRUE;
474 newEl->enabledChanged = TRUE;
475 if (dst == NULL) {
476 object->lights = newEl;
477 } else {
478 dst->next = newEl;
480 dst = newEl;
481 src = src->next;
486 } else {
487 FIXME("Unrecognized state block type %d\n", Type);
490 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
491 return D3D_OK;
495 /* ************************************
496 MSDN:
497 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
499 Discard
500 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
502 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.
504 ******************************** */
506 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) {
507 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
508 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
509 unsigned int pow2Width, pow2Height;
511 TRACE("(%p) Create surface\n",This);
513 /** FIXME: Check ranges on the inputs are valid
514 * MSDN
515 * MultisampleQuality
516 * [in] Quality level. The valid range is between zero and one less than the level
517 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
518 * Passing a larger value returns the error D3DERR_INVALIDCALL. The MultisampleQuality
519 * values of paired render targets, depth stencil surfaces, and the MultiSample type
520 * must all match.
521 *******************************/
525 * TODO: Discard MSDN
526 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
528 * If this flag is set, the contents of the depth stencil buffer will be
529 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
530 * with a different depth surface.
532 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
533 ***************************/
535 if(MultisampleQuality < 0) {
536 FIXME("Invalid multisample level %ld \n", MultisampleQuality);
537 return D3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
540 if(MultisampleQuality > 0){
541 FIXME("MultisampleQuality set to %ld, substituting 0 \n" , MultisampleQuality);
542 MultisampleQuality=0;
545 /* Non-power2 support */
547 /* Find the nearest pow2 match */
548 pow2Width = pow2Height = 1;
549 while (pow2Width < Width) pow2Width <<= 1;
550 while (pow2Height < Height) pow2Height <<= 1;
552 if((pow2Width > Width || pow2Height > Height) && !Usage & D3DUSAGE_RENDERTARGET) {
553 /** TODO: add support for non power two textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
554 FIXME("non-power-two textures unsupported\n");
555 return D3DERR_NOTAVAILABLE;
558 /** TODO: Check against the maximum texture sizes supported by the video card **/
560 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,D3DRTYPE_SURFACE)
561 object->container = (IUnknown*) This;
563 object->currentDesc.Width = Width;
564 object->currentDesc.Height = Height;
565 object->currentDesc.Level = Level;
566 object->currentDesc.MultiSampleType = MultiSample;
567 object->currentDesc.MultiSampleQuality = MultisampleQuality;
568 object->discard = Discard;
569 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
571 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
572 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
573 * space!
574 *********************************/
575 if (Format == WINED3DFMT_DXT1) {
576 /* DXT1 is half byte per pixel */
577 object->resource.size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4)) / 2;
579 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
580 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
581 object->resource.size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4));
582 } else {
583 object->resource.size = (Width * object->bytesPerPixel) * Height;
586 TRACE("Pool %d %d %d %d",Pool, D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM);
588 #if 0
589 /* TODO: Check that we have enough video ram left */
590 if(Pool == D3DPOOL_DEFAULT && IWineD3DDevice_GetAvailableTextureMem(iface) <= object->currentDesc.Size){
591 TRACE("Out of 'bogus' video memory\n");
592 HeapFree(GetProcessHeap(),0,object);
593 *ppSurface = NULL;
594 return D3DERR_OUTOFVIDEOMEMORY;
596 #endif
598 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
599 * this function is too deap to need to care about things like this.
600 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
601 * ****************************************/
602 switch(Pool) {
603 case D3DPOOL_SCRATCH:
604 if(Lockable == FALSE)
605 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
606 which are mutually exclusive, setting lockable to true\n");
607 Lockable = TRUE;
608 break;
609 case D3DPOOL_SYSTEMMEM:
610 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
611 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
612 case D3DPOOL_MANAGED:
613 if(Usage == D3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
614 Usage of DYNAMIC which are mutually exclusive, not doing \
615 anything just telling you.\n");
616 break;
617 case D3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
618 if(!(Usage & D3DUSAGE_DYNAMIC) && !(Usage & D3DUSAGE_RENDERTARGET)
619 && !(Usage && D3DUSAGE_DEPTHSTENCIL ) && Lockable == TRUE)
620 FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
621 break;
622 default:
623 FIXME("(%p) Unknown pool %d\n", This, Pool);
624 break;
627 if (Usage & D3DUSAGE_RENDERTARGET && Pool != D3DPOOL_DEFAULT){
628 FIXME("Trying to create a render target that isn't in the default pool\n");
632 object->locked = FALSE;
633 object->lockable = (WINED3DFMT_D16_LOCKABLE == Format) ? TRUE : Lockable;
634 /* TODO: memory management */
635 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
636 if(object->resource.allocatedMemory == NULL ) {
637 FIXME("Out of memory!\n");
638 HeapFree(GetProcessHeap(),0,object);
639 *ppSurface = NULL;
640 return D3DERR_OUTOFVIDEOMEMORY;
644 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
645 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
646 This, Width, Height, Format, debug_d3dformat(Format),
647 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
648 return D3D_OK;
652 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
653 DWORD Usage, WINED3DFORMAT Format, D3DPOOL Pool,
654 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
655 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
657 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
658 IWineD3DTextureImpl *object;
659 unsigned int i;
660 UINT tmpW;
661 UINT tmpH;
662 HRESULT hr;
664 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) .... \n", This, Width, Height, Levels, Usage);
666 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, D3DRTYPE_TEXTURE);
667 D3DINITILIZEBASETEXTURE(object->baseTexture);
668 object->width = Width;
669 object->height = Height;
671 /* Calculate levels for mip mapping */
672 if (Levels == 0) {
673 TRACE("calculating levels %d\n", object->baseTexture.levels);
674 object->baseTexture.levels++;
675 tmpW = Width;
676 tmpH = Height;
677 while (tmpW > 1 && tmpH > 1) {
678 tmpW = max(1, tmpW >> 1);
679 tmpH = max(1, tmpH >> 1);
680 object->baseTexture.levels++;
682 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
685 /* Generate all the surfaces */
686 tmpW = Width;
687 tmpH = Height;
688 for (i = 0; i < object->baseTexture.levels; i++)
690 /* use the callback to create the texture surface */
691 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
692 if(hr!= D3D_OK){
693 int j;
694 FIXME("Failed to create surface %p \n",object);
695 /* clean up */
696 for(j=0;j<i;j++){
697 IWineD3DSurface_Release(object->surfaces[j]);
699 /* heap free object */
700 HeapFree(GetProcessHeap(),0,object);
702 *ppTexture = NULL;
703 return hr;
706 IWineD3DSurface_SetContainer(object->surfaces[i], (IUnknown *)object);
707 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
708 /* calculate the next mipmap level */
709 tmpW = max(1, tmpW >> 1);
710 tmpH = max(1, tmpH >> 1);
713 TRACE("(%p) : Created texture %p\n", This, object);
714 return D3D_OK;
717 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
718 UINT Width, UINT Height, UINT Depth,
719 UINT Levels, DWORD Usage,
720 WINED3DFORMAT Format, D3DPOOL Pool,
721 IWineD3DVolumeTexture** ppVolumeTexture,
722 HANDLE* pSharedHandle, IUnknown *parent,
723 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
725 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
726 IWineD3DVolumeTextureImpl *object;
727 unsigned int i;
728 UINT tmpW;
729 UINT tmpH;
730 UINT tmpD;
732 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, D3DRTYPE_VOLUMETEXTURE);
733 D3DINITILIZEBASETEXTURE(object->baseTexture);
735 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
736 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
738 object->width = Width;
739 object->height = Height;
740 object->depth = Depth;
742 /* Calculate levels for mip mapping */
743 if (Levels == 0) {
744 object->baseTexture.levels++;
745 tmpW = Width;
746 tmpH = Height;
747 tmpD = Depth;
748 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
749 tmpW = max(1, tmpW >> 1);
750 tmpH = max(1, tmpH >> 1);
751 tmpD = max(1, tmpD >> 1);
752 object->baseTexture.levels++;
754 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
757 /* Generate all the surfaces */
758 tmpW = Width;
759 tmpH = Height;
760 tmpD = Depth;
762 for (i = 0; i < object->baseTexture.levels; i++)
764 /* Create the volume */
765 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
766 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
767 IWineD3DVolume_SetContainer(object->volumes[i], (IUnknown *)object);
769 tmpW = max(1, tmpW >> 1);
770 tmpH = max(1, tmpH >> 1);
771 tmpD = max(1, tmpD >> 1);
774 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
775 TRACE("(%p) : Created volume texture %p\n", This, object);
776 return D3D_OK;
779 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
780 UINT Width, UINT Height, UINT Depth,
781 DWORD Usage,
782 WINED3DFORMAT Format, D3DPOOL Pool,
783 IWineD3DVolume** ppVolume,
784 HANDLE* pSharedHandle, IUnknown *parent) {
786 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
787 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
789 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, D3DRTYPE_VOLUME)
791 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
792 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
794 object->currentDesc.Width = Width;
795 object->currentDesc.Height = Height;
796 object->currentDesc.Depth = Depth;
797 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
799 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
800 object->resource.size = (Width * object->bytesPerPixel) * Height * Depth;
801 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
802 object->lockable = TRUE;
803 object->locked = FALSE;
804 memset(&object->lockedBox, 0, sizeof(D3DBOX));
805 object->dirty = FALSE;
806 return IWineD3DVolume_CleanDirtyBox((IWineD3DVolume *) object);
809 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
810 UINT Levels, DWORD Usage,
811 WINED3DFORMAT Format, D3DPOOL Pool,
812 IWineD3DCubeTexture** ppCubeTexture,
813 HANDLE* pSharedHandle, IUnknown *parent,
814 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
816 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
817 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
818 unsigned int i,j;
819 UINT tmpW;
820 HRESULT hr;
822 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, D3DRTYPE_CUBETEXTURE);
823 D3DINITILIZEBASETEXTURE(object->baseTexture);
825 TRACE("(%p) Create Cube Texture \n", This);
827 object->edgeLength = EdgeLength;
829 /* Calculate levels for mip mapping */
830 if (Levels == 0) {
831 object->baseTexture.levels++;
832 tmpW = EdgeLength;
833 while (tmpW > 1) {
834 tmpW = max(1, tmpW / 2);
835 object->baseTexture.levels++;
837 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
840 /* Generate all the surfaces */
841 tmpW = EdgeLength;
842 for (i = 0; i < object->baseTexture.levels; i++) {
844 /* Create the 6 faces */
845 for (j = 0; j < 6; j++) {
847 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
848 i /* Level */, &object->surfaces[j][i],pSharedHandle);
850 if(hr!= D3D_OK){
851 /* clean up */
852 int k;
853 int l;
854 for (l=0;l<j;l++) {
855 IWineD3DSurface_Release(object->surfaces[j][i]);
857 for (k=0;k<i;k++) {
858 for (l=0;l<6;l++) {
859 IWineD3DSurface_Release(object->surfaces[l][j]);
863 FIXME("(%p) Failed to create surface\n",object);
864 HeapFree(GetProcessHeap(),0,object);
865 *ppCubeTexture = NULL;
866 return hr;
868 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IUnknown *)object);
869 TRACE("Created surface level %d @ %p, \n", i, object->surfaces[j][i]);
871 tmpW = max(1, tmpW >> 1);
874 TRACE("(%p) : Created Cube Texture %p\n", This, object);
875 *ppCubeTexture = (IWineD3DCubeTexture *) object;
876 return D3D_OK;
879 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent){
880 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
881 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
883 if(NULL == ppQuery){
884 /* Just a check to see if we support this type of query */
885 HRESULT hr = D3DERR_NOTAVAILABLE;
886 /* Lie and say everything is good (we can return ok fake data from a stub) */
887 switch(Type){
888 case WINED3DQUERYTYPE_VCACHE:
889 case WINED3DQUERYTYPE_RESOURCEMANAGER:
890 case WINED3DQUERYTYPE_VERTEXSTATS:
891 case WINED3DQUERYTYPE_EVENT:
892 case WINED3DQUERYTYPE_OCCLUSION:
893 case WINED3DQUERYTYPE_TIMESTAMP:
894 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
895 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
896 case WINED3DQUERYTYPE_PIPELINETIMINGS:
897 case WINED3DQUERYTYPE_INTERFACETIMINGS:
898 case WINED3DQUERYTYPE_VERTEXTIMINGS:
899 case WINED3DQUERYTYPE_PIXELTIMINGS:
900 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
901 case WINED3DQUERYTYPE_CACHEUTILIZATION:
902 hr = D3D_OK;
903 break;
904 default:
905 FIXME("(%p) Unhandled query type %d\n",This , Type);
907 FIXME("(%p) : Stub request for query type %d returned %ld\n", This, Type, hr);
908 return hr;
911 D3DCREATEOBJECTINSTANCE(object, Query)
912 object->type = Type;
913 object->extendedData = 0;
914 TRACE("(%p) : Created Query %p\n", This, object);
915 return D3D_OK;
918 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
919 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
920 IUnknown* parent,
921 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
922 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil){
923 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
925 HDC hDc;
926 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
927 int num;
928 XVisualInfo template;
929 GLXContext oldContext;
930 Drawable oldDrawable;
931 HRESULT hr = D3D_OK;
933 TRACE("(%p) : Created Aditional Swap Chain\n", This);
935 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
936 * does a device hold a reference to a swap chain giving them a lifetime of the device
937 * or does the swap chain notify the device of it'd destruction.
938 *******************************/
940 D3DCREATEOBJECTINSTANCE(object, SwapChain)
942 /* Initialize other useful values */
943 object->presentParms.BackBufferCount = 1; /* TODO:? support for gl_aux buffers */
945 /*********************
946 * Lookup the window Handle and the relating X window handle
947 ********************/
949 /* Setup hwnd we are using, plus which display this equates to */
950 object->win_handle = *(pPresentationParameters->hDeviceWindow);
951 if (!object->win_handle) {
952 object->win_handle = This->createParms.hFocusWindow;
955 object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window" );
956 hDc = GetDC(object->win_handle);
957 object->display = get_display(hDc);
958 ReleaseDC(object->win_handle, hDc);
959 TRACE("Using a display of %p %p \n", object->display, hDc);
961 if (NULL == object->display || NULL == hDc) {
962 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
963 return D3DERR_NOTAVAILABLE;
966 if (object->win == 0) {
967 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
968 return D3DERR_NOTAVAILABLE;
971 * Create an opengl context for the display visual
972 * NOTE: the visual is chosen as the window is created and the glcontext cannot
973 * use different properties after that point in time. FIXME: How to handle when requested format
974 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
975 * it chooses is identical to the one already being used!
976 **********************************/
978 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
979 ENTER_GL();
981 /* Create a new context for this swapchain */
982 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
983 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
984 (or the best possible if none is requested) */
985 TRACE("Found x visual ID : %ld\n", template.visualid);
987 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
988 if (NULL == object->visInfo) {
989 ERR("cannot really get XVisual\n");
990 LEAVE_GL();
991 return D3DERR_NOTAVAILABLE;
992 } else {
993 int n, value;
994 /* Write out some debug info about the visual/s */
995 TRACE("Using x visual ID : %ld\n", template.visualid);
996 TRACE(" visual info: %p\n", object->visInfo);
997 TRACE(" num items : %d\n", num);
998 for(n = 0;n < num; n++){
999 TRACE("=====item=====: %d\n", n + 1);
1000 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1001 TRACE(" screen : %d\n", object->visInfo[n].screen);
1002 TRACE(" depth : %u\n", object->visInfo[n].depth);
1003 TRACE(" class : %d\n", object->visInfo[n].class);
1004 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1005 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1006 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1007 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1008 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1009 /* log some extra glx info */
1010 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1011 TRACE(" gl_aux_buffers : %d\n", value);
1012 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1013 TRACE(" gl_buffer_size : %d\n", value);
1014 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1015 TRACE(" gl_red_size : %d\n", value);
1016 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1017 TRACE(" gl_green_size : %d\n", value);
1018 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1019 TRACE(" gl_blue_size : %d\n", value);
1020 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1021 TRACE(" gl_alpha_size : %d\n", value);
1022 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1023 TRACE(" gl_depth_size : %d\n", value);
1024 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1025 TRACE(" gl_stencil_size : %d\n", value);
1027 /* Now choose a simila visual ID*/
1029 #ifdef USE_CONTEXT_MANAGER
1031 /** TODO: use a context mamager **/
1032 #endif
1035 IWineD3DSwapChain *implSwapChain;
1036 if (D3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1037 /* The first time around we create the context that is shared with all other swapchians and render targets */
1038 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1039 TRACE("Creating implicite context for vis %p, hwnd %p\n", object->display, object->visInfo);
1040 } else {
1042 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1043 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1044 /* and create a new context with the implicit swapchains context as the shared context */
1045 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1046 IWineD3DSwapChain_Release(implSwapChain);
1050 /* Cleanup */
1051 XFree(object->visInfo);
1052 object->visInfo = NULL;
1054 if (NULL == object->glCtx) {
1055 ERR("cannot create glxContext\n");
1056 LEAVE_GL();
1057 return D3DERR_NOTAVAILABLE;
1060 LEAVE_GL();
1061 if (object->glCtx == NULL) {
1062 ERR("Error in context creation !\n");
1063 return D3DERR_INVALIDCALL;
1064 } else {
1065 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1066 object->win_handle, object->glCtx, object->win, object->visInfo);
1069 /*********************
1070 * Windowed / Fullscreen
1071 *******************/
1074 * TODO: MSDNsays that we are only allowed one fullscreen swapchain per device,
1075 * so we should really check to see if their is a fullscreen swapchain already
1076 * I think Windows and X have differnt ideas about fullscreen, does a single head count as full screen?
1077 **************************************/
1079 if (!*(pPresentationParameters->Windowed)) {
1081 DEVMODEW devmode;
1082 HDC hdc;
1083 int bpp = 0;
1085 /* Get info on the current display setup */
1086 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1087 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1088 DeleteDC(hdc);
1090 /* Change the display settings */
1091 memset(&devmode, 0, sizeof(DEVMODEW));
1092 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1093 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1094 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1095 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1096 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1097 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1099 /* Make popup window */
1100 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1101 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1102 *(pPresentationParameters->BackBufferWidth),
1103 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1109 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1110 * then the corresponding dimension of the client area of the hDeviceWindow
1111 * (or the focus window, if hDeviceWindow is NULL) is taken.
1112 **********************/
1114 if (*(pPresentationParameters->Windowed) &&
1115 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1116 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1118 RECT Rect;
1119 GetClientRect(object->win_handle, &Rect);
1121 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1122 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1123 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1125 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1126 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1127 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1131 /*********************
1132 * finish off parameter initialization
1133 *******************/
1135 /* Put the correct figures in the presentation parameters */
1136 TRACE("Coppying accross presentaion paraneters\n");
1137 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1138 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1139 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1140 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1141 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1142 object->presentParms.MultiSampleQuality = *(pPresentationParameters->MultiSampleQuality);
1143 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1144 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1145 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1146 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1147 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1148 object->presentParms.Flags = *(pPresentationParameters->Flags);
1149 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1150 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1153 /* FIXME: check for any failures */
1154 /*********************
1155 * Create the back, front and stencil buffers
1156 *******************/
1157 TRACE("calling rendertarget CB\n");
1158 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1159 object->presentParms.BackBufferWidth,
1160 object->presentParms.BackBufferHeight,
1161 object->presentParms.BackBufferFormat,
1162 object->presentParms.MultiSampleType,
1163 object->presentParms.MultiSampleQuality,
1164 TRUE /* Lockable */,
1165 &object->frontBuffer,
1166 NULL /* pShared (always null)*/);
1167 if (object->frontBuffer != NULL)
1168 IWineD3DSurface_SetContainer(object->frontBuffer, (IUnknown *)object);
1169 TRACE("calling rendertarget CB\n");
1170 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1171 object->presentParms.BackBufferWidth,
1172 object->presentParms.BackBufferHeight,
1173 object->presentParms.BackBufferFormat,
1174 object->presentParms.MultiSampleType,
1175 object->presentParms.MultiSampleQuality,
1176 TRUE /* Lockable */,
1177 &object->backBuffer,
1178 NULL /* pShared (always null)*/);
1179 if (object->backBuffer != NULL)
1180 IWineD3DSurface_SetContainer(object->backBuffer, (IUnknown *)object);
1182 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1183 if (pPresentationParameters->EnableAutoDepthStencil) {
1184 TRACE("Creating depth stencil buffer\n");
1185 if (This->depthStencilBuffer == NULL ) {
1186 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1187 object->presentParms.BackBufferWidth,
1188 object->presentParms.BackBufferHeight,
1189 object->presentParms.AutoDepthStencilFormat,
1190 object->presentParms.MultiSampleType,
1191 object->presentParms.MultiSampleQuality,
1192 FALSE /* FIXME: Discard */,
1193 &This->depthStencilBuffer,
1194 NULL /* pShared (always null)*/ );
1195 if (This->depthStencilBuffer != NULL)
1196 IWineD3DSurface_SetContainer(This->depthStencilBuffer, (IUnknown *)iface);
1199 /** TODO: A check on width, height and multisample types
1200 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1201 ****************************/
1202 object->wantsDepthStencilBuffer = TRUE;
1203 } else {
1204 object->wantsDepthStencilBuffer = FALSE;
1207 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1210 /*********************
1211 * init the default renderTarget management
1212 *******************/
1213 object->drawable = object->win;
1214 object->render_ctx = object->glCtx;
1216 if(hr == D3D_OK){
1217 /*********************
1218 * Setup some defaults and clear down the buffers
1219 *******************/
1220 ENTER_GL();
1221 /** save current context and drawable **/
1222 oldContext = glXGetCurrentContext();
1223 oldDrawable = glXGetCurrentDrawable();
1225 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1226 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1227 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1229 checkGLcall("glXMakeCurrent");
1231 TRACE("Setting up the screen\n");
1232 /* Clear the screen */
1233 glClearColor(0.0, 0.0, 0.0, 0.0);
1234 checkGLcall("glClearColor");
1235 glClearIndex(0);
1236 glClearDepth(1);
1237 glClearStencil(0xffff);
1239 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1240 checkGLcall("glClear");
1242 glColor3f(1.0, 1.0, 1.0);
1243 checkGLcall("glColor3f");
1245 glEnable(GL_LIGHTING);
1246 checkGLcall("glEnable");
1248 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1249 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1251 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1252 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1254 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1255 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1257 /* switch back to the original context (unless it was zero)*/
1258 if (This->numberOfSwapChains != 0) {
1259 /** TODO: restore the context and drawable **/
1260 glXMakeCurrent(object->display, oldDrawable, oldContext);
1263 LEAVE_GL();
1265 /* TODO: move this off into a linked list implementation! (add swapchain, remove swapchain or something along those lines) */
1266 #if 0
1267 IListOperator *listOperator;
1268 IListStore_CreateListOperator(This->swapchainStore, &listOperator);
1269 IListOperator_Append(listOperator, (void *)object);
1270 IListOperator_Release(listOperator);
1271 #endif
1273 This->swapchains[This->numberOfSwapChains++] = (IWineD3DSwapChain *)object;
1274 TRACE("Set swapchain to %p\n", object);
1275 } else { /* something went wrong so clean up */
1276 IUnknown* bufferParent;
1277 if (object->frontBuffer) {
1278 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1279 IUnknown_Release(bufferParent); /* once for the get parent */
1280 if(IUnknown_Release(bufferParent) > 0){
1281 FIXME("(%p) Something's still holding the front buffer\n",This);
1284 if (object->backBuffer) {
1285 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1286 IUnknown_Release(bufferParent); /* once for the get parent */
1287 if(IUnknown_Release(bufferParent) > 0){
1288 FIXME("(%p) Something's still holding the back buffer\n",This);
1291 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1292 /* Clean up the context */
1293 /* check that we are the current context first (we shouldn't be though!) */
1294 if (object->glCtx != 0) {
1295 if(glXGetCurrentContext() == object->glCtx){
1296 glXMakeCurrent(object->display, None, NULL);
1298 glXDestroyContext(object->display, object->glCtx);
1300 HeapFree(GetProcessHeap(), 0, object);
1303 return hr;
1306 /** NOTE: These are ahead of the other getters and setters to save using a forward declartion **/
1307 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1308 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1310 /* TODO: move over to using a linked list. */
1311 TRACE("(%p) returning %d\n", This, This->numberOfSwapChains);
1312 return This->numberOfSwapChains;
1315 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1316 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1317 TRACE("(%p) : swapchain %d \n", This, iSwapChain);
1319 if(iSwapChain >= IWineD3DDeviceImpl_GetNumberOfSwapChains(iface) || iSwapChain < 0){
1320 *pSwapChain = NULL;
1321 return D3DERR_INVALIDCALL;
1322 }else{
1323 /** TODO: move off to a linked list implementation **/
1324 *pSwapChain = This->swapchains[iSwapChain];
1327 /* TODO: move over to using stores and linked lists. */
1329 IWineD3DSwapChain_AddRef(*pSwapChain);
1330 TRACE("(%p) returning %p\n", This, *pSwapChain);
1331 return D3D_OK;
1334 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters){
1335 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1337 FIXME("(%p) : Stub\n",This);
1338 return D3D_OK;
1342 /*****
1343 * Vertex Declaration
1344 *****/
1345 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1346 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1347 IWineD3DVertexDeclarationImpl *object = NULL;
1348 HRESULT hr = D3D_OK;
1349 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1350 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1351 object->allFVF = 0;
1353 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1355 return hr;
1358 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1359 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DVertexShader** ppVertexShader, IUnknown *parent){
1360 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1361 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1362 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1363 object->function = pFunction;
1364 FIXME("(%p) : STUB: Created Vertex shader %p\n", This, ppVertexShader);
1365 return D3D_OK;
1369 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DPixelShader** ppPixelShader, IUnknown *parent){
1370 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1371 FIXME("(%p) : Stub\n", This);
1372 return D3D_OK;
1375 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice* iface, IWineD3D** ppD3D){
1376 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1377 *ppD3D= This->wineD3D;
1378 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1379 IWineD3D_AddRef(*ppD3D);
1380 return D3D_OK;
1384 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1385 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1386 FIXME("Stub :(%p) returning 64Mib\n", This);
1387 return 64*1024*1024;
1391 /*****
1392 * Get / Set FVF
1393 *****/
1394 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1395 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1397 /* Update the current state block */
1398 This->updateStateBlock->fvf = fvf;
1399 This->updateStateBlock->changed.fvf = TRUE;
1400 This->updateStateBlock->set.fvf = TRUE;
1402 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1403 /* clear down the vertex declaration
1404 NOTE: Axis and Allies doesn't work properly otherwise
1405 (may be a stateblock problem though!)
1407 /* No difference if recording or not */
1408 return IWineD3DDevice_SetVertexDeclaration(iface, NULL);
1413 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1414 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1415 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1416 *pfvf = This->stateBlock->fvf;
1417 return D3D_OK;
1420 /*****
1421 * Get / Set Stream Source
1422 *****/
1423 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1424 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1425 IWineD3DVertexBuffer *oldSrc;
1427 oldSrc = This->stateBlock->streamSource[StreamNumber];
1428 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1430 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
1431 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
1432 This->updateStateBlock->streamStride[StreamNumber] = Stride;
1433 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
1434 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
1436 /* Handle recording of state blocks */
1437 if (This->isRecordingState) {
1438 TRACE("Recording... not performing anything\n");
1439 return D3D_OK;
1442 /* Not recording... */
1443 if (oldSrc != NULL) IWineD3DVertexBuffer_Release(oldSrc);
1444 if (pStreamData != NULL) IWineD3DVertexBuffer_AddRef(pStreamData);
1446 return D3D_OK;
1449 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
1450 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1452 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
1453 *pStream = This->stateBlock->streamSource[StreamNumber];
1454 *pStride = This->stateBlock->streamStride[StreamNumber];
1455 *pOffset = This->stateBlock->streamOffset[StreamNumber];
1456 if (*pStream != NULL) IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
1457 return D3D_OK;
1460 /*Should be quite easy, just an extension of vertexdata
1461 ref...
1462 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1464 The divider is a bit odd though
1466 VertexOffset = StartVertex / Divider * StreamStride +
1467 VertexIndex / Divider * StreamStride + StreamOffset
1470 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider){
1471 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1473 FIXME("(%p) : stub\n", This);
1474 return D3D_OK;
1477 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider){
1478 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1480 FIXME("(%p) : stub\n", This);
1481 return D3D_OK;
1485 /*****
1486 * Get / Set & Multipy Transform
1487 *****/
1488 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1489 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1491 /* Most of this routine, comments included copied from ddraw tree initially: */
1492 TRACE("(%p) : Transform State=%d\n", This, d3dts);
1494 /* Handle recording of state blocks */
1495 if (This->isRecordingState) {
1496 TRACE("Recording... not performing anything\n");
1497 This->updateStateBlock->changed.transform[d3dts] = TRUE;
1498 This->updateStateBlock->set.transform[d3dts] = TRUE;
1499 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1500 return D3D_OK;
1504 * If the new matrix is the same as the current one,
1505 * we cut off any further processing. this seems to be a reasonable
1506 * optimization because as was noticed, some apps (warcraft3 for example)
1507 * tend towards setting the same matrix repeatedly for some reason.
1509 * From here on we assume that the new matrix is different, wherever it matters.
1511 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1512 TRACE("The app is setting the same matrix over again\n");
1513 return D3D_OK;
1514 } else {
1515 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1519 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1520 where ViewMat = Camera space, WorldMat = world space.
1522 In OpenGL, camera and world space is combined into GL_MODELVIEW
1523 matrix. The Projection matrix stay projection matrix.
1526 /* Capture the times we can just ignore the change for now */
1527 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1528 This->modelview_valid = FALSE;
1529 return D3D_OK;
1531 } else if (d3dts == D3DTS_PROJECTION) {
1532 This->proj_valid = FALSE;
1533 return D3D_OK;
1535 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1536 /* Indexed Vertex Blending Matrices 256 -> 511 */
1537 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1538 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1539 return D3D_OK;
1542 /* Now we really are going to have to change a matrix */
1543 ENTER_GL();
1545 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1546 if (d3dts < GL_LIMITS(textures)) {
1547 int tex = d3dts - D3DTS_TEXTURE0;
1548 GLACTIVETEXTURE(tex);
1549 set_texture_matrix((float *)lpmatrix,
1550 This->updateStateBlock->textureState[tex][WINED3DTSS_TEXTURETRANSFORMFLAGS]);
1553 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1554 unsigned int k;
1556 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1557 * NOTE: We have to reset the positions even if the light/plane is not currently
1558 * enabled, since the call to enable it will not reset the position.
1559 * NOTE2: Apparently texture transforms do NOT need reapplying
1562 PLIGHTINFOEL *lightChain = NULL;
1563 This->modelview_valid = FALSE;
1564 This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
1566 glMatrixMode(GL_MODELVIEW);
1567 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1568 glPushMatrix();
1569 glLoadMatrixf((float *)lpmatrix);
1570 checkGLcall("glLoadMatrixf(...)");
1572 /* Reset lights */
1573 lightChain = This->stateBlock->lights;
1574 while (lightChain && lightChain->glIndex != -1) {
1575 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1576 checkGLcall("glLightfv posn");
1577 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1578 checkGLcall("glLightfv dirn");
1579 lightChain = lightChain->next;
1582 /* Reset Clipping Planes if clipping is enabled */
1583 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1584 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1585 checkGLcall("glClipPlane");
1587 glPopMatrix();
1589 } else { /* What was requested!?? */
1590 WARN("invalid matrix specified: %i\n", d3dts);
1593 /* Release lock, all done */
1594 LEAVE_GL();
1595 return D3D_OK;
1598 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1599 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1600 TRACE("(%p) : for Transform State %d\n", This, State);
1601 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1602 return D3D_OK;
1605 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1606 D3DMATRIX *mat = NULL;
1607 D3DMATRIX temp;
1609 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1610 * below means it will be recorded in a state block change, but it
1611 * works regardless where it is recorded.
1612 * If this is found to be wrong, change to StateBlock.
1614 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1615 TRACE("(%p) : For state %u\n", This, State);
1617 if (State < HIGHEST_TRANSFORMSTATE)
1619 mat = &This->updateStateBlock->transforms[State];
1620 } else {
1621 FIXME("Unhandled transform state!!\n");
1624 /* Copied from ddraw code: */
1625 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);
1626 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);
1627 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);
1628 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);
1630 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);
1631 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);
1632 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);
1633 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);
1635 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);
1636 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);
1637 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);
1638 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);
1640 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);
1641 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);
1642 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);
1643 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);
1645 /* Apply change via set transform - will reapply to eg. lights this way */
1646 IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
1647 return D3D_OK;
1650 /*****
1651 * Get / Set Light
1652 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
1653 *****/
1654 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1655 you can reference any indexes you want as long as that number max are enabled at any
1656 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1657 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1658 but when recording, just build a chain pretty much of commands to be replayed. */
1660 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
1661 float rho;
1662 PLIGHTINFOEL *object, *temp;
1664 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1665 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1667 /* If recording state block, just add to end of lights chain */
1668 if (This->isRecordingState) {
1669 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1670 if (NULL == object) {
1671 return D3DERR_OUTOFVIDEOMEMORY;
1673 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1674 object->OriginalIndex = Index;
1675 object->glIndex = -1;
1676 object->changed = TRUE;
1678 /* Add to the END of the chain of lights changes to be replayed */
1679 if (This->updateStateBlock->lights == NULL) {
1680 This->updateStateBlock->lights = object;
1681 } else {
1682 temp = This->updateStateBlock->lights;
1683 while (temp->next != NULL) temp=temp->next;
1684 temp->next = object;
1686 TRACE("Recording... not performing anything more\n");
1687 return D3D_OK;
1690 /* Ok, not recording any longer so do real work */
1691 object = This->stateBlock->lights;
1692 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1694 /* If we didn't find it in the list of lights, time to add it */
1695 if (object == NULL) {
1696 PLIGHTINFOEL *insertAt,*prevPos;
1698 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1699 if (NULL == object) {
1700 return D3DERR_OUTOFVIDEOMEMORY;
1702 object->OriginalIndex = Index;
1703 object->glIndex = -1;
1705 /* Add it to the front of list with the idea that lights will be changed as needed
1706 BUT after any lights currently assigned GL indexes */
1707 insertAt = This->stateBlock->lights;
1708 prevPos = NULL;
1709 while (insertAt != NULL && insertAt->glIndex != -1) {
1710 prevPos = insertAt;
1711 insertAt = insertAt->next;
1714 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1715 This->stateBlock->lights = object;
1716 } else if (insertAt == NULL) { /* End of list */
1717 prevPos->next = object;
1718 object->prev = prevPos;
1719 } else { /* Middle of chain */
1720 if (prevPos == NULL) {
1721 This->stateBlock->lights = object;
1722 } else {
1723 prevPos->next = object;
1725 object->prev = prevPos;
1726 object->next = insertAt;
1727 insertAt->prev = object;
1731 /* Initialze the object */
1732 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,
1733 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1734 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1735 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1736 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1737 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1738 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1740 /* Save away the information */
1741 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1743 switch (pLight->Type) {
1744 case D3DLIGHT_POINT:
1745 /* Position */
1746 object->lightPosn[0] = pLight->Position.x;
1747 object->lightPosn[1] = pLight->Position.y;
1748 object->lightPosn[2] = pLight->Position.z;
1749 object->lightPosn[3] = 1.0f;
1750 object->cutoff = 180.0f;
1751 /* FIXME: Range */
1752 break;
1754 case D3DLIGHT_DIRECTIONAL:
1755 /* Direction */
1756 object->lightPosn[0] = -pLight->Direction.x;
1757 object->lightPosn[1] = -pLight->Direction.y;
1758 object->lightPosn[2] = -pLight->Direction.z;
1759 object->lightPosn[3] = 0.0;
1760 object->exponent = 0.0f;
1761 object->cutoff = 180.0f;
1762 break;
1764 case D3DLIGHT_SPOT:
1765 /* Position */
1766 object->lightPosn[0] = pLight->Position.x;
1767 object->lightPosn[1] = pLight->Position.y;
1768 object->lightPosn[2] = pLight->Position.z;
1769 object->lightPosn[3] = 1.0;
1771 /* Direction */
1772 object->lightDirn[0] = pLight->Direction.x;
1773 object->lightDirn[1] = pLight->Direction.y;
1774 object->lightDirn[2] = pLight->Direction.z;
1775 object->lightDirn[3] = 1.0;
1778 * opengl-ish and d3d-ish spot lights use too different models for the
1779 * light "intensity" as a function of the angle towards the main light direction,
1780 * so we only can approximate very roughly.
1781 * however spot lights are rather rarely used in games (if ever used at all).
1782 * furthermore if still used, probably nobody pays attention to such details.
1784 if (pLight->Falloff == 0) {
1785 rho = 6.28f;
1786 } else {
1787 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1789 if (rho < 0.0001) rho = 0.0001f;
1790 object->exponent = -0.3/log(cos(rho/2));
1791 object->cutoff = pLight->Phi*90/M_PI;
1793 /* FIXME: Range */
1794 break;
1796 default:
1797 FIXME("Unrecognized light type %d\n", pLight->Type);
1800 /* Update the live definitions if the light is currently assigned a glIndex */
1801 if (object->glIndex != -1) {
1802 setup_light(iface, object->glIndex, object);
1804 return D3D_OK;
1807 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
1808 PLIGHTINFOEL *lightInfo = NULL;
1809 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1810 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1812 /* Locate the light in the live lights */
1813 lightInfo = This->stateBlock->lights;
1814 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1816 if (lightInfo == NULL) {
1817 TRACE("Light information requested but light not defined\n");
1818 return D3DERR_INVALIDCALL;
1821 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
1822 return D3D_OK;
1825 /*****
1826 * Get / Set Light Enable
1827 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
1828 *****/
1829 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
1830 PLIGHTINFOEL *lightInfo = NULL;
1831 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1832 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1834 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1835 if (This->isRecordingState) {
1836 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1837 if (NULL == lightInfo) {
1838 return D3DERR_OUTOFVIDEOMEMORY;
1840 lightInfo->OriginalIndex = Index;
1841 lightInfo->glIndex = -1;
1842 lightInfo->enabledChanged = TRUE;
1844 /* Add to the END of the chain of lights changes to be replayed */
1845 if (This->updateStateBlock->lights == NULL) {
1846 This->updateStateBlock->lights = lightInfo;
1847 } else {
1848 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
1849 while (temp->next != NULL) temp=temp->next;
1850 temp->next = lightInfo;
1852 TRACE("Recording... not performing anything more\n");
1853 return D3D_OK;
1856 /* Not recording... So, locate the light in the live lights */
1857 lightInfo = This->stateBlock->lights;
1858 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1860 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1861 if (lightInfo == NULL) {
1862 D3DLIGHT9 lightParms;
1863 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1864 wait until someone confirms it seems to work! */
1865 TRACE("Light enabled requested but light not defined, so defining one!\n");
1866 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1867 lightParms.Diffuse.r = 1.0;
1868 lightParms.Diffuse.g = 1.0;
1869 lightParms.Diffuse.b = 1.0;
1870 lightParms.Diffuse.a = 0.0;
1871 lightParms.Specular.r = 0.0;
1872 lightParms.Specular.g = 0.0;
1873 lightParms.Specular.b = 0.0;
1874 lightParms.Specular.a = 0.0;
1875 lightParms.Ambient.r = 0.0;
1876 lightParms.Ambient.g = 0.0;
1877 lightParms.Ambient.b = 0.0;
1878 lightParms.Ambient.a = 0.0;
1879 lightParms.Position.x = 0.0;
1880 lightParms.Position.y = 0.0;
1881 lightParms.Position.z = 0.0;
1882 lightParms.Direction.x = 0.0;
1883 lightParms.Direction.y = 0.0;
1884 lightParms.Direction.z = 1.0;
1885 lightParms.Range = 0.0;
1886 lightParms.Falloff = 0.0;
1887 lightParms.Attenuation0 = 0.0;
1888 lightParms.Attenuation1 = 0.0;
1889 lightParms.Attenuation2 = 0.0;
1890 lightParms.Theta = 0.0;
1891 lightParms.Phi = 0.0;
1892 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
1894 /* Search for it again! Should be fairly quick as near head of list */
1895 lightInfo = This->stateBlock->lights;
1896 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1897 if (lightInfo == NULL) {
1898 FIXME("Adding default lights has failed dismally\n");
1899 return D3DERR_INVALIDCALL;
1903 /* OK, we now have a light... */
1904 if (Enable == FALSE) {
1906 /* If we are disabling it, check it was enabled, and
1907 still only do something if it has assigned a glIndex (which it should have!) */
1908 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
1909 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1910 ENTER_GL();
1911 glDisable(GL_LIGHT0 + lightInfo->glIndex);
1912 checkGLcall("glDisable GL_LIGHT0+Index");
1913 LEAVE_GL();
1914 } else {
1915 TRACE("Nothing to do as light was not enabled\n");
1917 lightInfo->lightEnabled = FALSE;
1918 } else {
1920 /* We are enabling it. If it is enabled, it's really simple */
1921 if (lightInfo->lightEnabled) {
1922 /* nop */
1923 TRACE("Nothing to do as light was enabled\n");
1925 /* If it already has a glIndex, it's still simple */
1926 } else if (lightInfo->glIndex != -1) {
1927 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
1928 lightInfo->lightEnabled = TRUE;
1929 ENTER_GL();
1930 glEnable(GL_LIGHT0 + lightInfo->glIndex);
1931 checkGLcall("glEnable GL_LIGHT0+Index already setup");
1932 LEAVE_GL();
1934 /* Otherwise got to find space - lights are ordered gl indexes first */
1935 } else {
1936 PLIGHTINFOEL *bsf = NULL;
1937 PLIGHTINFOEL *pos = This->stateBlock->lights;
1938 PLIGHTINFOEL *prev = NULL;
1939 int Index= 0;
1940 int glIndex = -1;
1942 /* Try to minimize changes as much as possible */
1943 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
1945 /* Try to remember which index can be replaced if necessary */
1946 if (bsf==NULL && pos->lightEnabled == FALSE) {
1947 /* Found a light we can replace, save as best replacement */
1948 bsf = pos;
1951 /* Step to next space */
1952 prev = pos;
1953 pos = pos->next;
1954 Index ++;
1957 /* If we have too many active lights, fail the call */
1958 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
1959 FIXME("Program requests too many concurrent lights\n");
1960 return D3DERR_INVALIDCALL;
1962 /* If we have allocated all lights, but not all are enabled,
1963 reuse one which is not enabled */
1964 } else if (Index == This->maxConcurrentLights) {
1965 /* use bsf - Simply swap the new light and the BSF one */
1966 PLIGHTINFOEL *bsfNext = bsf->next;
1967 PLIGHTINFOEL *bsfPrev = bsf->prev;
1969 /* Sort out ends */
1970 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
1971 if (bsf->prev != NULL) {
1972 bsf->prev->next = lightInfo;
1973 } else {
1974 This->stateBlock->lights = lightInfo;
1977 /* If not side by side, lots of chains to update */
1978 if (bsf->next != lightInfo) {
1979 lightInfo->prev->next = bsf;
1980 bsf->next->prev = lightInfo;
1981 bsf->next = lightInfo->next;
1982 bsf->prev = lightInfo->prev;
1983 lightInfo->next = bsfNext;
1984 lightInfo->prev = bsfPrev;
1986 } else {
1987 /* Simple swaps */
1988 bsf->prev = lightInfo;
1989 bsf->next = lightInfo->next;
1990 lightInfo->next = bsf;
1991 lightInfo->prev = bsfPrev;
1995 /* Update states */
1996 glIndex = bsf->glIndex;
1997 bsf->glIndex = -1;
1998 lightInfo->glIndex = glIndex;
1999 lightInfo->lightEnabled = TRUE;
2001 /* Finally set up the light in gl itself */
2002 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2003 ENTER_GL();
2004 setup_light(iface, glIndex, lightInfo);
2005 glEnable(GL_LIGHT0 + glIndex);
2006 checkGLcall("glEnable GL_LIGHT0 new setup");
2007 LEAVE_GL();
2009 /* If we reached the end of the allocated lights, with space in the
2010 gl lights, setup a new light */
2011 } else if (pos->glIndex == -1) {
2013 /* We reached the end of the allocated gl lights, so already
2014 know the index of the next one! */
2015 glIndex = Index;
2016 lightInfo->glIndex = glIndex;
2017 lightInfo->lightEnabled = TRUE;
2019 /* In an ideal world, it's already in the right place */
2020 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2021 /* No need to move it */
2022 } else {
2023 /* Remove this light from the list */
2024 lightInfo->prev->next = lightInfo->next;
2025 if (lightInfo->next != NULL) {
2026 lightInfo->next->prev = lightInfo->prev;
2029 /* Add in at appropriate place (inbetween prev and pos) */
2030 lightInfo->prev = prev;
2031 lightInfo->next = pos;
2032 if (prev == NULL) {
2033 This->stateBlock->lights = lightInfo;
2034 } else {
2035 prev->next = lightInfo;
2037 if (pos != NULL) {
2038 pos->prev = lightInfo;
2042 /* Finally set up the light in gl itself */
2043 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2044 ENTER_GL();
2045 setup_light(iface, glIndex, lightInfo);
2046 glEnable(GL_LIGHT0 + glIndex);
2047 checkGLcall("glEnable GL_LIGHT0 new setup");
2048 LEAVE_GL();
2053 return D3D_OK;
2056 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2058 PLIGHTINFOEL *lightInfo = NULL;
2059 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2060 TRACE("(%p) : for idx(%ld)\n", This, Index);
2062 /* Locate the light in the live lights */
2063 lightInfo = This->stateBlock->lights;
2064 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2066 if (lightInfo == NULL) {
2067 TRACE("Light enabled state requested but light not defined\n");
2068 return D3DERR_INVALIDCALL;
2070 *pEnable = lightInfo->lightEnabled;
2071 return D3D_OK;
2074 /*****
2075 * Get / Set Clip Planes
2076 *****/
2077 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2078 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2079 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2081 /* Validate Index */
2082 if (Index >= GL_LIMITS(clipplanes)) {
2083 TRACE("Application has requested clipplane this device doesn't support\n");
2084 return D3DERR_INVALIDCALL;
2087 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2088 This->updateStateBlock->set.clipplane[Index] = TRUE;
2089 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2090 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2091 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2092 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2094 /* Handle recording of state blocks */
2095 if (This->isRecordingState) {
2096 TRACE("Recording... not performing anything\n");
2097 return D3D_OK;
2100 /* Apply it */
2102 ENTER_GL();
2104 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2105 glMatrixMode(GL_MODELVIEW);
2106 glPushMatrix();
2107 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2109 TRACE("Clipplane [%f,%f,%f,%f]\n",
2110 This->updateStateBlock->clipplane[Index][0],
2111 This->updateStateBlock->clipplane[Index][1],
2112 This->updateStateBlock->clipplane[Index][2],
2113 This->updateStateBlock->clipplane[Index][3]);
2114 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2115 checkGLcall("glClipPlane");
2117 glPopMatrix();
2118 LEAVE_GL();
2120 return D3D_OK;
2123 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2124 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2125 TRACE("(%p) : for idx %ld\n", This, Index);
2127 /* Validate Index */
2128 if (Index >= GL_LIMITS(clipplanes)) {
2129 TRACE("Application has requested clipplane this device doesn't support\n");
2130 return D3DERR_INVALIDCALL;
2133 pPlane[0] = This->stateBlock->clipplane[Index][0];
2134 pPlane[1] = This->stateBlock->clipplane[Index][1];
2135 pPlane[2] = This->stateBlock->clipplane[Index][2];
2136 pPlane[3] = This->stateBlock->clipplane[Index][3];
2137 return D3D_OK;
2140 /*****
2141 * Get / Set Clip Plane Status
2142 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2143 *****/
2144 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2145 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2146 FIXME("(%p) : stub\n", This);
2147 if (NULL == pClipStatus) {
2148 return D3DERR_INVALIDCALL;
2150 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2151 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2152 return D3D_OK;
2155 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2156 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2157 FIXME("(%p) : stub\n", This);
2158 if (NULL == pClipStatus) {
2159 return D3DERR_INVALIDCALL;
2161 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2162 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2163 return D3D_OK;
2166 /*****
2167 * Get / Set Material
2168 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2169 *****/
2170 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2171 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2173 This->updateStateBlock->changed.material = TRUE;
2174 This->updateStateBlock->set.material = TRUE;
2175 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2177 /* Handle recording of state blocks */
2178 if (This->isRecordingState) {
2179 TRACE("Recording... not performing anything\n");
2180 return D3D_OK;
2183 ENTER_GL();
2184 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2185 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2186 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2187 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2188 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2190 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2191 checkGLcall("glMaterialfv");
2192 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2193 checkGLcall("glMaterialfv");
2195 /* Only change material color if specular is enabled, otherwise it is set to black */
2196 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2197 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2198 checkGLcall("glMaterialfv");
2199 } else {
2200 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2201 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2202 checkGLcall("glMaterialfv");
2204 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2205 checkGLcall("glMaterialfv");
2206 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2207 checkGLcall("glMaterialf");
2209 LEAVE_GL();
2210 return D3D_OK;
2213 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2214 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2215 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2216 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2217 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2218 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2219 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2220 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2221 return D3D_OK;
2224 /*****
2225 * Get / Set Indices
2226 *****/
2227 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2228 UINT BaseVertexIndex) {
2229 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2230 IWineD3DIndexBuffer *oldIdxs;
2232 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2233 oldIdxs = This->updateStateBlock->pIndexData;
2235 This->updateStateBlock->changed.indices = TRUE;
2236 This->updateStateBlock->set.indices = TRUE;
2237 This->updateStateBlock->pIndexData = pIndexData;
2238 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2240 /* Handle recording of state blocks */
2241 if (This->isRecordingState) {
2242 TRACE("Recording... not performing anything\n");
2243 return D3D_OK;
2246 if (oldIdxs) IWineD3DIndexBuffer_Release(oldIdxs);
2247 if (pIndexData) IWineD3DIndexBuffer_AddRef(This->stateBlock->pIndexData);
2248 return D3D_OK;
2251 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2252 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2254 *ppIndexData = This->stateBlock->pIndexData;
2256 /* up ref count on ppindexdata */
2257 if (*ppIndexData) IWineD3DIndexBuffer_AddRef(*ppIndexData);
2258 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2260 return D3D_OK;
2263 /*****
2264 * Get / Set Viewports
2265 *****/
2266 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2267 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2269 TRACE("(%p)\n", This);
2270 This->updateStateBlock->changed.viewport = TRUE;
2271 This->updateStateBlock->set.viewport = TRUE;
2272 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2274 /* Handle recording of state blocks */
2275 if (This->isRecordingState) {
2276 TRACE("Recording... not performing anything\n");
2277 return D3D_OK;
2280 ENTER_GL();
2282 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2283 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2285 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2286 checkGLcall("glDepthRange");
2287 /* Note: GL requires lower left, DirectX supplies upper left */
2288 /* TODO: replace usage of renderTarget with context management */
2289 glViewport(pViewport->X, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2290 pViewport->Width, pViewport->Height);
2291 checkGLcall("glViewport");
2293 LEAVE_GL();
2295 return D3D_OK;
2299 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2300 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2301 TRACE("(%p)\n", This);
2302 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2303 return D3D_OK;
2306 /*****
2307 * Get / Set Render States
2308 * TODO: Verify against dx9 definitions
2309 *****/
2310 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2312 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2313 DWORD OldValue = This->stateBlock->renderState[State];
2315 /* Simple way of referring to either a DWORD or a 4 byte float */
2316 union {
2317 DWORD d;
2318 float f;
2319 } tmpvalue;
2321 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2322 This->updateStateBlock->changed.renderState[State] = TRUE;
2323 This->updateStateBlock->set.renderState[State] = TRUE;
2324 This->updateStateBlock->renderState[State] = Value;
2326 /* Handle recording of state blocks */
2327 if (This->isRecordingState) {
2328 TRACE("Recording... not performing anything\n");
2329 return D3D_OK;
2332 ENTER_GL();
2334 switch (State) {
2335 case WINED3DRS_FILLMODE :
2336 switch ((D3DFILLMODE) Value) {
2337 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2338 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2339 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2340 default:
2341 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
2343 checkGLcall("glPolygonMode (fillmode)");
2344 break;
2346 case WINED3DRS_LIGHTING :
2347 if (Value) {
2348 glEnable(GL_LIGHTING);
2349 checkGLcall("glEnable GL_LIGHTING");
2350 } else {
2351 glDisable(GL_LIGHTING);
2352 checkGLcall("glDisable GL_LIGHTING");
2354 break;
2356 case WINED3DRS_ZENABLE :
2357 switch ((D3DZBUFFERTYPE) Value) {
2358 case D3DZB_FALSE:
2359 glDisable(GL_DEPTH_TEST);
2360 checkGLcall("glDisable GL_DEPTH_TEST");
2361 break;
2362 case D3DZB_TRUE:
2363 glEnable(GL_DEPTH_TEST);
2364 checkGLcall("glEnable GL_DEPTH_TEST");
2365 break;
2366 case D3DZB_USEW:
2367 glEnable(GL_DEPTH_TEST);
2368 checkGLcall("glEnable GL_DEPTH_TEST");
2369 FIXME("W buffer is not well handled\n");
2370 break;
2371 default:
2372 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2374 break;
2376 case WINED3DRS_CULLMODE :
2378 /* If we are culling "back faces with clockwise vertices" then
2379 set front faces to be counter clockwise and enable culling
2380 of back faces */
2381 switch ((D3DCULL) Value) {
2382 case D3DCULL_NONE:
2383 glDisable(GL_CULL_FACE);
2384 checkGLcall("glDisable GL_CULL_FACE");
2385 break;
2386 case D3DCULL_CW:
2387 glEnable(GL_CULL_FACE);
2388 checkGLcall("glEnable GL_CULL_FACE");
2389 if (This->renderUpsideDown) {
2390 glFrontFace(GL_CW);
2391 checkGLcall("glFrontFace GL_CW");
2392 } else {
2393 glFrontFace(GL_CCW);
2394 checkGLcall("glFrontFace GL_CCW");
2396 glCullFace(GL_BACK);
2397 break;
2398 case D3DCULL_CCW:
2399 glEnable(GL_CULL_FACE);
2400 checkGLcall("glEnable GL_CULL_FACE");
2401 if (This->renderUpsideDown) {
2402 glFrontFace(GL_CCW);
2403 checkGLcall("glFrontFace GL_CCW");
2404 } else {
2405 glFrontFace(GL_CW);
2406 checkGLcall("glFrontFace GL_CW");
2408 glCullFace(GL_BACK);
2409 break;
2410 default:
2411 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2413 break;
2415 case WINED3DRS_SHADEMODE :
2416 switch ((D3DSHADEMODE) Value) {
2417 case D3DSHADE_FLAT:
2418 glShadeModel(GL_FLAT);
2419 checkGLcall("glShadeModel");
2420 break;
2421 case D3DSHADE_GOURAUD:
2422 glShadeModel(GL_SMOOTH);
2423 checkGLcall("glShadeModel");
2424 break;
2425 case D3DSHADE_PHONG:
2426 FIXME("D3DSHADE_PHONG isn't supported?\n");
2428 LEAVE_GL();
2429 return D3DERR_INVALIDCALL;
2430 default:
2431 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2433 break;
2435 case WINED3DRS_DITHERENABLE :
2436 if (Value) {
2437 glEnable(GL_DITHER);
2438 checkGLcall("glEnable GL_DITHER");
2439 } else {
2440 glDisable(GL_DITHER);
2441 checkGLcall("glDisable GL_DITHER");
2443 break;
2445 case WINED3DRS_ZWRITEENABLE :
2446 if (Value) {
2447 glDepthMask(1);
2448 checkGLcall("glDepthMask");
2449 } else {
2450 glDepthMask(0);
2451 checkGLcall("glDepthMask");
2453 break;
2455 case WINED3DRS_ZFUNC :
2457 int glParm = GL_LESS;
2459 switch ((D3DCMPFUNC) Value) {
2460 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2461 case D3DCMP_LESS: glParm=GL_LESS; break;
2462 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2463 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2464 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2465 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2466 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2467 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2468 default:
2469 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2471 glDepthFunc(glParm);
2472 checkGLcall("glDepthFunc");
2474 break;
2476 case WINED3DRS_AMBIENT :
2478 float col[4];
2479 D3DCOLORTOGLFLOAT4(Value, col);
2480 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2481 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2482 checkGLcall("glLightModel for MODEL_AMBIENT");
2485 break;
2487 case WINED3DRS_ALPHABLENDENABLE :
2488 if (Value) {
2489 glEnable(GL_BLEND);
2490 checkGLcall("glEnable GL_BLEND");
2491 } else {
2492 glDisable(GL_BLEND);
2493 checkGLcall("glDisable GL_BLEND");
2495 break;
2497 case WINED3DRS_SRCBLEND :
2498 case WINED3DRS_DESTBLEND :
2500 int newVal = GL_ZERO;
2501 switch (Value) {
2502 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2503 case D3DBLEND_ONE : newVal = GL_ONE; break;
2504 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2505 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2506 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2507 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2508 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2509 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2510 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2511 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2512 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2514 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2515 This->srcBlend = newVal;
2516 This->dstBlend = newVal;
2517 break;
2519 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2520 This->srcBlend = newVal;
2521 This->dstBlend = newVal;
2522 break;
2523 default:
2524 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2527 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2528 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2529 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2530 glBlendFunc(This->srcBlend, This->dstBlend);
2532 checkGLcall("glBlendFunc");
2534 break;
2536 case WINED3DRS_ALPHATESTENABLE :
2537 if (Value) {
2538 glEnable(GL_ALPHA_TEST);
2539 checkGLcall("glEnable GL_ALPHA_TEST");
2540 } else {
2541 glDisable(GL_ALPHA_TEST);
2542 checkGLcall("glDisable GL_ALPHA_TEST");
2544 break;
2546 case WINED3DRS_ALPHAFUNC :
2548 int glParm = GL_LESS;
2549 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2551 switch ((D3DCMPFUNC) Value) {
2552 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2553 case D3DCMP_LESS: glParm = GL_LESS; break;
2554 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2555 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2556 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2557 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2558 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2559 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2560 default:
2561 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2563 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2564 glAlphaFunc(glParm, ref);
2565 This->alphafunc = glParm;
2566 checkGLcall("glAlphaFunc");
2568 break;
2570 case WINED3DRS_ALPHAREF :
2572 int glParm = This->alphafunc;
2573 float ref = 1.0f;
2575 ref = ((float) Value) / 255.0f;
2576 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2577 glAlphaFunc(glParm, ref);
2578 checkGLcall("glAlphaFunc");
2580 break;
2582 case WINED3DRS_CLIPPLANEENABLE :
2583 case WINED3DRS_CLIPPING :
2585 /* Ensure we only do the changed clip planes */
2586 DWORD enable = 0xFFFFFFFF;
2587 DWORD disable = 0x00000000;
2589 /* If enabling / disabling all */
2590 if (State == WINED3DRS_CLIPPING) {
2591 if (Value) {
2592 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2593 disable = 0x00;
2594 } else {
2595 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2596 enable = 0x00;
2598 } else {
2599 enable = Value & ~OldValue;
2600 disable = ~Value & OldValue;
2603 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2604 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2605 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2606 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2607 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2608 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2610 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2611 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2612 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2613 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2614 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2615 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2617 /** update clipping status */
2618 if (enable) {
2619 This->stateBlock->clip_status.ClipUnion = 0;
2620 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
2621 } else {
2622 This->stateBlock->clip_status.ClipUnion = 0;
2623 This->stateBlock->clip_status.ClipIntersection = 0;
2626 break;
2628 case WINED3DRS_BLENDOP :
2630 int glParm = GL_FUNC_ADD;
2632 switch ((D3DBLENDOP) Value) {
2633 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2634 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2635 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2636 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2637 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2638 default:
2639 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2641 TRACE("glBlendEquation(%x)\n", glParm);
2642 glBlendEquation(glParm);
2643 checkGLcall("glBlendEquation");
2645 break;
2647 case WINED3DRS_TEXTUREFACTOR :
2649 unsigned int i;
2651 /* Note the texture color applies to all textures whereas
2652 GL_TEXTURE_ENV_COLOR applies to active only */
2653 float col[4];
2654 D3DCOLORTOGLFLOAT4(Value, col);
2655 /* Set the default alpha blend color */
2656 glBlendColor(col[0], col[1], col[2], col[3]);
2657 checkGLcall("glBlendColor");
2659 /* And now the default texture color as well */
2660 for (i = 0; i < GL_LIMITS(textures); i++) {
2662 /* Note the D3DRS value applies to all textures, but GL has one
2663 per texture, so apply it now ready to be used! */
2664 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2665 GLACTIVETEXTURE(i);
2666 } else if (i>0) {
2667 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2670 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2671 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2674 break;
2676 case WINED3DRS_SPECULARENABLE :
2678 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2679 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2680 specular color. This is wrong:
2681 Separate specular color means the specular colour is maintained separately, whereas
2682 single color means it is merged in. However in both cases they are being used to
2683 some extent.
2684 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2685 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2686 running 1.4 yet!
2688 if (Value) {
2689 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2690 checkGLcall("glMaterialfv");
2691 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2692 glEnable(GL_COLOR_SUM_EXT);
2693 } else {
2694 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2696 checkGLcall("glEnable(GL_COLOR_SUM)");
2697 } else {
2698 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2700 /* for the case of enabled lighting: */
2701 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2702 checkGLcall("glMaterialfv");
2704 /* for the case of disabled lighting: */
2705 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2706 glDisable(GL_COLOR_SUM_EXT);
2707 } else {
2708 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2710 checkGLcall("glDisable(GL_COLOR_SUM)");
2713 break;
2715 case WINED3DRS_STENCILENABLE :
2716 if (Value) {
2717 glEnable(GL_STENCIL_TEST);
2718 checkGLcall("glEnable GL_STENCIL_TEST");
2719 } else {
2720 glDisable(GL_STENCIL_TEST);
2721 checkGLcall("glDisable GL_STENCIL_TEST");
2723 break;
2725 case WINED3DRS_STENCILFUNC :
2727 int glParm = GL_ALWAYS;
2728 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2729 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2731 switch ((D3DCMPFUNC) Value) {
2732 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2733 case D3DCMP_LESS: glParm=GL_LESS; break;
2734 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2735 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2736 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2737 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2738 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2739 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2740 default:
2741 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2743 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2744 This->stencilfunc = glParm;
2745 glStencilFunc(glParm, ref, mask);
2746 checkGLcall("glStencilFunc");
2748 break;
2750 case WINED3DRS_STENCILREF :
2752 int glParm = This->stencilfunc;
2753 int ref = 0;
2754 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2756 ref = Value;
2757 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2758 glStencilFunc(glParm, ref, mask);
2759 checkGLcall("glStencilFunc");
2761 break;
2763 case WINED3DRS_STENCILMASK :
2765 int glParm = This->stencilfunc;
2766 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2767 GLuint mask = Value;
2769 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2770 glStencilFunc(glParm, ref, mask);
2771 checkGLcall("glStencilFunc");
2773 break;
2775 case WINED3DRS_STENCILFAIL :
2777 GLenum fail ;
2778 GLenum zpass ;
2779 GLenum zfail ;
2781 fail = StencilOp(Value);
2782 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2783 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2784 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2785 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2787 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2788 glStencilOp(fail, zfail, zpass);
2789 checkGLcall("glStencilOp(fail, zfail, zpass);");
2791 break;
2792 case WINED3DRS_STENCILZFAIL :
2794 GLenum fail ;
2795 GLenum zpass ;
2796 GLenum zfail ;
2798 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2799 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2800 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2801 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2802 zfail = StencilOp(Value);
2804 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2805 glStencilOp(fail, zfail, zpass);
2806 checkGLcall("glStencilOp(fail, zfail, zpass);");
2808 break;
2809 case WINED3DRS_STENCILPASS :
2811 GLenum fail ;
2812 GLenum zpass ;
2813 GLenum zfail ;
2815 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2816 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2817 zpass = StencilOp(Value);
2818 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2819 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2821 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2822 glStencilOp(fail, zfail, zpass);
2823 checkGLcall("glStencilOp(fail, zfail, zpass);");
2825 break;
2827 case WINED3DRS_STENCILWRITEMASK :
2829 glStencilMask(Value);
2830 TRACE("glStencilMask(%lu)\n", Value);
2831 checkGLcall("glStencilMask");
2833 break;
2835 case WINED3DRS_FOGENABLE :
2837 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2838 glEnable(GL_FOG);
2839 checkGLcall("glEnable GL_FOG");
2840 } else {
2841 glDisable(GL_FOG);
2842 checkGLcall("glDisable GL_FOG");
2845 break;
2847 case WINED3DRS_RANGEFOGENABLE :
2849 if (Value) {
2850 TRACE("Enabled RANGEFOG");
2851 } else {
2852 TRACE("Disabled RANGEFOG");
2855 break;
2857 case WINED3DRS_FOGCOLOR :
2859 float col[4];
2860 D3DCOLORTOGLFLOAT4(Value, col);
2861 /* Set the default alpha blend color */
2862 glFogfv(GL_FOG_COLOR, &col[0]);
2863 checkGLcall("glFog GL_FOG_COLOR");
2865 break;
2867 case WINED3DRS_FOGTABLEMODE :
2869 glHint(GL_FOG_HINT, GL_NICEST);
2870 switch (Value) {
2871 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2872 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2873 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2874 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2875 default:
2876 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
2878 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2879 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
2882 break;
2884 case WINED3DRS_FOGVERTEXMODE :
2886 glHint(GL_FOG_HINT, GL_FASTEST);
2887 switch (Value) {
2888 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2889 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2890 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2891 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2892 default:
2893 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
2895 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2896 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
2899 break;
2901 case WINED3DRS_FOGSTART :
2903 tmpvalue.d = Value;
2904 glFogfv(GL_FOG_START, &tmpvalue.f);
2905 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2906 TRACE("Fog Start == %f\n", tmpvalue.f);
2908 break;
2910 case WINED3DRS_FOGEND :
2912 tmpvalue.d = Value;
2913 glFogfv(GL_FOG_END, &tmpvalue.f);
2914 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2915 TRACE("Fog End == %f\n", tmpvalue.f);
2917 break;
2919 case WINED3DRS_FOGDENSITY :
2921 tmpvalue.d = Value;
2922 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
2923 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2925 break;
2927 case WINED3DRS_VERTEXBLEND :
2929 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2930 TRACE("Vertex Blending state to %ld\n", Value);
2932 break;
2934 case WINED3DRS_TWEENFACTOR :
2936 tmpvalue.d = Value;
2937 This->updateStateBlock->tween_factor = tmpvalue.f;
2938 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
2940 break;
2942 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
2944 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2946 break;
2948 case WINED3DRS_COLORVERTEX :
2949 case WINED3DRS_DIFFUSEMATERIALSOURCE :
2950 case WINED3DRS_SPECULARMATERIALSOURCE :
2951 case WINED3DRS_AMBIENTMATERIALSOURCE :
2952 case WINED3DRS_EMISSIVEMATERIALSOURCE :
2954 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2956 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
2957 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2958 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
2959 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
2960 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
2961 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
2963 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2964 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2965 Parm = GL_AMBIENT_AND_DIFFUSE;
2966 } else {
2967 Parm = GL_DIFFUSE;
2969 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2970 Parm = GL_AMBIENT;
2971 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2972 Parm = GL_EMISSION;
2973 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2974 Parm = GL_SPECULAR;
2975 } else {
2976 Parm = -1;
2979 if (Parm == -1) {
2980 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2981 } else {
2982 This->tracking_color = NEEDS_TRACKING;
2983 This->tracking_parm = Parm;
2986 } else {
2987 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2990 break;
2992 case WINED3DRS_LINEPATTERN :
2994 union {
2995 DWORD d;
2996 D3DLINEPATTERN lp;
2997 } tmppattern;
2998 tmppattern.d = Value;
3000 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3002 if (tmppattern.lp.wRepeatFactor) {
3003 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3004 checkGLcall("glLineStipple(repeat, linepattern)");
3005 glEnable(GL_LINE_STIPPLE);
3006 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3007 } else {
3008 glDisable(GL_LINE_STIPPLE);
3009 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3012 break;
3014 case WINED3DRS_ZBIAS :
3016 if (Value) {
3017 tmpvalue.d = Value;
3018 TRACE("ZBias value %f\n", tmpvalue.f);
3019 glPolygonOffset(0, -tmpvalue.f);
3020 checkGLcall("glPolygonOffset(0, -Value)");
3021 glEnable(GL_POLYGON_OFFSET_FILL);
3022 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3023 glEnable(GL_POLYGON_OFFSET_LINE);
3024 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3025 glEnable(GL_POLYGON_OFFSET_POINT);
3026 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3027 } else {
3028 glDisable(GL_POLYGON_OFFSET_FILL);
3029 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3030 glDisable(GL_POLYGON_OFFSET_LINE);
3031 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3032 glDisable(GL_POLYGON_OFFSET_POINT);
3033 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3036 break;
3038 case WINED3DRS_NORMALIZENORMALS :
3039 if (Value) {
3040 glEnable(GL_NORMALIZE);
3041 checkGLcall("glEnable(GL_NORMALIZE);");
3042 } else {
3043 glDisable(GL_NORMALIZE);
3044 checkGLcall("glDisable(GL_NORMALIZE);");
3046 break;
3048 case WINED3DRS_POINTSIZE :
3049 tmpvalue.d = Value;
3050 TRACE("Set point size to %f\n", tmpvalue.f);
3051 glPointSize(tmpvalue.f);
3052 checkGLcall("glPointSize(...);");
3053 break;
3055 case WINED3DRS_POINTSIZE_MIN :
3056 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3057 tmpvalue.d = Value;
3058 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3059 checkGLcall("glPointParameterfEXT(...);");
3060 } else {
3061 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3063 break;
3065 case WINED3DRS_POINTSIZE_MAX :
3066 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3067 tmpvalue.d = Value;
3068 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3069 checkGLcall("glPointParameterfEXT(...);");
3070 } else {
3071 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3073 break;
3075 case WINED3DRS_POINTSCALE_A :
3076 case WINED3DRS_POINTSCALE_B :
3077 case WINED3DRS_POINTSCALE_C :
3078 case WINED3DRS_POINTSCALEENABLE :
3080 /* If enabled, supply the parameters, otherwise fall back to defaults */
3081 if (This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3082 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3083 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]);
3084 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]);
3085 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]);
3087 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3088 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3089 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3090 } else {
3091 TRACE("WINED3DRS_POINTSCALEENABLE not supported on this opengl\n");
3093 } else {
3094 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3095 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3096 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3097 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3098 } else {
3099 TRACE("WINED3DRS_POINTSCALEENABLE not supported, but not on either\n");
3102 break;
3105 case WINED3DRS_COLORWRITEENABLE :
3107 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3108 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3109 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3110 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3111 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3112 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3113 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3114 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3115 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3116 checkGLcall("glColorMask(...)");
3118 break;
3120 case WINED3DRS_LOCALVIEWER :
3122 GLint state = (Value) ? 1 : 0;
3123 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3124 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3126 break;
3128 case WINED3DRS_LASTPIXEL :
3130 if (Value) {
3131 TRACE("Last Pixel Drawing Enabled\n");
3132 } else {
3133 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3136 break;
3138 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3140 if (Value) {
3141 TRACE("Software Processing Enabled\n");
3142 } else {
3143 TRACE("Software Processing Disabled\n");
3146 break;
3148 /** not supported */
3149 case WINED3DRS_ZVISIBLE :
3151 LEAVE_GL();
3152 return D3DERR_INVALIDCALL;
3155 /* Unhandled yet...! */
3156 case WINED3DRS_EDGEANTIALIAS :
3157 case WINED3DRS_WRAP0 :
3158 case WINED3DRS_WRAP1 :
3159 case WINED3DRS_WRAP2 :
3160 case WINED3DRS_WRAP3 :
3161 case WINED3DRS_WRAP4 :
3162 case WINED3DRS_WRAP5 :
3163 case WINED3DRS_WRAP6 :
3164 case WINED3DRS_WRAP7 :
3165 case WINED3DRS_POINTSPRITEENABLE :
3166 case WINED3DRS_MULTISAMPLEANTIALIAS :
3167 case WINED3DRS_MULTISAMPLEMASK :
3168 case WINED3DRS_PATCHEDGESTYLE :
3169 case WINED3DRS_PATCHSEGMENTS :
3170 case WINED3DRS_DEBUGMONITORTOKEN :
3171 case WINED3DRS_POSITIONORDER :
3172 case WINED3DRS_NORMALORDER :
3173 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3174 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3175 break;
3176 default:
3177 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3180 LEAVE_GL();
3182 return D3D_OK;
3185 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3186 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3187 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3188 *pValue = This->stateBlock->renderState[State];
3189 return D3D_OK;
3192 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value){
3193 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3195 * SetSampler is designed to allow for more than the standard up to 8 textures
3196 * and Geforce has stopped supporting more than 6 standard textures in openGL.
3197 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3199 * http://developer.nvidia.com/object/General_FAQ.html#t6
3201 * There are two new settings for GForce
3202 * the sampler one:
3203 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3204 * and the texture one:
3205 * GL_MAX_TEXTURE_COORDS_ARB.
3206 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3207 ******************/
3208 union {
3209 float f;
3210 DWORD d;
3211 } tmpvalue;
3213 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
3215 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > HIGHEST_SAMPLER_STATE || Type < 0){
3216 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), HIGHEST_SAMPLER_STATE, Sampler, Type);
3217 return D3DERR_INVALIDCALL;
3220 This->updateStateBlock->changed.samplerState[Sampler][Type] = TRUE;
3221 This->updateStateBlock->set.samplerState[Sampler][Type] = TRUE;
3222 TRACE("Setting sampler %ld %d to %ld \n", Sampler, Type, Value);
3223 This->updateStateBlock->samplerState[Sampler][Type] = Value;
3225 /* Handle recording of state blocks */
3226 if (This->isRecordingState) {
3227 TRACE("Recording... not performing anything\n");
3228 return D3D_OK;
3231 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
3232 clamping, MIPLOD, etc. This will work for up to 16 samplers.
3233 is this just GL_TEXTURE_2D or is it GL_TEXTURE_1D and GL_TEXTURE_3D as well?
3235 ENTER_GL();
3236 VTRACE(("Activating appropriate texture state %ld\n", Sampler));
3237 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3238 GLACTIVETEXTURE(Sampler);
3239 } else if (Sampler > 0) {
3240 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3244 switch (Type) {
3246 case WINED3DSAMP_ADDRESSU : /* 1 */
3247 case WINED3DSAMP_ADDRESSV : /* 2 */
3248 case WINED3DSAMP_ADDRESSW : /* 3 */
3250 GLint wrapParm = GL_REPEAT;
3251 switch (Value) {
3252 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3253 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3254 case D3DTADDRESS_BORDER:
3256 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3257 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3258 } else {
3259 /* FIXME: Not right, but better */
3260 TRACE("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3261 wrapParm = GL_REPEAT;
3264 break;
3265 case D3DTADDRESS_MIRROR:
3267 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3268 wrapParm = GL_MIRRORED_REPEAT_ARB;
3269 } else {
3270 /* Unsupported in OpenGL pre-1.4 */
3271 TRACE("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3272 wrapParm = GL_REPEAT;
3275 break;
3276 case D3DTADDRESS_MIRRORONCE:
3278 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3279 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3280 } else {
3281 TRACE("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3282 wrapParm = GL_REPEAT;
3285 break;
3287 default:
3288 /* This is for the whole context, not just the sampler,
3289 so we should warn if two states are baing set for any given scene */
3290 if (Type!=0)
3291 TRACE("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3292 wrapParm = GL_REPEAT;
3294 switch (Type) {
3295 case WINED3DSAMP_ADDRESSU:
3296 TRACE("Setting WRAP_S for %ld to %d \n", Sampler, wrapParm);
3297 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_WRAP_S, wrapParm);
3298 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3299 break;
3300 case WINED3DSAMP_ADDRESSV:
3301 TRACE("Setting WRAP_T for %ld to %d\n", Sampler, wrapParm);
3302 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_WRAP_T, wrapParm);
3303 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3304 break;
3306 case WINED3DSAMP_ADDRESSW:
3307 TRACE("Setting WRAP_R for %ld to %d\n", Sampler, wrapParm);
3308 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_WRAP_R, wrapParm);
3309 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3310 break;
3311 default: /* nop */
3312 break; /** stupic compilator */
3315 break;
3317 case WINED3DSAMP_BORDERCOLOR : /* 4 */
3319 float col[4];
3320 D3DCOLORTOGLFLOAT4(Value, col);
3321 TRACE("Setting border color for %ld to %lx\n", Sampler, Value);
3322 glTexParameterfv(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_BORDER_COLOR, &col[0]);
3323 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3325 break;
3327 case WINED3DSAMP_MAGFILTER : /* 5 */
3329 DWORD ValueMAG = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAGFILTER];
3330 GLint realVal = GL_NEAREST;
3332 if (ValueMAG == D3DTEXF_POINT) {
3333 realVal = GL_NEAREST;
3334 } else if (ValueMAG == D3DTEXF_LINEAR) {
3335 realVal = GL_LINEAR;
3336 } else if (ValueMAG == D3DTEXF_ANISOTROPIC) {
3337 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3338 realVal = GL_LINEAR;
3339 } else {
3340 FIXME("Trying to use ANISOTROPIC_FILTERING for WINED3DTSS_MAGFILTER. But not supported by current OpenGL driver\n");
3341 realVal = GL_NEAREST;
3343 } else {
3344 FIXME("Unhandled WINED3DTSS_MAGFILTER value of %ld\n", ValueMAG);
3345 realVal = GL_NEAREST;
3347 TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", ValueMAG, realVal);
3348 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_MAG_FILTER, realVal);
3349 checkGLcall("glTexParameter GL_TEXTURE_MAG_FILTER, ...");
3351 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3353 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMAG) {
3354 glTexParameteri(This->stateBlock->textureDimensions[Sampler],
3355 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3356 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXANISOTROPY]);
3357 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3360 break;
3362 case WINED3DSAMP_MINFILTER: /* 6 */
3363 case WINED3DSAMP_MIPFILTER: /* 7 */
3365 DWORD ValueMIN = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MINFILTER];
3366 DWORD ValueMIP = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPFILTER];
3367 GLint realVal = GL_LINEAR;
3369 if (ValueMIN == D3DTEXF_NONE) {
3370 /* Doesn't really make sense - Windows just seems to disable
3371 mipmapping when this occurs */
3372 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3373 realVal = GL_LINEAR;
3374 } else if (ValueMIN == D3DTEXF_POINT) {
3375 /* GL_NEAREST_* */
3376 if (ValueMIP == D3DTEXF_NONE) {
3377 realVal = GL_NEAREST;
3378 } else if (ValueMIP == D3DTEXF_POINT) {
3379 realVal = GL_NEAREST_MIPMAP_NEAREST;
3380 } else if (ValueMIP == D3DTEXF_LINEAR) {
3381 realVal = GL_NEAREST_MIPMAP_LINEAR;
3382 } else {
3383 FIXME("Unhandled WINED3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3384 realVal = GL_NEAREST;
3386 } else if (ValueMIN == D3DTEXF_LINEAR) {
3387 /* GL_LINEAR_* */
3388 if (ValueMIP == D3DTEXF_NONE) {
3389 realVal = GL_LINEAR;
3390 } else if (ValueMIP == D3DTEXF_POINT) {
3391 realVal = GL_LINEAR_MIPMAP_NEAREST;
3392 } else if (ValueMIP == D3DTEXF_LINEAR) {
3393 realVal = GL_LINEAR_MIPMAP_LINEAR;
3394 } else {
3395 FIXME("Unhandled WINED3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3396 realVal = GL_LINEAR;
3398 } else if (ValueMIN == D3DTEXF_ANISOTROPIC) {
3399 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3400 if (ValueMIP == D3DTEXF_NONE) {
3401 realVal = GL_LINEAR_MIPMAP_LINEAR;
3402 } else if (ValueMIP == D3DTEXF_POINT) {
3403 realVal = GL_LINEAR_MIPMAP_NEAREST;
3404 } else if (ValueMIP == D3DTEXF_LINEAR) {
3405 realVal = GL_LINEAR_MIPMAP_LINEAR;
3406 } else {
3407 FIXME("Unhandled WINED3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3408 realVal = GL_LINEAR;
3410 } else {
3411 WARN("Trying to use ANISOTROPIC_FILTERING for WINED3DTSS_MINFILTER. But not supported by OpenGL driver\n");
3412 realVal = GL_LINEAR;
3414 } else {
3415 FIXME("Unhandled WINED3DTSS_MINFILTER value of %ld\n", ValueMIN);
3416 realVal = GL_LINEAR_MIPMAP_LINEAR;
3419 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3420 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_MIN_FILTER, realVal);
3421 checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
3423 * if we just choose to use ANISOTROPIC filtering, refresh openGL state
3425 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMIN) {
3426 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_MAX_ANISOTROPY_EXT,
3427 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXANISOTROPY]);
3428 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3431 break;
3433 case WINED3DSAMP_MIPMAPLODBIAS : /* 8 */
3435 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3436 tmpvalue.d = Value;
3437 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3438 GL_TEXTURE_LOD_BIAS_EXT,
3439 tmpvalue.f);
3440 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
3443 break;
3445 case WINED3DSAMP_MAXMIPLEVEL : /* 9 */
3448 * Not really the same, but the more apprioprate than nothing
3450 glTexParameteri(This->stateBlock->textureDimensions[Sampler],
3451 GL_TEXTURE_BASE_LEVEL,
3452 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXMIPLEVEL]);
3453 checkGLcall("glTexParameteri GL_TEXTURE_BASE_LEVEL ...");
3455 break;
3457 case WINED3DSAMP_MAXANISOTROPY : /* 10 */
3459 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3460 glTexParameteri(This->stateBlock->textureDimensions[Sampler],
3461 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3462 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXANISOTROPY]);
3463 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3466 break;
3467 case WINED3DSAMP_SRGBTEXTURE : /* 11 */
3468 /* Per texture gamma correction, default 0 */
3469 case WINED3DSAMP_ELEMENTINDEX : /* 12 */
3470 /* When a multi-element textures is used this indicates the element, (what's a multielement texture?) */
3471 case WINED3DSAMP_DMAPOFFSET : /* 13 */
3472 /* Value of a precompiled displacement map used by the tesselator, default 0 */
3473 TRACE("Unsupported sampler setting, Sampler=%ld, Type=%d, Value =%ld\n", Sampler, Type, Value);
3474 break;
3475 default:
3477 TRACE("invalid sampler setting, Sampler=%ld, Type=%d, Value =%ld\n", Sampler, Type, Value);
3479 LEAVE_GL();
3480 return D3D_OK;
3483 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value){
3484 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3485 /** TODO: check that sampler is in range **/
3486 *Value = This->updateStateBlock->samplerState[Sampler][Type];
3487 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
3488 return D3D_OK;
3492 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect){
3493 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3494 ENTER_GL();
3496 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3497 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3498 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3499 LEAVE_GL();
3500 return D3D_OK;
3503 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect){
3504 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3505 GLint scissorBox[4];
3507 ENTER_GL();
3508 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3509 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
3510 pRect->left = scissorBox[1];
3511 pRect->top = scissorBox[2];
3512 pRect->right = scissorBox[1] + scissorBox[3];
3513 pRect->bottom = scissorBox[2] + scissorBox[4];
3514 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3515 LEAVE_GL();
3516 return D3D_OK;
3519 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3520 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3522 TRACE("(%p) : pDecl=%p\n", This, pDecl);
3524 /* TODO: what about recording stateblocks? */
3525 IWineD3DVertexDeclaration_AddRef(pDecl);
3526 if (NULL != This->updateStateBlock->vertexDecl) {
3527 IWineD3DVertexDeclaration_Release(This->updateStateBlock->vertexDecl);
3529 This->updateStateBlock->vertexDecl = pDecl;
3530 This->updateStateBlock->changed.vertexDecl = TRUE;
3531 This->updateStateBlock->set.vertexDecl = TRUE;
3532 return D3D_OK;
3535 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3536 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3538 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3540 *ppDecl = This->updateStateBlock->vertexDecl;
3541 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3542 return D3D_OK;
3545 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader){
3546 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3548 static BOOL showFixmes = TRUE;
3550 This->updateStateBlock->vertexShader = pShader;
3551 This->updateStateBlock->changed.vertexShader = TRUE;
3552 This->updateStateBlock->set.vertexShader = TRUE;
3554 if(pShader == NULL){
3555 /* clear down the shader */
3556 TRACE("Clear down the shader\n");
3557 }else{
3558 if(showFixmes){
3559 FIXME("(%p) : stub pShader(%p)\n", This, pShader);
3560 showFixmes = FALSE;
3564 return D3D_OK;
3566 /** FIXME: refernece counting? **/
3567 if (pShader == NULL) { /* only valid with non FVF shaders */
3568 TRACE_(d3d_shader)("(%p) : FVF Shader, pShader=%p\n", This, pShader);
3569 This->updateStateBlock->vertexShader = NULL;
3570 } else {
3571 TRACE_(d3d_shader)("(%p) : Created shader, pShader=%p\n", This, pShader);
3572 This->updateStateBlock->vertexShader = pShader;
3575 This->updateStateBlock->changed.vertexShader = TRUE;
3576 This->updateStateBlock->set.vertexShader = TRUE;
3578 /* Handle recording of state blocks */
3579 if (This->isRecordingState) {
3580 TRACE("Recording... not performing anything\n");
3581 return D3D_OK;
3584 * TODO: merge HAL shaders context switching from prototype
3586 return D3D_OK;
3590 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader){
3591 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3592 *ppShader = This->stateBlock->vertexShader;
3593 if(*ppShader != NULL)
3594 IWineD3DVertexShader_AddRef(*ppShader);
3595 TRACE("(%p) : returning %p\n", This, *ppShader);
3596 return D3D_OK;
3599 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
3600 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3602 TRACE("(%p) : stub\n", This);
3603 return D3D_OK;
3606 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
3607 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3608 TRACE("(%p) : stub\n", This);
3609 return D3D_OK;
3612 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
3613 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3614 TRACE("(%p) : stub\n", This);
3615 return D3D_OK;
3618 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
3619 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3620 TRACE("(%p) : stub\n", This);
3621 return D3D_OK;
3624 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
3625 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3626 TRACE("(%p) : stub\n", This);
3627 return D3D_OK;
3630 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
3631 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3632 TRACE("(%p) : stub\n", This);
3633 return D3D_OK;
3636 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader){
3637 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3638 TRACE("(%p) : stub\n", This);
3639 return D3D_OK;
3642 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader){
3643 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3644 TRACE("(%p) : stub\n", This);
3645 return D3D_OK;
3649 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
3650 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3651 TRACE("(%p) : stub\n", This);
3652 return D3D_OK;
3655 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
3656 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3657 TRACE("(%p) : stub\n", This);
3658 return D3D_OK;
3661 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
3662 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3663 TRACE("(%p) : stub\n", This);
3664 return D3D_OK;
3667 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
3668 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3669 TRACE("(%p) : stub\n", This);
3670 return D3D_OK;
3673 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
3674 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3675 TRACE("(%p) : stub\n", This);
3676 return D3D_OK;
3679 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
3680 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3681 TRACE("(%p) : stub\n", This);
3682 return D3D_OK;
3685 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags){
3686 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3687 FIXME("(%p) : stub\n", This);
3688 return D3D_OK;
3691 /*****
3692 * Get / Set Texture Stage States
3693 * TODO: Verify against dx9 definitions
3694 *****/
3695 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3696 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3698 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3700 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3702 /* Reject invalid texture units */
3703 if (Stage >= GL_LIMITS(textures)) {
3704 TRACE("Attempt to access invalid texture rejected\n");
3705 return D3DERR_INVALIDCALL;
3708 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
3709 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
3710 This->updateStateBlock->textureState[Stage][Type] = Value;
3712 /* Handle recording of state blocks */
3713 if (This->isRecordingState) {
3714 TRACE("Recording... not performing anything\n");
3715 return D3D_OK;
3718 ENTER_GL();
3720 /* Make appropriate texture active */
3721 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3722 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3723 GLACTIVETEXTURE(Stage);
3724 } else if (Stage > 0) {
3725 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3728 switch (Type) {
3729 case WINED3DTSS_ALPHAOP :
3730 case WINED3DTSS_COLOROP :
3733 if ((Value == D3DTOP_DISABLE) && (Type == WINED3DTSS_COLOROP)) {
3734 /* TODO: Disable by making this and all later levels disabled */
3735 glDisable(GL_TEXTURE_1D);
3736 checkGLcall("Disable GL_TEXTURE_1D");
3737 glDisable(GL_TEXTURE_2D);
3738 checkGLcall("Disable GL_TEXTURE_2D");
3739 glDisable(GL_TEXTURE_3D);
3740 checkGLcall("Disable GL_TEXTURE_3D");
3741 break; /* Don't bother setting the texture operations */
3742 } else {
3743 /* Enable only the appropriate texture dimension */
3744 if (Type == WINED3DTSS_COLOROP) {
3745 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3746 glEnable(GL_TEXTURE_1D);
3747 checkGLcall("Enable GL_TEXTURE_1D");
3748 } else {
3749 glDisable(GL_TEXTURE_1D);
3750 checkGLcall("Disable GL_TEXTURE_1D");
3752 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3753 if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
3754 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
3755 checkGLcall("Enable GL_TEXTURE_2D");
3756 } else {
3757 glEnable(GL_TEXTURE_2D);
3758 checkGLcall("Enable GL_TEXTURE_2D");
3760 } else {
3761 glDisable(GL_TEXTURE_2D);
3762 checkGLcall("Disable GL_TEXTURE_2D");
3764 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3765 glEnable(GL_TEXTURE_3D);
3766 checkGLcall("Enable GL_TEXTURE_3D");
3767 } else {
3768 glDisable(GL_TEXTURE_3D);
3769 checkGLcall("Disable GL_TEXTURE_3D");
3771 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3772 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3773 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3774 } else {
3775 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3776 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3780 /* Drop through... (Except disable case) */
3781 case WINED3DTSS_COLORARG0 :
3782 case WINED3DTSS_COLORARG1 :
3783 case WINED3DTSS_COLORARG2 :
3784 case WINED3DTSS_ALPHAARG0 :
3785 case WINED3DTSS_ALPHAARG1 :
3786 case WINED3DTSS_ALPHAARG2 :
3788 BOOL isAlphaArg = (Type == WINED3DTSS_ALPHAOP || Type == WINED3DTSS_ALPHAARG1 ||
3789 Type == WINED3DTSS_ALPHAARG2 || Type == WINED3DTSS_ALPHAARG0);
3790 if (isAlphaArg) {
3791 set_tex_op(iface, TRUE, Stage, This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAOP],
3792 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG1],
3793 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG2],
3794 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG0]);
3795 } else {
3796 set_tex_op(iface, FALSE, Stage, This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP],
3797 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG1],
3798 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG2],
3799 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG0]);
3802 break;
3805 case WINED3DTSS_ADDRESSW :
3807 GLint wrapParm = GL_REPEAT;
3809 switch (Value) {
3810 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3811 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3812 case D3DTADDRESS_BORDER:
3814 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3815 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3816 } else {
3817 /* FIXME: Not right, but better */
3818 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3819 wrapParm = GL_REPEAT;
3822 break;
3823 case D3DTADDRESS_MIRROR:
3825 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3826 wrapParm = GL_MIRRORED_REPEAT_ARB;
3827 } else {
3828 /* Unsupported in OpenGL pre-1.4 */
3829 FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3830 wrapParm = GL_REPEAT;
3833 break;
3834 case D3DTADDRESS_MIRRORONCE:
3836 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3837 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3838 } else {
3839 FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3840 wrapParm = GL_REPEAT;
3843 break;
3845 default:
3846 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3847 wrapParm = GL_REPEAT;
3850 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
3851 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3852 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3854 break;
3856 case WINED3DTSS_TEXCOORDINDEX :
3858 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3860 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
3861 one flag, you can still specify an index value, which the system uses to
3862 determine the texture wrapping mode.
3863 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3864 means use the vertex position (camera-space) as the input texture coordinates
3865 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
3866 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3867 to the TEXCOORDINDEX value */
3869 /**
3870 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3872 switch (Value & 0xFFFF0000) {
3873 case D3DTSS_TCI_PASSTHRU:
3874 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3875 glDisable(GL_TEXTURE_GEN_S);
3876 glDisable(GL_TEXTURE_GEN_T);
3877 glDisable(GL_TEXTURE_GEN_R);
3878 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3879 break;
3881 case D3DTSS_TCI_CAMERASPACEPOSITION:
3882 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3883 as the input texture coordinates for this stage's texture transformation. This
3884 equates roughly to EYE_LINEAR */
3886 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3887 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3888 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3889 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3890 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3892 glMatrixMode(GL_MODELVIEW);
3893 glPushMatrix();
3894 glLoadIdentity();
3895 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3896 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3897 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3898 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3899 glPopMatrix();
3901 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3902 glEnable(GL_TEXTURE_GEN_S);
3903 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3904 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3905 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3906 glEnable(GL_TEXTURE_GEN_T);
3907 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3908 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3909 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3910 glEnable(GL_TEXTURE_GEN_R);
3911 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3912 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3913 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3915 break;
3917 case D3DTSS_TCI_CAMERASPACENORMAL:
3919 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3920 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3921 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3922 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3923 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3924 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3926 glMatrixMode(GL_MODELVIEW);
3927 glPushMatrix();
3928 glLoadIdentity();
3929 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3930 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3931 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3932 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3933 glPopMatrix();
3935 glEnable(GL_TEXTURE_GEN_S);
3936 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3937 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3938 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3939 glEnable(GL_TEXTURE_GEN_T);
3940 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3941 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3942 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3943 glEnable(GL_TEXTURE_GEN_R);
3944 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3945 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3946 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3949 break;
3951 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3953 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3954 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3955 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3956 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3957 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3958 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3960 glMatrixMode(GL_MODELVIEW);
3961 glPushMatrix();
3962 glLoadIdentity();
3963 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3964 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3965 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3966 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3967 glPopMatrix();
3969 glEnable(GL_TEXTURE_GEN_S);
3970 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3971 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3972 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3973 glEnable(GL_TEXTURE_GEN_T);
3974 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3975 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3976 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3977 glEnable(GL_TEXTURE_GEN_R);
3978 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3979 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3980 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3983 break;
3985 /* Unhandled types: */
3986 default:
3987 /* Todo: */
3988 /* ? disable GL_TEXTURE_GEN_n ? */
3989 glDisable(GL_TEXTURE_GEN_S);
3990 glDisable(GL_TEXTURE_GEN_T);
3991 glDisable(GL_TEXTURE_GEN_R);
3992 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
3993 break;
3996 break;
3998 /* Unhandled */
3999 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
4000 set_texture_matrix((float *)&This->stateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
4001 break;
4003 case WINED3DTSS_BUMPENVMAT00 :
4004 case WINED3DTSS_BUMPENVMAT01 :
4005 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
4006 break;
4007 case WINED3DTSS_BUMPENVMAT10 :
4008 case WINED3DTSS_BUMPENVMAT11 :
4009 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
4010 break;
4012 case WINED3DTSS_BUMPENVLSCALE :
4013 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4014 break;
4016 case WINED3DTSS_BUMPENVLOFFSET :
4017 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4018 break;
4020 case WINED3DTSS_RESULTARG :
4021 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4022 break;
4024 default:
4025 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
4026 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4029 LEAVE_GL();
4031 return D3D_OK;
4034 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4035 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4036 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4037 *pValue = This->updateStateBlock->textureState[Stage][Type];
4038 return D3D_OK;
4041 /*****
4042 * Get / Set Texture
4043 *****/
4044 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4046 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4047 IWineD3DBaseTexture *oldTexture;
4048 BOOL reapplyStates = TRUE;
4049 DWORD reapplyFlags = 0;
4050 INT oldTextureDimensions = -1;
4051 D3DRESOURCETYPE textureType;
4053 oldTexture = This->updateStateBlock->textures[Stage];
4054 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
4056 /* Reject invalid texture units */
4057 if (Stage >= GL_LIMITS(textures)) {
4058 TRACE("Attempt to access invalid texture rejected\n");
4059 return D3DERR_INVALIDCALL;
4062 This->updateStateBlock->set.textures[Stage] = TRUE;
4063 This->updateStateBlock->changed.textures[Stage] = TRUE;
4064 This->updateStateBlock->textures[Stage] = pTexture;
4066 /* Handle recording of state blocks */
4067 if (This->isRecordingState) {
4068 TRACE("Recording... not performing anything\n");
4069 return D3D_OK;
4072 oldTextureDimensions = This->updateStateBlock->textureDimensions[Stage];
4074 ENTER_GL();
4076 /* Make appropriate texture active */
4077 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
4078 GLACTIVETEXTURE(Stage);
4080 } else if (Stage>0) {
4081 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
4084 /** NOTE: MSDN says that setTexture increases the reference count,
4085 * and the the application nust set the texture back to null (or have a leaky application),
4086 * This means we should pass the refcount upto the parent
4087 *******************************/
4088 if (NULL != oldTexture) {
4090 IUnknown *textureParent;
4091 IWineD3DBaseTexture_GetParent(oldTexture, (IUnknown **)&textureParent);
4092 IUnknown_Release(textureParent);
4093 IUnknown_Release(textureParent); /** NOTE: Twice because GetParent adds a ref **/
4094 oldTexture = NULL;
4098 if (NULL != pTexture) {
4099 IUnknown *textureParent;
4100 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[Stage], (IUnknown **)&textureParent);
4101 /** NOTE: GetParent will increase the ref count for me, I won't clean up untill the texture is set to NULL **/
4103 /* Now setup the texture appropraitly */
4104 textureType = IWineD3DBaseTexture_GetType(pTexture);
4106 if (textureType == D3DRTYPE_TEXTURE) {
4108 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
4109 TRACE("Skipping setting texture as old == new\n");
4110 reapplyStates = FALSE;
4112 } else {
4114 /* Standard 2D texture */
4115 TRACE("Standard 2d texture\n");
4116 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
4118 /* Load up the texture now */
4119 IWineD3DTexture_PreLoad((IWineD3DTexture *) pTexture);
4122 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
4124 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
4125 TRACE("Skipping setting texture as old == new\n");
4126 reapplyStates = FALSE;
4128 } else {
4130 /* Standard 3D (volume) texture */
4131 TRACE("Standard 3d texture\n");
4132 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
4134 /* Load up the texture now */
4135 IWineD3DVolumeTexture_PreLoad((IWineD3DVolumeTexture *) pTexture);
4138 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
4140 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
4141 TRACE("Skipping setting texture as old == new\n");
4142 reapplyStates = FALSE;
4144 } else {
4146 /* Standard Cube texture */
4147 TRACE("Standard Cube texture\n");
4148 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
4150 /* Load up the texture now */
4151 IWineD3DCubeTexture_PreLoad((IWineD3DCubeTexture *) pTexture);
4154 } else {
4155 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dresourcetype(textureType));
4158 } else {
4160 TRACE("Setting to no texture (ie default texture)\n");
4161 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
4162 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
4163 checkGLcall("glBindTexture");
4164 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
4167 /* Disable the old texture binding and enable the new one (unless operations are disabled) */
4168 if (oldTextureDimensions != This->updateStateBlock->textureDimensions[Stage]) {
4170 glDisable(oldTextureDimensions);
4171 checkGLcall("Disable oldTextureDimensions");
4173 if (This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP] != D3DTOP_DISABLE) {
4174 glEnable(This->updateStateBlock->textureDimensions[Stage]);
4175 checkGLcall("glEnable new texture dimensions");
4178 /* If Alpha arg1 is texture then handle the special case when there changes between a
4179 texture and no texture - See comments in set_tex_op */
4180 if ((This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
4181 (((oldTexture == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTexture != NULL))))
4183 reapplyFlags |= REAPPLY_ALPHAOP;
4188 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
4189 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
4190 if (reapplyStates) {
4191 IWineD3DDeviceImpl_SetupTextureStates(iface, Stage, reapplyFlags);
4194 LEAVE_GL();
4195 TRACE("Texture now fully setup\n");
4197 return D3D_OK;
4200 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4201 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4202 TRACE("(%p) : returning %p for stage %ld\n", This, This->updateStateBlock->textures[Stage], Stage);
4203 *ppTexture = (IWineD3DBaseTexture *) This->updateStateBlock->textures[Stage];
4204 if (*ppTexture)
4205 IWineD3DBaseTexture_AddRef(*ppTexture);
4206 return D3D_OK;
4209 /*****
4210 * Get Back Buffer
4211 *****/
4212 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type,
4213 IWineD3DSurface** ppBackBuffer) {
4214 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4215 IWineD3DSwapChain *swapChain;
4216 HRESULT hr;
4218 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4220 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4221 if(hr == D3D_OK){
4222 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4223 IWineD3DSwapChain_Release(swapChain);
4224 }else{
4225 *ppBackBuffer = NULL;
4227 return hr;
4230 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4231 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4232 WARN("(%p) : stub, calling idirect3d for now\n", This);
4233 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4236 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
4237 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4238 IWineD3DSwapChain *swapChain;
4239 HRESULT hr;
4241 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4242 if (hr == D3D_OK) {
4243 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4244 IWineD3DSwapChain_Release(swapChain);
4245 }else{
4246 FIXME("(%p) Error getting display mode\n", This);
4248 return hr;
4250 /*****
4251 * Stateblock related functions
4252 *****/
4254 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4255 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4256 IWineD3DStateBlockImpl *object;
4257 TRACE("(%p)", This);
4258 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4259 if(NULL == object ){
4260 FIXME("(%p)Error allocating memory for stateblock\n", This);
4261 return E_OUTOFMEMORY;
4263 TRACE("(%p) creted object %p\n", This, object);
4264 object->wineD3DDevice= This;
4265 /** FIXME: object->parent = parent; **/
4266 object->parent = NULL;
4267 object->blockType = D3DSBT_ALL;
4268 object->ref = 1;
4269 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
4271 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4272 This->updateStateBlock = object;
4273 This->isRecordingState = TRUE;
4275 TRACE("(%p) recording stateblock %p\n",This , object);
4276 return D3D_OK;
4279 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4280 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4282 if (!This->isRecordingState) {
4283 FIXME("(%p) not recording! returning error\n", This);
4284 *ppStateBlock = NULL;
4285 return D3DERR_INVALIDCALL;
4288 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4289 This->isRecordingState = FALSE;
4290 This->updateStateBlock = This->stateBlock;
4291 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4292 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4293 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4294 return D3D_OK;
4297 /*****
4298 * Scene related functions
4299 *****/
4300 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4301 /* At the moment we have no need for any functionality at the beginning
4302 of a scene */
4303 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4304 TRACE("(%p) : stub\n", This);
4305 return D3D_OK;
4308 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4309 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4310 TRACE("(%p)\n", This);
4311 ENTER_GL();
4312 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4313 glFlush();
4314 checkGLcall("glFlush");
4316 TRACE("End Scene\n");
4317 if(This->renderTarget != NULL){
4319 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4320 IUnknown *targetContainer = NULL;
4321 if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)) {
4322 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
4323 /** always dirtify for now. we must find a better way to see that surface have been modified
4324 (Modifications should will only occur via draw-primitive, but we do need better locking
4325 switching to render-to-texture should remove the overhead though.
4327 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4328 IWineD3DBaseTexture_SetDirty((IWineD3DBaseTexture *)targetContainer, TRUE);
4329 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *)targetContainer);
4330 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4331 IUnknown_Release(targetContainer);
4332 } else
4333 if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)){
4334 /* The surface is stand-alone, so doesn't currently have a context of it's own */
4335 TRACE("(%p) : standalone rendertarget %p\n", This, This->renderTarget);
4336 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4337 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
4338 IWineD3DSurface_PreLoad(This->renderTarget);
4339 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4340 IUnknown_Release(targetContainer);
4345 LEAVE_GL();
4346 return D3D_OK;
4349 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4350 CONST RECT* pSourceRect, CONST RECT* pDestRect,
4351 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4352 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4353 IWineD3DSwapChain *swapChain = NULL;
4354 int i;
4355 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4357 TRACE("(%p) Presenting the frame\n", This);
4359 for(i = 0 ; i < swapchains ; i ++){
4361 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4362 TRACE("presentinng chain %d, %p\n", i, swapChain);
4363 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4364 IWineD3DSwapChain_Release(swapChain);
4367 return D3D_OK;
4370 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4371 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4372 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4374 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4375 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4376 when the depth-buffer format does not contain stencil buffer information, this method fails. */
4377 GLbitfield glMask = 0;
4378 GLboolean old_ztest;
4379 GLfloat old_z_clear_value;
4380 GLint old_stencil_clear_value;
4381 GLfloat old_color_clear_value[4];
4382 unsigned int i;
4383 CONST D3DRECT* curRect;
4385 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4386 Count, pRects, Flags, Z, Stencil);
4388 ENTER_GL();
4390 glEnable(GL_SCISSOR_TEST);
4391 checkGLcall("glEnable GL_SCISSOR_TEST");
4393 if (Count > 0 && pRects) {
4394 curRect = pRects;
4395 } else {
4396 curRect = NULL;
4399 /* Only set the values up once, as they are not changing */
4400 if (Flags & D3DCLEAR_STENCIL) {
4401 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4402 glClearStencil(Stencil);
4403 checkGLcall("glClearStencil");
4404 glMask = glMask | GL_STENCIL_BUFFER_BIT;
4405 glStencilMask(0xFFFFFFFF);
4408 if (Flags & D3DCLEAR_ZBUFFER) {
4409 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4410 glDepthMask(GL_TRUE);
4411 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4412 glClearDepth(Z);
4413 checkGLcall("glClearDepth");
4414 glMask = glMask | GL_DEPTH_BUFFER_BIT;
4417 if (Flags & D3DCLEAR_TARGET) {
4418 TRACE("Clearing screen with glClear to color %lx\n", Color);
4419 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4420 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
4421 ((Color >> 8) & 0xFF) / 255.0f,
4422 ((Color >> 0) & 0xFF) / 255.0f,
4423 ((Color >> 24) & 0xFF) / 255.0f);
4424 checkGLcall("glClearColor");
4426 /* Clear ALL colors! */
4427 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4428 glMask = glMask | GL_COLOR_BUFFER_BIT;
4431 /* Now process each rect in turn */
4432 for (i = 0; i < Count || i == 0; i++) {
4434 if (curRect) {
4435 /* Note gl uses lower left, width/height */
4436 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4437 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4438 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4439 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4440 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4441 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4442 checkGLcall("glScissor");
4443 } else {
4444 glScissor(This->stateBlock->viewport.X,
4445 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4446 This->stateBlock->viewport.Width,
4447 This->stateBlock->viewport.Height);
4448 checkGLcall("glScissor");
4451 /* Clear the selected rectangle (or full screen) */
4452 glClear(glMask);
4453 checkGLcall("glClear");
4455 /* Step to the next rectangle */
4456 if (curRect) curRect = curRect + sizeof(D3DRECT);
4459 /* Restore the old values (why..?) */
4460 if (Flags & D3DCLEAR_STENCIL) {
4461 glClearStencil(old_stencil_clear_value);
4462 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4464 if (Flags & D3DCLEAR_ZBUFFER) {
4465 glDepthMask(old_ztest);
4466 glClearDepth(old_z_clear_value);
4468 if (Flags & D3DCLEAR_TARGET) {
4469 glClearColor(old_color_clear_value[0],
4470 old_color_clear_value[1],
4471 old_color_clear_value[2],
4472 old_color_clear_value[3]);
4473 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4474 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4475 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4476 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4479 glDisable(GL_SCISSOR_TEST);
4480 checkGLcall("glDisable");
4481 LEAVE_GL();
4483 return D3D_OK;
4486 /*****
4487 * Drawing functions
4488 *****/
4489 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4490 UINT PrimitiveCount) {
4492 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4493 This->stateBlock->streamIsUP = FALSE;
4495 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4496 debug_d3dprimitivetype(PrimitiveType),
4497 StartVertex, PrimitiveCount);
4498 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
4500 return D3D_OK;
4503 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4504 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4505 D3DPRIMITIVETYPE PrimitiveType,
4506 INT baseVIndex, UINT minIndex,
4507 UINT NumVertices,UINT startIndex,UINT primCount) {
4509 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4510 UINT idxStride = 2;
4511 IWineD3DIndexBuffer *pIB;
4512 D3DINDEXBUFFER_DESC IdxBufDsc;
4514 pIB = This->stateBlock->pIndexData;
4515 This->stateBlock->streamIsUP = FALSE;
4517 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d \n", This,
4518 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4519 minIndex, NumVertices, startIndex, baseVIndex, primCount);
4521 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4522 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4523 idxStride = 2;
4524 } else {
4525 idxStride = 4;
4528 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex,
4529 startIndex, idxStride,
4530 ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory,
4531 minIndex);
4533 return D3D_OK;
4536 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4537 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4538 UINT VertexStreamZeroStride) {
4539 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4541 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4542 debug_d3dprimitivetype(PrimitiveType),
4543 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4545 if (This->stateBlock->streamSource[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
4547 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4548 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4549 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4550 This->stateBlock->streamIsUP = TRUE;
4551 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
4552 This->stateBlock->streamStride[0] = 0;
4553 This->stateBlock->streamSource[0] = NULL;
4555 /*stream zero settings set to null at end, as per the msdn */
4556 return D3D_OK;
4559 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4560 UINT MinVertexIndex,
4561 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
4562 WINED3DFORMAT IndexDataFormat, CONST void* pVertexStreamZeroData,
4563 UINT VertexStreamZeroStride) {
4564 int idxStride;
4565 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4567 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4568 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4569 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData,
4570 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4572 if (This->stateBlock->streamSource[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
4574 if (IndexDataFormat == WINED3DFMT_INDEX16) {
4575 idxStride = 2;
4576 } else {
4577 idxStride = 4;
4580 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4581 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4582 This->stateBlock->streamIsUP = TRUE;
4583 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4585 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, idxStride, pIndexData, MinVertexIndex);
4587 /* stream zero settings set to null at end as per the msdn */
4588 This->stateBlock->streamSource[0] = NULL;
4589 This->stateBlock->streamStride[0] = 0;
4590 IWineD3DDevice_SetIndices(iface, NULL, 0);
4592 return D3D_OK;
4595 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
4596 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4598 TRACE("(%p) : stub\n", This);
4599 return D3D_OK;
4602 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
4603 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
4604 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
4605 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4607 TRACE("(%p) : stub\n", This);
4608 return D3D_OK;
4610 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface){
4611 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4613 TRACE("(%p) : stub\n", This);
4614 return D3D_OK;
4617 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface){
4618 IWineD3DSwapChain *swapChain;
4619 HRESULT hr;
4620 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4621 if(hr == D3D_OK){
4622 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
4623 IWineD3DSwapChain_Release(swapChain);
4625 return hr;
4628 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4629 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4630 /* return a sensible default */
4631 *pNumPasses = 1;
4632 FIXME("(%p) : stub\n", This);
4633 return D3D_OK;
4636 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4637 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4638 FIXME("(%p) : stub\n", This);
4639 return D3D_OK;
4642 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4643 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4644 FIXME("(%p) : stub\n", This);
4645 return D3D_OK;
4648 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4649 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4650 FIXME("(%p) : stub\n", This);
4651 return D3D_OK;
4654 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4655 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4656 FIXME("(%p) : stub\n", This);
4657 return D3D_OK;
4660 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4661 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4662 FIXME("(%p) : stub\n", This);
4663 return D3D_OK;
4667 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4668 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4669 FIXME("(%p) : stub\n", This);
4670 return FALSE;
4674 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
4675 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4677 pRasterStatus->InVBlank = TRUE;
4678 pRasterStatus->ScanLine = 0;
4679 FIXME("(%p) : stub\n", This);
4680 return D3D_OK;
4684 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4685 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4686 static BOOL showfixmes = TRUE;
4687 if(nSegments != 0.0f){
4688 if( showfixmes){
4689 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4690 showfixmes = FALSE;
4693 return D3D_OK;
4696 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4697 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4698 static BOOL showfixmes = TRUE;
4699 if( showfixmes){
4700 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4701 showfixmes = FALSE;
4703 return 0.0f;
4707 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4708 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4709 FIXME("(%p) : stub\n", This);
4710 return D3D_OK;
4714 /* Implementation details at http://developer.nvidia.com/attach/6494
4716 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
4717 hmm.. no longer supported use
4718 OpenGL evaluators or tessellate surfaces within your application.
4721 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
4722 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo){
4723 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4724 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p) \n", This, Handle, pNumSegs, pRectPatchInfo);
4725 FIXME("(%p) : Stub\n", This);
4726 return D3D_OK;
4730 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
4731 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo){
4732 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4733 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p) \n", This, Handle, pNumSegs, pTriPatchInfo);
4734 FIXME("(%p) : Stub\n", This);
4735 return D3D_OK;
4738 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle){
4739 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4740 TRACE("(%p) Handle(%d)\n", This, Handle);
4741 FIXME("(%p) : Stub\n", This);
4742 return D3D_OK;
4745 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color){
4746 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4748 FIXME("(%p) : stub\n", This);
4749 return D3D_OK;
4752 /* rendertarget and deptth stencil functions */
4753 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget){
4754 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4756 /* FIXME: Implelent RenderTargetIndex >0 */
4757 if(RenderTargetIndex > 0)
4758 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
4760 *ppRenderTarget = (IWineD3DSurface *)This->renderTarget;
4761 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
4762 /* Note inc ref on returned surface */
4763 if(*ppRenderTarget != NULL)
4764 IWineD3DSurface_AddRef(*ppRenderTarget);
4765 return D3D_OK;
4768 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface){
4769 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4770 *ppZStencilSurface = (IWineD3DSurface *)This->depthStencilBuffer;
4771 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
4773 if(*ppZStencilSurface != NULL){
4774 /* Note inc ref on returned surface */
4775 IWineD3DSurface_AddRef(*ppZStencilSurface);
4777 return D3D_OK;
4780 /* internal static helper functions */
4781 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
4782 IWineD3DSurface *RenderSurface);
4784 HRESULT WINAPI static IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain);
4786 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget){
4787 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4788 HRESULT hr = D3D_OK;
4789 WINED3DVIEWPORT viewport;
4791 TRACE("(%p) Swapping rendertarget\n",This);
4792 if (RenderTargetIndex>0) {
4793 FIXME("(%p) Render targets other than the first are not supported\n",This);
4794 RenderTargetIndex=0;
4797 /* MSDN says that null disables the render target
4798 but a device must always be associatated with a render target
4799 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
4801 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
4802 for more details
4804 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
4805 FIXME("Trying to set render target 0 to NULL\n");
4806 return D3DERR_INVALIDCALL;
4808 /* TODO: raplce Impl* usage with interface usage */
4809 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & D3DUSAGE_RENDERTARGET) {
4810 FIXME("(%p)Trying to set the render target to a surface(%p) that wasn't created with a usage of D3DUSAGE_RENDERTARGET\n",This ,pRenderTarget);
4811 return D3DERR_INVALIDCALL;
4813 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
4814 * builds, but I think wine counts as a 'debug' build for now.
4815 ******************************/
4816 /* If we are trying to set what we already have, don't bother */
4817 if (pRenderTarget == This->renderTarget) {
4818 TRACE("Trying to do a NOP SetRenderTarget operation\n");
4819 } else {
4820 /* Otherwise, set the render target up */
4821 TRACE("clearing renderer\n");
4822 /* IWineD3DDeviceImpl_CleanRender(iface); */
4823 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
4824 depending on the renter target implemenattion being used.
4825 A shared context implementation will share all buffers between all rendertargets (including swapchains),
4826 implemenations that use serperate pbuffers for different swapchains or rendertargets will have to duplicate the
4827 stencil buffer and incure an extra memory overhead */
4828 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
4831 if (SUCCEEDED(hr)) {
4832 /* Finally, reset the viewport as the MSDN states. */
4833 /* TODO: Repalace impl usage */
4834 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
4835 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
4836 viewport.X = 0;
4837 viewport.Y = 0;
4838 viewport.MaxZ = 1.0f;
4839 viewport.MinZ = 0.0f;
4840 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
4841 }else{
4842 FIXME("Unknown error setting the render target\n");
4844 return hr;
4847 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil){
4848 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4849 HRESULT hr = D3D_OK;
4850 WINED3DVIEWPORT viewport;
4851 IWineD3DSurface *tmp;
4853 TRACE("(%p) Swapping z-buffer\n",This);
4855 if (pNewZStencil == This->stencilBufferTarget){
4856 TRACE("Trying to do a NOP SetRenderTarget operation\n");
4857 }else{
4858 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
4859 * depending on the renter target implemenattion being used.
4860 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
4861 * implemenations that use serperate pbuffers for different swapchains or rendertargets will have to duplicate the
4862 * stencil buffer and incure an extra memory overhead
4863 ******************************************************/
4866 tmp = This->stencilBufferTarget;
4867 This->stencilBufferTarget = pNewZStencil;
4868 /* should we be calling the parent or the wined3d surface? */
4869 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
4870 if (NULL != tmp) IWineD3DSurface_Release(tmp);
4871 hr = D3D_OK;
4872 /** TODO: glEnable/glDisable on depth/stencil depending on
4873 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
4874 **********************************************************/
4877 if (SUCCEEDED(hr)) {
4878 /* Finally, reset the viewport as the MSDN states.*/
4879 /* TODO: get ridd of Impl usage */
4880 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
4881 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
4882 viewport.X = 0;
4883 viewport.Y = 0;
4884 viewport.MaxZ = 1.0f;
4885 viewport.MinZ = 0.0f;
4886 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
4889 return hr;
4893 /* Internal functions not in DirectX */
4894 /** TODO: move this off to the opengl context manager
4895 *(the swapchain doesn't need to know anything about offscreen rendering!)
4896 ****************************************************/
4898 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
4900 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4901 #if defined(GL_VERSION_1_3) /* @see comments on ActiveRender */
4903 TRACE("(%p), %p\n", This, swapchain);
4905 if (swapchain->win != swapchain->drawable) {
4906 ENTER_GL();
4907 if (swapchain->glCtx != swapchain->render_ctx) {
4908 FIXME("Destroying context %p \n", swapchain->render_ctx);
4909 glXDestroyContext(swapchain->display, swapchain->render_ctx);
4912 FIXME("glXDestroyPbuffer %ld \n", swapchain->drawable);
4913 glXDestroyPbuffer(swapchain->display, swapchain->drawable);
4914 #endif
4915 LEAVE_GL();
4916 /* Set everything back to the way that it ws */
4917 swapchain->render_ctx = swapchain->glCtx;
4918 swapchain->drawable = swapchain->win;
4920 return D3D_OK;
4923 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
4924 * the functiolaity needs splitting up so that we don't do more than we should do.
4925 * this only seems to affect performance a little.
4926 ******************************/
4927 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
4928 IWineD3DSurface *RenderSurface) {
4929 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4930 #ifndef USE_RENDER_MANAGER
4932 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
4933 HRESULT ret = D3DERR_INVALIDCALL;
4935 * Currently only active for GLX >= 1.3
4936 * for others versions we'll have to use GLXPixmaps
4938 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
4939 * as they implements GLX 1.3 but only define GLX_VERSION_1_2
4940 * so only check OpenGL version
4941 * ..........................
4942 * I don't belive that it is a problem with NVidia headers,
4943 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
4944 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
4945 * ATI Note:
4946 * Your application will report GLX version 1.2 on glXQueryVersion.
4947 * However, it is safe to call the GLX 1.3 functions as described below.
4949 #if defined(GL_VERSION_1_3)
4951 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
4952 GLXFBConfig* cfgs = NULL;
4953 int nCfgs = 0;
4954 int attribs[256];
4955 int nAttribs = 0;
4956 IWineD3DSwapChain *currentSwapchain;
4957 IWineD3DSwapChainImpl *swapchain;
4958 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if pussible,
4959 * but switch them off if the StencilSurface is set to NULL
4960 ** *********************************************************/
4961 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
4962 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
4963 #if 0
4964 UINT Width = ((IWineD3DSurfaceImpl *) RenderSurface)->currentDesc.Width;
4965 UINT Height = ((IWineD3DSurfaceImpl *) RenderSurface)->currentDesc.Height;
4966 #endif
4967 IWineD3DSurface *tmp;
4969 /**TODO:
4970 if StencilSurface == NULL && zBufferTarget != NULL then swtich the zbuffer off,
4971 it StencilSurface != NULL && zBufferTarget == NULL switch it on
4974 #define PUSH1(att) attribs[nAttribs++] = (att);
4975 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
4977 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
4979 /** TODO: remove the reff to Impl (context manager should fis this!) **/
4980 IWineD3DSwapChainImpl *impSwapChain;
4981 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
4982 if (NULL == impSwapChain){ /* NOTE: This should NEVER fail */
4983 ERR("(%p) Failed to get a the implicite swapchain\n", iface);
4986 ENTER_GL();
4988 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
4989 PUSH2(GLX_X_RENDERABLE, TRUE);
4990 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4991 TRACE("calling makeglcfg\n");
4992 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
4994 PUSH1(None);
4997 TRACE("calling chooseFGConfig\n");
4998 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
4999 attribs, &nCfgs);
5001 if (!cfgs){ /* OK we didn't find the exact config, so use any reasonably match */
5002 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
5003 why we failed and only show this message once! */
5004 MESSAGE("Failed to find exact match, finding alternative but you may suffer performance issues, try changing xfree's depth to match the requested depth\n"); /**/
5005 nAttribs = 0;
5006 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
5007 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
5008 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
5009 PUSH2(GLX_DOUBLEBUFFER, FALSE);
5010 TRACE("calling makeglcfg\n");
5011 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
5012 PUSH1(None);
5013 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5014 attribs, &nCfgs);
5017 #if 0
5018 #ifdef EXTRA_TRACES
5019 int i;
5020 for (i = 0; i < nCfgs; ++i) {
5021 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
5022 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
5023 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
5025 #endif
5026 #endif
5027 if (NULL != This->renderTarget) {
5028 #ifdef EXTRA_TRACES
5029 glFlush();
5030 vcheckGLcall("glFlush");
5031 /** This is only usefuly if the old render target was a swapchain,
5032 * we need to supercede this with a function that displays
5033 * the current buffer on the screen. This is easy to do in glx1.3 but
5034 * we need to do copy-write pixels in glx 1.2.
5035 ************************************************/
5036 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
5038 printf("Hit Enter to get next frame ...\n");
5039 getchar();
5040 #endif
5043 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&currentSwapchain) != D3D_OK){
5044 /* the selected render target doesn't belong to a swapchain, so use the devices implicite swapchain */
5045 IWineD3DDevice_GetSwapChain(iface, 0, &currentSwapchain);
5049 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
5050 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
5051 **********************************************************************/
5052 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == D3D_OK){
5053 /* We also need to make sure that the lights &co are also in the context of the swapchains */
5054 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
5055 TRACE("making swapchain active\n");
5056 if (RenderSurface != This->renderTarget){
5057 if (RenderSurface == swapchain->backBuffer){
5058 } else {
5059 /* This could be flagged so that some operations work directly with the front buffer */
5060 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
5062 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
5063 == False) {
5064 TRACE("Error in setting current context: context %p drawable %ld !\n",
5065 impSwapChain->glCtx, impSwapChain->win);
5069 #if 0 /* TODO: apply the state block to the 'possibly' new context. */
5070 BOOL oldRecording;
5071 IWineD3DStateBlockImpl *oldUpdateStateBlock;
5072 oldUpdateStateBlock = This->updateStateBlock;
5073 oldRecording= This->isRecordingState;
5074 This->isRecordingState = FALSE;
5075 This->updateStateBlock = This->stateBlock;
5076 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
5078 This->isRecordingState = oldRecording;
5079 This->updateStateBlock = oldUpdateStateBlock;
5080 #endif
5082 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5084 checkGLcall("glXMakeContextCurrent");
5086 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5088 #if 0
5089 else
5090 if (NULL != cfgs &&
5091 (((IWineD3DSwapChainImpl *)currentSwapchain)->drawable == ((IWineD3DSwapChainImpl *)currentSwapchain)->win
5092 || BackBufferFormat != ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Format
5093 || (Width > ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width
5094 || Height > ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height))) {
5096 /** ********************************************************************
5097 * This code is far too leaky to be usefull IWineD3DDeviceImpl_CleanRender
5098 * doesn't seem to work properly and creating a new context Every time is 'extream' overkill.
5099 * The code does however work, and should be moved to a context manager to
5100 * manage caching of pbuffers or render to texture are appropriate.
5102 * There are some real speed vs compatability issues here:
5103 * we should really use a new context for every texture, but that eats ram.
5104 * we should also be restoring the texture to the pbuffer but that eats CPU
5105 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
5106 * but if this means reusing the display backbuffer then we need to make sure that
5107 * states are correctly preserved.
5108 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
5109 * and gain a good performance increase at the cost of compatability.
5110 * I would suggest that, when this is the case, a user configurable flag be made
5111 * available, alowing the user to choose the best emmulated experiance for them.
5112 *********************************************************************/
5115 * TODO: support for faces of cube textures, possibly volumes
5116 * (this should be easy for ATI as I have examples)
5119 GLXContext newContext;
5120 Drawable newDrawable;
5121 XVisualInfo *visinfo;
5123 TRACE("making new buffer\n");
5124 nAttribs = 0;
5125 PUSH2(GLX_PBUFFER_WIDTH, Width);
5126 PUSH2(GLX_PBUFFER_HEIGHT, Height);
5128 #if 0 /* ATI render to texture support */
5129 PUSH2(GLX_LARGEST_PBUFFER, True);/* This is ignored by ATI */
5130 PUSH2(GLX_TEXTURE_FORMAT_ATI, GLX_TEXTURE_RGBA_ATI);
5131 PUSH2(GLX_TEXTURE_TARGET_ATI, cubemap? GLX_TEXTURE_CUBE_MAP_ATI : GLX_TEXTURE_2D_ATI);
5132 PUSH2(GLX_MIPMAP_TEXTURE_ATI, mipmapped? True : False);
5133 #endif
5135 #if 0
5136 /* TODO: discardable Pbuffer */
5137 PUSH2(GLX_PRESERVED_CONTENTS, FALSE);
5138 #endif
5140 PUSH1(None);
5141 newDrawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
5143 /** ****************************************
5144 *GLX1.3 isn't supported by XFree 'yet' untill that point ATI emulates pBuffers
5145 *they note:
5146 * In future releases, we may provide the calls glXCreateNewContext,
5147 * glXQueryDrawable and glXMakeContextCurrent.
5148 * so until then we have to use glXGetVisualFromFBConfig &co..
5149 ********************************************/
5152 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
5153 if (!visinfo) {
5154 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
5156 newContext = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
5157 XFree(visinfo);
5159 /* Make sure that the sorface exists as a glTexture */
5160 IWineD3DSurface_PreLoad(RenderSurface);
5162 newContext = glXCreateNewContext(impSwapChain->display, cfgs[0], GLX_RGBA_TYPE, impSwapChain->glCtx, TRUE);
5164 if (NULL == newContext) {
5165 ERR("cannot create glxContext\n");
5166 }else{
5167 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
5168 FIXME("Created context %p drawable %ld \n", newContext, newDrawable);
5170 if (glXMakeCurrent(impSwapChain->display, newDrawable, newContext) == False) {
5172 TRACE("Error in setting current context: context %p drawable %ld\n", newContext, newDrawable);
5175 /* TODO: find out what of the current context needs to be coppied accross */
5177 checkGLcall("glXMakeContextCurrent");
5179 /* clean renderer should become part of the context manager so I'm not goint to put in in SwapChain just to remove it */
5180 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5181 /** TODO: We may need to copy the bits into the buffer,
5182 * this should !!ONLY!! be done if an operation is performed on the target
5183 * without it being cleared and the buffer is not discardable.
5184 * (basicly only bother preserving the contents if there's a possiblity that it will be reused)
5185 ** *********************************************************************/
5186 impSwapChain->drawable = newDrawable;
5187 impSwapChain->render_ctx = newContext;
5192 #endif
5193 /* clean up the current rendertargets swapchain (if it belonged to one) */
5194 if (currentSwapchain != NULL){
5195 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
5198 /* Were done with the opengl context management, setup the rendertargets */
5200 tmp = This->renderTarget;
5201 This->renderTarget = RenderSurface;
5202 IWineD3DSurface_AddRef(This->renderTarget);
5203 IWineD3DSurface_Release(tmp);
5208 DWORD value;
5209 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
5210 /* Check that the container is not a swapchain member */
5212 IWineD3DSwapChain *tmpSwapChain;
5213 if (D3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)){
5214 This->renderUpsideDown = TRUE;
5215 }else{
5216 This->renderUpsideDown = FALSE;
5217 IWineD3DSwapChain_Release(tmpSwapChain);
5219 /* Force updating the cull mode */
5220 TRACE("setting render state\n");
5221 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
5222 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
5224 /* Force updating projection matrix */
5225 This->last_was_rhw = FALSE;
5226 This->proj_valid = FALSE;
5229 ret = D3D_OK;
5231 if (cfgs != NULL){
5232 XFree(cfgs);
5233 } else {
5234 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
5235 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
5238 #undef PUSH1
5239 #undef PUSH2
5240 if ( NULL != impSwapChain) {
5241 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
5243 LEAVE_GL();
5245 #endif
5246 #else
5248 IWineD3DSurface *tmp;
5249 /* This should be handled outside of this function */
5250 tmp = This->renderTarget;
5251 This->renderTarget = RenderSurface;
5252 IWineD3DSurface_AddRef(This->renderTarget);
5253 IWineD3DSurface_Release( tmp);
5254 tmp = This->stencilBufferTarget;
5255 This->stencilBufferTarget = StencilSurface;
5257 #endif
5258 return ret;
5262 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
5263 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
5264 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5265 /* TODO: the use of Impl is deprecated. */
5266 /* some basic validation checks */
5267 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
5269 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
5271 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
5272 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
5273 return D3DERR_INVALIDCALL;
5275 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
5276 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
5277 return D3DERR_INVALIDCALL;
5279 /* TODO: make the cursor 'real' */
5281 This->xHotSpot = XHotSpot;
5282 This->yHotSpot = YHotSpot;
5284 return D3D_OK;
5287 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
5288 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5289 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
5291 This->xScreenSpace = XScreenSpace;
5292 This->yScreenSpace = YScreenSpace;
5294 return;
5298 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
5299 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5300 TRACE("(%p) : visible(%d)\n", This, bShow);
5302 This->bCursorVisible = bShow;
5304 return D3D_OK;
5307 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
5308 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5309 FIXME("(%p) : stub\n", This); /* No way of notifying yet! */
5310 return D3D_OK;
5314 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
5315 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5316 /** FIXME: Resource tracking needs to be done,
5317 * The closes we can do to this is set the priorities of all managed textures low
5318 * and then reset them.
5319 ***********************************************************/
5320 FIXME("(%p) : stub\n", This);
5321 return D3D_OK;
5324 HRESULT WINAPI IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
5325 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5326 /** FIXME: Resource trascking needs to be done.
5327 * in effect this pulls all non only default
5328 * textures out of video memory and deletes all glTextures (glDeleteTextures)
5329 * and should clear down the context and set it up according to pPresentationParameters
5330 ***********************************************************/
5331 FIXME("(%p) : stub\n", This);
5332 return D3D_OK;
5335 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs){
5336 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5337 /** FIXME: always true at the moment **/
5338 if(bEnableDialogs == FALSE){
5339 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
5341 return D3D_OK;
5345 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
5346 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5348 FIXME("(%p) : stub\n", This);
5349 /* Setup some reasonable defaults */
5350 pParameters->AdapterOrdinal = 0; /* always for now */
5351 pParameters->DeviceType = D3DDEVTYPE_HAL; /* always for now */
5352 pParameters->hFocusWindow = 0;
5353 pParameters->BehaviorFlags =0;
5354 return D3D_OK;
5357 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
5358 IWineD3DSwapChain *swapchain;
5359 HRESULT hrc = D3D_OK;
5361 TRACE("Relaying to swapchain\n");
5363 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK){
5364 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (D3DGAMMARAMP *)pRamp);
5365 IWineD3DSwapChain_Release(swapchain);
5367 return;
5370 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
5371 IWineD3DSwapChain *swapchain;
5372 HRESULT hrc = D3D_OK;
5374 TRACE("Relaying to swapchain\n");
5376 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK){
5377 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
5378 IWineD3DSwapChain_Release(swapchain);
5380 return;
5383 /**********************************************************
5384 * IWineD3DDevice VTbl follows
5385 **********************************************************/
5387 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
5389 /*** IUnknown methods ***/
5390 IWineD3DDeviceImpl_QueryInterface,
5391 IWineD3DDeviceImpl_AddRef,
5392 IWineD3DDeviceImpl_Release,
5393 /*** IWineD3DDevice methods ***/
5394 IWineD3DDeviceImpl_GetParent,
5395 /*** Creation methods**/
5396 IWineD3DDeviceImpl_CreateVertexBuffer,
5397 IWineD3DDeviceImpl_CreateIndexBuffer,
5398 IWineD3DDeviceImpl_CreateStateBlock,
5399 IWineD3DDeviceImpl_CreateSurface,
5400 IWineD3DDeviceImpl_CreateTexture,
5401 IWineD3DDeviceImpl_CreateVolumeTexture,
5402 IWineD3DDeviceImpl_CreateVolume,
5403 IWineD3DDeviceImpl_CreateCubeTexture,
5404 IWineD3DDeviceImpl_CreateQuery,
5405 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
5406 IWineD3DDeviceImpl_CreateVertexDeclaration,
5407 IWineD3DDeviceImpl_CreateVertexShader,
5408 IWineD3DDeviceImpl_CreatePixelShader,
5410 /*** Odd functions **/
5411 IWineD3DDeviceImpl_EvictManagedResources,
5412 IWineD3DDeviceImpl_GetAvailableTextureMem,
5413 IWineD3DDeviceImpl_GetBackBuffer,
5414 IWineD3DDeviceImpl_GetCreationParameters,
5415 IWineD3DDeviceImpl_GetDeviceCaps,
5416 IWineD3DDeviceImpl_GetDirect3D,
5417 IWineD3DDeviceImpl_GetDisplayMode,
5418 IWineD3DDeviceImpl_GetNumberOfSwapChains,
5419 IWineD3DDeviceImpl_GetRasterStatus,
5420 IWineD3DDeviceImpl_GetSwapChain,
5421 IWineD3DDeviceImpl_Reset,
5422 IWineD3DDeviceImpl_SetDialogBoxMode,
5423 IWineD3DDeviceImpl_SetCursorProperties,
5424 IWineD3DDeviceImpl_SetCursorPosition,
5425 IWineD3DDeviceImpl_ShowCursor,
5426 IWineD3DDeviceImpl_TestCooperativeLevel,
5427 /*** Getters and setters **/
5428 IWineD3DDeviceImpl_SetClipPlane,
5429 IWineD3DDeviceImpl_GetClipPlane,
5430 IWineD3DDeviceImpl_SetClipStatus,
5431 IWineD3DDeviceImpl_GetClipStatus,
5432 IWineD3DDeviceImpl_SetCurrentTexturePalette,
5433 IWineD3DDeviceImpl_GetCurrentTexturePalette,
5434 IWineD3DDeviceImpl_SetDepthStencilSurface,
5435 IWineD3DDeviceImpl_GetDepthStencilSurface,
5436 IWineD3DDeviceImpl_SetFVF,
5437 IWineD3DDeviceImpl_GetFVF,
5438 IWineD3DDeviceImpl_SetGammaRamp,
5439 IWineD3DDeviceImpl_GetGammaRamp,
5440 IWineD3DDeviceImpl_SetIndices,
5441 IWineD3DDeviceImpl_GetIndices,
5442 IWineD3DDeviceImpl_SetLight,
5443 IWineD3DDeviceImpl_GetLight,
5444 IWineD3DDeviceImpl_SetLightEnable,
5445 IWineD3DDeviceImpl_GetLightEnable,
5446 IWineD3DDeviceImpl_SetMaterial,
5447 IWineD3DDeviceImpl_GetMaterial,
5448 IWineD3DDeviceImpl_SetNPatchMode,
5449 IWineD3DDeviceImpl_GetNPatchMode,
5450 IWineD3DDeviceImpl_SetPaletteEntries,
5451 IWineD3DDeviceImpl_GetPaletteEntries,
5452 IWineD3DDeviceImpl_SetPixelShader,
5453 IWineD3DDeviceImpl_GetPixelShader,
5454 IWineD3DDeviceImpl_SetPixelShaderConstantB,
5455 IWineD3DDeviceImpl_GetPixelShaderConstantB,
5456 IWineD3DDeviceImpl_SetPixelShaderConstantI,
5457 IWineD3DDeviceImpl_GetPixelShaderConstantI,
5458 IWineD3DDeviceImpl_SetPixelShaderConstantF,
5459 IWineD3DDeviceImpl_GetPixelShaderConstantF,
5460 IWineD3DDeviceImpl_SetRenderState,
5461 IWineD3DDeviceImpl_GetRenderState,
5462 IWineD3DDeviceImpl_SetRenderTarget,
5463 IWineD3DDeviceImpl_GetRenderTarget,
5464 IWineD3DDeviceImpl_SetSamplerState,
5465 IWineD3DDeviceImpl_GetSamplerState,
5466 IWineD3DDeviceImpl_SetScissorRect,
5467 IWineD3DDeviceImpl_GetScissorRect,
5468 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
5469 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
5470 IWineD3DDeviceImpl_SetStreamSource,
5471 IWineD3DDeviceImpl_GetStreamSource,
5472 IWineD3DDeviceImpl_SetStreamSourceFreq,
5473 IWineD3DDeviceImpl_GetStreamSourceFreq,
5474 IWineD3DDeviceImpl_SetTexture,
5475 IWineD3DDeviceImpl_GetTexture,
5476 IWineD3DDeviceImpl_SetTextureStageState,
5477 IWineD3DDeviceImpl_GetTextureStageState,
5478 IWineD3DDeviceImpl_SetTransform,
5479 IWineD3DDeviceImpl_GetTransform,
5480 IWineD3DDeviceImpl_SetVertexDeclaration,
5481 IWineD3DDeviceImpl_GetVertexDeclaration,
5482 IWineD3DDeviceImpl_SetVertexShader,
5483 IWineD3DDeviceImpl_GetVertexShader,
5484 IWineD3DDeviceImpl_SetVertexShaderConstantB,
5485 IWineD3DDeviceImpl_GetVertexShaderConstantB,
5486 IWineD3DDeviceImpl_SetVertexShaderConstantI,
5487 IWineD3DDeviceImpl_GetVertexShaderConstantI,
5488 IWineD3DDeviceImpl_SetVertexShaderConstantF,
5489 IWineD3DDeviceImpl_GetVertexShaderConstantF,
5490 IWineD3DDeviceImpl_SetViewport,
5491 IWineD3DDeviceImpl_GetViewport,
5492 IWineD3DDeviceImpl_MultiplyTransform,
5493 IWineD3DDeviceImpl_ValidateDevice,
5494 IWineD3DDeviceImpl_ProcessVertices,
5495 /*** State block ***/
5496 IWineD3DDeviceImpl_BeginStateBlock,
5497 IWineD3DDeviceImpl_EndStateBlock,
5498 /*** Scene management ***/
5499 IWineD3DDeviceImpl_BeginScene,
5500 IWineD3DDeviceImpl_EndScene,
5501 IWineD3DDeviceImpl_Present,
5502 IWineD3DDeviceImpl_Clear,
5503 /*** Drawing ***/
5504 IWineD3DDeviceImpl_DrawPrimitive,
5505 IWineD3DDeviceImpl_DrawIndexedPrimitive,
5506 IWineD3DDeviceImpl_DrawPrimitiveUP,
5507 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
5508 IWineD3DDeviceImpl_DrawRectPatch,
5509 IWineD3DDeviceImpl_DrawTriPatch,
5510 IWineD3DDeviceImpl_DeletePatch,
5511 IWineD3DDeviceImpl_ColorFill,
5512 IWineD3DDeviceImpl_UpdateTexture,
5513 IWineD3DDeviceImpl_UpdateSurface,
5514 IWineD3DDeviceImpl_StretchRect,
5515 IWineD3DDeviceImpl_GetRenderTargetData,
5516 IWineD3DDeviceImpl_GetFrontBufferData,
5517 /*** Internal use IWineD3DDevice methods ***/
5518 IWineD3DDeviceImpl_SetupTextureStates
5522 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
5523 WINED3DRS_ALPHABLENDENABLE ,
5524 WINED3DRS_ALPHAFUNC ,
5525 WINED3DRS_ALPHAREF ,
5526 WINED3DRS_ALPHATESTENABLE ,
5527 WINED3DRS_BLENDOP ,
5528 WINED3DRS_COLORWRITEENABLE ,
5529 WINED3DRS_DESTBLEND ,
5530 WINED3DRS_DITHERENABLE ,
5531 WINED3DRS_FILLMODE ,
5532 WINED3DRS_FOGDENSITY ,
5533 WINED3DRS_FOGEND ,
5534 WINED3DRS_FOGSTART ,
5535 WINED3DRS_LASTPIXEL ,
5536 WINED3DRS_SHADEMODE ,
5537 WINED3DRS_SRCBLEND ,
5538 WINED3DRS_STENCILENABLE ,
5539 WINED3DRS_STENCILFAIL ,
5540 WINED3DRS_STENCILFUNC ,
5541 WINED3DRS_STENCILMASK ,
5542 WINED3DRS_STENCILPASS ,
5543 WINED3DRS_STENCILREF ,
5544 WINED3DRS_STENCILWRITEMASK ,
5545 WINED3DRS_STENCILZFAIL ,
5546 WINED3DRS_TEXTUREFACTOR ,
5547 WINED3DRS_WRAP0 ,
5548 WINED3DRS_WRAP1 ,
5549 WINED3DRS_WRAP2 ,
5550 WINED3DRS_WRAP3 ,
5551 WINED3DRS_WRAP4 ,
5552 WINED3DRS_WRAP5 ,
5553 WINED3DRS_WRAP6 ,
5554 WINED3DRS_WRAP7 ,
5555 WINED3DRS_ZENABLE ,
5556 WINED3DRS_ZFUNC ,
5557 WINED3DRS_ZWRITEENABLE
5560 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
5561 WINED3DTSS_ADDRESSW ,
5562 WINED3DTSS_ALPHAARG0 ,
5563 WINED3DTSS_ALPHAARG1 ,
5564 WINED3DTSS_ALPHAARG2 ,
5565 WINED3DTSS_ALPHAOP ,
5566 WINED3DTSS_BUMPENVLOFFSET ,
5567 WINED3DTSS_BUMPENVLSCALE ,
5568 WINED3DTSS_BUMPENVMAT00 ,
5569 WINED3DTSS_BUMPENVMAT01 ,
5570 WINED3DTSS_BUMPENVMAT10 ,
5571 WINED3DTSS_BUMPENVMAT11 ,
5572 WINED3DTSS_COLORARG0 ,
5573 WINED3DTSS_COLORARG1 ,
5574 WINED3DTSS_COLORARG2 ,
5575 WINED3DTSS_COLOROP ,
5576 WINED3DTSS_RESULTARG ,
5577 WINED3DTSS_TEXCOORDINDEX ,
5578 WINED3DTSS_TEXTURETRANSFORMFLAGS
5581 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
5582 WINED3DSAMP_ADDRESSU ,
5583 WINED3DSAMP_ADDRESSV ,
5584 WINED3DSAMP_ADDRESSW ,
5585 WINED3DSAMP_BORDERCOLOR ,
5586 WINED3DSAMP_MAGFILTER ,
5587 WINED3DSAMP_MINFILTER ,
5588 WINED3DSAMP_MIPFILTER ,
5589 WINED3DSAMP_MIPMAPLODBIAS ,
5590 WINED3DSAMP_MAXMIPLEVEL ,
5591 WINED3DSAMP_MAXANISOTROPY ,
5592 WINED3DSAMP_SRGBTEXTURE ,
5593 WINED3DSAMP_ELEMENTINDEX
5596 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
5597 WINED3DRS_AMBIENT ,
5598 WINED3DRS_AMBIENTMATERIALSOURCE ,
5599 WINED3DRS_CLIPPING ,
5600 WINED3DRS_CLIPPLANEENABLE ,
5601 WINED3DRS_COLORVERTEX ,
5602 WINED3DRS_DIFFUSEMATERIALSOURCE ,
5603 WINED3DRS_EMISSIVEMATERIALSOURCE ,
5604 WINED3DRS_FOGDENSITY ,
5605 WINED3DRS_FOGEND ,
5606 WINED3DRS_FOGSTART ,
5607 WINED3DRS_FOGTABLEMODE ,
5608 WINED3DRS_FOGVERTEXMODE ,
5609 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
5610 WINED3DRS_LIGHTING ,
5611 WINED3DRS_LOCALVIEWER ,
5612 WINED3DRS_MULTISAMPLEANTIALIAS ,
5613 WINED3DRS_MULTISAMPLEMASK ,
5614 WINED3DRS_NORMALIZENORMALS ,
5615 WINED3DRS_PATCHEDGESTYLE ,
5616 WINED3DRS_POINTSCALE_A ,
5617 WINED3DRS_POINTSCALE_B ,
5618 WINED3DRS_POINTSCALE_C ,
5619 WINED3DRS_POINTSCALEENABLE ,
5620 WINED3DRS_POINTSIZE ,
5621 WINED3DRS_POINTSIZE_MAX ,
5622 WINED3DRS_POINTSIZE_MIN ,
5623 WINED3DRS_POINTSPRITEENABLE ,
5624 WINED3DRS_RANGEFOGENABLE ,
5625 WINED3DRS_SPECULARMATERIALSOURCE ,
5626 WINED3DRS_TWEENFACTOR ,
5627 WINED3DRS_VERTEXBLEND
5630 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
5631 WINED3DTSS_TEXCOORDINDEX ,
5632 WINED3DTSS_TEXTURETRANSFORMFLAGS
5635 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
5636 WINED3DSAMP_DMAPOFFSET