Faster implementation of wcstombs that handles overlapping buffers
[wine/wine-kai.git] / dlls / wined3d / device.c
blob5e930aff61de5d8cdee78ce65066de11477cbf13
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 /* Memory tracking and object counting */
54 static unsigned int emulated_textureram = 64*1024*1024;
56 /* TODO: setup some flags in the regestry to enable, disable pbuffer support */
57 /* enable pbuffer support for offscreen textures */
58 BOOL pbuffer_support = TRUE;
59 /* allocate one pbuffer per surface */
60 BOOL pbuffer_per_surface = FALSE;
62 /* helper macros */
63 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return D3DERR_OUTOFVIDEOMEMORY;}
65 #define D3DCREATEOBJECTINSTANCE(object, type) { \
66 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
67 D3DMEMCHECK(object, pp##type); \
68 object->lpVtbl = &IWineD3D##type##_Vtbl; \
69 object->wineD3DDevice = This; \
70 object->parent = parent; \
71 object->ref = 1; \
72 *pp##type = (IWineD3D##type *) object; \
75 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
76 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
77 D3DMEMCHECK(object, pp##type); \
78 object->lpVtbl = &IWineD3D##type##_Vtbl; \
79 object->resource.wineD3DDevice = This; \
80 object->resource.parent = parent; \
81 object->resource.resourceType = d3dtype; \
82 object->resource.ref = 1; \
83 object->resource.pool = Pool; \
84 object->resource.format = Format; \
85 object->resource.usage = Usage; \
86 object->resource.size = _size; \
87 /* Check that we have enough video ram left */ \
88 if (Pool == D3DPOOL_DEFAULT) { \
89 if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
90 WARN("Out of 'bogus' video memory\n"); \
91 HeapFree(GetProcessHeap(),0,object); \
92 *pp##type = NULL; \
93 return D3DERR_OUTOFVIDEOMEMORY; \
94 } \
95 globalChangeGlRam(_size); \
96 } \
97 object->resource.allocatedMemory = (0 == _size ? NULL : Pool == D3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
98 if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != D3DPOOL_DEFAULT) { \
99 FIXME("Out of memory!\n"); \
100 HeapFree(GetProcessHeap(), 0, object); \
101 *pp##type = NULL; \
102 return D3DERR_OUTOFVIDEOMEMORY; \
104 *pp##type = (IWineD3D##type *) object; \
105 TRACE("(%p) : Created resource %p\n", This, object); \
108 #define D3DINITILIZEBASETEXTURE(_basetexture) { \
109 _basetexture.levels = Levels; \
110 _basetexture.filterType = (Usage & D3DUSAGE_AUTOGENMIPMAP) ? D3DTEXF_LINEAR : D3DTEXF_NONE; \
111 _basetexture.LOD = 0; \
112 _basetexture.dirty = TRUE; \
115 /**********************************************************
116 * Global variable / Constants follow
117 **********************************************************/
118 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
120 /**********************************************************
121 * Utility functions follow
122 **********************************************************/
123 /* Convert the D3DLIGHT properties into equivalent gl lights */
124 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
126 float quad_att;
127 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
128 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
130 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
131 glMatrixMode(GL_MODELVIEW);
132 glPushMatrix();
133 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
135 /* Diffuse: */
136 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
137 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
138 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
139 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
140 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
141 checkGLcall("glLightfv");
143 /* Specular */
144 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
145 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
146 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
147 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
148 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
149 checkGLcall("glLightfv");
151 /* Ambient */
152 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
153 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
154 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
155 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
156 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
157 checkGLcall("glLightfv");
159 /* Attenuation - Are these right? guessing... */
160 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
161 checkGLcall("glLightf");
162 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
163 checkGLcall("glLightf");
165 if ((lightInfo->OriginalParms.Range * lightInfo->OriginalParms.Range) != 0 ) {
166 quad_att = 1.4/(lightInfo->OriginalParms.Range*lightInfo->OriginalParms.Range);
167 } else {
168 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
171 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
172 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
173 checkGLcall("glLightf");
175 switch (lightInfo->OriginalParms.Type) {
176 case D3DLIGHT_POINT:
177 /* Position */
178 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
179 checkGLcall("glLightfv");
180 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
181 checkGLcall("glLightf");
182 /* FIXME: Range */
183 break;
185 case D3DLIGHT_SPOT:
186 /* Position */
187 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
188 checkGLcall("glLightfv");
189 /* Direction */
190 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
191 checkGLcall("glLightfv");
192 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
193 checkGLcall("glLightf");
194 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
195 checkGLcall("glLightf");
196 /* FIXME: Range */
197 break;
199 case D3DLIGHT_DIRECTIONAL:
200 /* Direction */
201 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
202 checkGLcall("glLightfv");
203 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
204 checkGLcall("glLightf");
205 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
206 checkGLcall("glLightf");
207 break;
209 default:
210 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
213 /* Restore the modelview matrix */
214 glPopMatrix();
217 /* Apply the current values to the specified texture stage */
218 void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Stage, DWORD Flags) {
219 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
220 int i = 0;
221 float col[4];
222 BOOL changeTexture = TRUE;
224 TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
225 for (i = 1; i < HIGHEST_TEXTURE_STATE; i++) {
227 BOOL skip = FALSE;
229 switch (i) {
230 /* Performance: For texture states where multiples effect the outcome, only bother
231 applying the last one as it will pick up all the other values */
232 case WINED3DTSS_COLORARG0: /* Will be picked up when setting color op */
233 case WINED3DTSS_COLORARG1: /* Will be picked up when setting color op */
234 case WINED3DTSS_COLORARG2: /* Will be picked up when setting color op */
235 case WINED3DTSS_ALPHAARG0: /* Will be picked up when setting alpha op */
236 case WINED3DTSS_ALPHAARG1: /* Will be picked up when setting alpha op */
237 case WINED3DTSS_ALPHAARG2: /* Will be picked up when setting alpha op */
238 skip = TRUE;
239 break;
241 /* Performance: If the texture states only impact settings for the texture unit
242 (compared to the texture object) then there is no need to reapply them. The
243 only time they need applying is the first time, since we cheat and put the
244 values into the stateblock without applying.
245 Per-texture unit: texture function (eg. combine), ops and args
246 texture env color
247 texture generation settings
248 Note: Due to some special conditions there may be a need to do particular ones
249 of these, which is what the Flags allows */
250 case WINED3DTSS_COLOROP:
251 case WINED3DTSS_TEXCOORDINDEX:
252 if (!(Flags == REAPPLY_ALL)) skip=TRUE;
253 break;
255 case WINED3DTSS_ALPHAOP:
256 if (!(Flags & REAPPLY_ALPHAOP)) skip=TRUE;
257 break;
259 default:
260 skip = FALSE;
263 if (skip == FALSE) {
264 /* Performance: Only change to this texture if we have to */
265 if (changeTexture) {
266 /* Make appropriate texture active */
267 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
268 GLACTIVETEXTURE(Stage);
269 } else if (Stage > 0) {
270 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
272 changeTexture = FALSE;
275 /* Now apply the change */
276 IWineD3DDevice_SetTextureStageState(iface, Stage, i, This->stateBlock->textureState[Stage][i]);
280 /* apply the sampler states to the texture */
281 for (i = 1; i <= HIGHEST_SAMPLER_STATE;i++) {
282 IWineD3DDevice_SetSamplerState(iface, Stage, i, This->stateBlock->samplerState[Stage][i]);
285 /* Note the D3DRS value applies to all textures, but GL has one
286 * per texture, so apply it now ready to be used!
288 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
289 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
290 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
292 TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
295 /**********************************************************
296 * IUnknown parts follows
297 **********************************************************/
299 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
301 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
302 /* FIXME: This needs to extend an IWineD3DBaseObject */
304 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
305 if (IsEqualGUID(riid, &IID_IUnknown)
306 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
307 IUnknown_AddRef(iface);
308 *ppobj = This;
309 return D3D_OK;
312 return E_NOINTERFACE;
315 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
316 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
317 ULONG refCount = InterlockedIncrement(&This->ref);
319 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
320 return refCount;
323 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
324 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
325 ULONG refCount = InterlockedDecrement(&This->ref);
327 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
329 if (!refCount) {
330 /* TODO: Clean up all the surfaces and textures! */
331 /* FIXME: Create targets and state blocks in d3d8 */
332 if (((IWineD3DImpl *)This->wineD3D)->dxVersion > 8) { /*We don't create a state block in d3d8 yet*/
333 /* NOTE: You must release the parent if the object was created via a callback
334 ** ***************************/
335 int i;
336 IUnknown* swapChainParent;
338 /* Release all of the swapchains, except the implicit swapchain (#0) */
339 for(i = 1; i < This->numberOfSwapChains; i++) {
340 /* TODO: don't access swapchains[x] directly! */
341 IWineD3DSwapChain_Release(This->swapchains[i]);
344 if (This->stateBlock != NULL) {
345 IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->stateBlock);
348 if (This->swapchains[0] != NULL) {
349 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
350 /* TODO: don't access swapchains[x] directly!, check that there are no-more swapchains left for this device! */
351 IWineD3DSwapChain_GetParent(This->swapchains[0], &swapChainParent);
352 IUnknown_Release(swapChainParent); /* once for the get parent */
353 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
354 FIXME("(%p) Something's still holding the implicit swapchain\n",This);
359 IWineD3D_Release(This->wineD3D);
360 HeapFree(GetProcessHeap(), 0, This);
362 return refCount;
365 /**********************************************************
366 * IWineD3DDevice implementation follows
367 **********************************************************/
368 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
369 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
370 *pParent = This->parent;
371 IUnknown_AddRef(This->parent);
372 return D3D_OK;
375 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
376 DWORD FVF, D3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
377 IUnknown *parent) {
378 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
379 IWineD3DVertexBufferImpl *object;
380 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
381 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, D3DRTYPE_VERTEXBUFFER, Size)
383 /*TODO: use VBO's */
384 if (Pool == D3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
385 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
387 object->fvf = FVF;
389 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
390 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
392 return D3D_OK;
395 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
396 WINED3DFORMAT Format, D3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
397 HANDLE *sharedHandle, IUnknown *parent) {
398 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
399 IWineD3DIndexBufferImpl *object;
400 TRACE("(%p) Creating index buffer\n", This);
402 /* Allocate the storage for the device */
403 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,D3DRTYPE_INDEXBUFFER, Length)
405 /*TODO: use VBO's */
406 if (Pool == D3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
407 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
410 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
411 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
412 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
414 return D3D_OK;
417 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, D3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
419 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
420 IWineD3DStateBlockImpl *object;
421 int i,j;
423 D3DCREATEOBJECTINSTANCE(object, StateBlock)
424 object->blockType = Type;
426 /* Special case - Used during initialization to produce a placeholder stateblock
427 so other functions called can update a state block */
428 if (Type == (D3DSTATEBLOCKTYPE) 0) {
429 /* Don't bother increasing the reference count otherwise a device will never
430 be freed due to circular dependencies */
431 return D3D_OK;
434 /* Otherwise, might as well set the whole state block to the appropriate values */
435 IWineD3DDevice_AddRef(iface);
436 /* Otherwise, might as well set the whole state block to the appropriate values */
437 if ( This->stateBlock != NULL) {
438 memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
439 } else {
440 memset(object->streamFreq, 1, sizeof(object->streamFreq));
443 /* Reset the ref and type after kludging it */
444 object->wineD3DDevice = This;
445 object->ref = 1;
446 object->blockType = Type;
448 TRACE("Updating changed flags appropriate for type %d\n", Type);
450 if (Type == D3DSBT_ALL) {
451 TRACE("ALL => Pretend everything has changed\n");
452 memset(&object->changed, TRUE, sizeof(This->stateBlock->changed));
453 } else if (Type == D3DSBT_PIXELSTATE) {
455 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
456 /* TODO: Pixel Shader Constants */
457 object->changed.pixelShader = TRUE;
458 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
459 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
461 for (j = 0; j < GL_LIMITS(textures); i++) {
462 for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
463 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
466 /* Setting sampler block changes states */
467 for (j = 0 ; j < GL_LIMITS(samplers); j++) {
468 for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
470 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
473 } else if (Type == D3DSBT_VERTEXSTATE) {
475 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
477 /* TODO: Vertex Shader Constants */
478 object->changed.vertexShader = TRUE;
479 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
480 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
482 for (j = 0; j < GL_LIMITS(textures); i++) {
483 for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
484 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
487 /* Setting sampler block changes states */
488 for (j = 0 ; j < GL_LIMITS(samplers); j++) {
489 for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
490 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
494 /* Duplicate light chain */
496 PLIGHTINFOEL *src = NULL;
497 PLIGHTINFOEL *dst = NULL;
498 PLIGHTINFOEL *newEl = NULL;
499 src = This->stateBlock->lights;
500 object->lights = NULL;
503 while (src) {
504 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
505 if (newEl == NULL) return D3DERR_OUTOFVIDEOMEMORY;
506 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
507 newEl->prev = dst;
508 newEl->changed = TRUE;
509 newEl->enabledChanged = TRUE;
510 if (dst == NULL) {
511 object->lights = newEl;
512 } else {
513 dst->next = newEl;
515 dst = newEl;
516 src = src->next;
521 } else {
522 FIXME("Unrecognized state block type %d\n", Type);
525 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
526 return D3D_OK;
530 /* ************************************
531 MSDN:
532 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
534 Discard
535 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
537 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.
539 ******************************** */
541 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) {
542 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
543 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
544 unsigned int pow2Width, pow2Height;
545 unsigned int Size = 1;
546 TRACE("(%p) Create surface\n",This);
548 /** FIXME: Check ranges on the inputs are valid
549 * MSDN
550 * MultisampleQuality
551 * [in] Quality level. The valid range is between zero and one less than the level
552 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
553 * Passing a larger value returns the error D3DERR_INVALIDCALL. The MultisampleQuality
554 * values of paired render targets, depth stencil surfaces, and the MultiSample type
555 * must all match.
556 *******************************/
560 * TODO: Discard MSDN
561 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
563 * If this flag is set, the contents of the depth stencil buffer will be
564 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
565 * with a different depth surface.
567 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
568 ***************************/
570 if(MultisampleQuality < 0) {
571 FIXME("Invalid multisample level %ld \n", MultisampleQuality);
572 return D3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
575 if(MultisampleQuality > 0) {
576 FIXME("MultisampleQuality set to %ld, substituting 0 \n" , MultisampleQuality);
577 MultisampleQuality=0;
580 /* Non-power2 support */
582 /* Find the nearest pow2 match */
583 pow2Width = pow2Height = 1;
584 while (pow2Width < Width) pow2Width <<= 1;
585 while (pow2Height < Height) pow2Height <<= 1;
587 if (pow2Width > Width || pow2Height > Height) {
588 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
589 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
590 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
591 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d) \n",
592 This, Width, Height);
593 return D3DERR_NOTAVAILABLE;
597 /** TODO: Check against the maximum texture sizes supported by the video card **/
600 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
601 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
602 * space!
603 *********************************/
604 if (Format == WINED3DFMT_DXT1) {
605 /* DXT1 is half byte per pixel */
606 Size = ((max(Width,4) * D3DFmtGetBpp(This, Format)) * max(Height,4)) >> 1;
608 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
609 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
610 Size = ((max(Width,4) * D3DFmtGetBpp(This, Format)) * max(Height,4));
611 } else {
612 Size = (Width * D3DFmtGetBpp(This, Format)) * Height;
615 /** Create the and initilise surface resource **/
616 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,D3DRTYPE_SURFACE, Size)
617 object->container = (IUnknown*) This;
619 object->currentDesc.Width = Width;
620 object->currentDesc.Height = Height;
621 object->currentDesc.MultiSampleType = MultiSample;
622 object->currentDesc.MultiSampleQuality = MultisampleQuality;
624 /* Setup some glformat defaults */
625 object->glDescription.glFormat = D3DFmt2GLFmt(This, object->resource.format);
626 object->glDescription.glFormatInternal = D3DFmt2GLIntFmt(This, object->resource.format);
627 object->glDescription.glType = D3DFmt2GLType(This, object->resource.format);
628 object->glDescription.textureName = 0;
629 object->glDescription.level = Level;
630 object->glDescription.target = GL_TEXTURE_2D;
632 /* Internal data */
633 object->pow2Width = pow2Width;
634 object->pow2Height = pow2Height;
635 object->nonpow2 = (pow2Width != Width || pow2Height != Height) ? TRUE : FALSE;
636 object->discard = Discard;
637 object->activeLock = FALSE;
638 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
639 object->pow2Size = (pow2Width * object->bytesPerPixel) * pow2Height;
641 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
643 /* Precalculated scaling for 'faked' non power of two texture coords */
644 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
645 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
646 TRACE(" xf(%f) yf(%f) \n", object->pow2scalingFactorX, object->pow2scalingFactorY);
648 TRACE("Pool %d %d %d %d",Pool, D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM);
650 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
651 * this function is too deap to need to care about things like this.
652 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
653 * ****************************************/
654 switch(Pool) {
655 case D3DPOOL_SCRATCH:
656 if(Lockable == FALSE)
657 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
658 which are mutually exclusive, setting lockable to true\n");
659 Lockable = TRUE;
660 break;
661 case D3DPOOL_SYSTEMMEM:
662 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
663 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
664 case D3DPOOL_MANAGED:
665 if(Usage == D3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
666 Usage of DYNAMIC which are mutually exclusive, not doing \
667 anything just telling you.\n");
668 break;
669 case D3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
670 if(!(Usage & D3DUSAGE_DYNAMIC) && !(Usage & D3DUSAGE_RENDERTARGET)
671 && !(Usage && D3DUSAGE_DEPTHSTENCIL ) && Lockable == TRUE)
672 FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
673 break;
674 default:
675 FIXME("(%p) Unknown pool %d\n", This, Pool);
676 break;
679 if (Usage & D3DUSAGE_RENDERTARGET && Pool != D3DPOOL_DEFAULT) {
680 FIXME("Trying to create a render target that isn't in the default pool\n");
684 object->locked = FALSE;
685 object->lockable = (WINED3DFMT_D16_LOCKABLE == Format) ? TRUE : Lockable;
687 /* mark the texture as dirty so that it get's loaded first time around*/
688 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
689 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
690 This, Width, Height, Format, debug_d3dformat(Format),
691 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
692 return D3D_OK;
696 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
697 DWORD Usage, WINED3DFORMAT Format, D3DPOOL Pool,
698 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
699 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
701 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
702 IWineD3DTextureImpl *object;
703 unsigned int i;
704 UINT tmpW;
705 UINT tmpH;
706 HRESULT hr;
708 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) .... \n", This, Width, Height, Levels, Usage);
710 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, D3DRTYPE_TEXTURE, 0);
711 D3DINITILIZEBASETEXTURE(object->baseTexture);
712 object->width = Width;
713 object->height = Height;
715 /* Calculate levels for mip mapping */
716 if (Levels == 0) {
717 TRACE("calculating levels %d\n", object->baseTexture.levels);
718 object->baseTexture.levels++;
719 tmpW = Width;
720 tmpH = Height;
721 while (tmpW > 1 && tmpH > 1) {
722 tmpW = max(1, tmpW >> 1);
723 tmpH = max(1, tmpH >> 1);
724 object->baseTexture.levels++;
726 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
729 /* Generate all the surfaces */
730 tmpW = Width;
731 tmpH = Height;
732 for (i = 0; i < object->baseTexture.levels; i++)
734 /* use the callback to create the texture surface */
735 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
736 if(hr!= D3D_OK) {
737 int j;
738 FIXME("Failed to create surface %p \n",object);
739 /* clean up */
740 for(j = 0 ; j < i ; j++) {
741 IWineD3DSurface_Release(object->surfaces[j]);
743 /* heap free object */
744 HeapFree(GetProcessHeap(),0,object);
746 *ppTexture = NULL;
747 return hr;
750 IWineD3DSurface_SetContainer(object->surfaces[i], (IUnknown *)object);
751 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
752 /* calculate the next mipmap level */
753 tmpW = max(1, tmpW >> 1);
754 tmpH = max(1, tmpH >> 1);
757 TRACE("(%p) : Created texture %p\n", This, object);
758 return D3D_OK;
761 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
762 UINT Width, UINT Height, UINT Depth,
763 UINT Levels, DWORD Usage,
764 WINED3DFORMAT Format, D3DPOOL Pool,
765 IWineD3DVolumeTexture** ppVolumeTexture,
766 HANDLE* pSharedHandle, IUnknown *parent,
767 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
769 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
770 IWineD3DVolumeTextureImpl *object;
771 unsigned int i;
772 UINT tmpW;
773 UINT tmpH;
774 UINT tmpD;
776 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, D3DRTYPE_VOLUMETEXTURE, 0);
777 D3DINITILIZEBASETEXTURE(object->baseTexture);
779 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
780 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
782 object->width = Width;
783 object->height = Height;
784 object->depth = Depth;
786 /* Calculate levels for mip mapping */
787 if (Levels == 0) {
788 object->baseTexture.levels++;
789 tmpW = Width;
790 tmpH = Height;
791 tmpD = Depth;
792 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
793 tmpW = max(1, tmpW >> 1);
794 tmpH = max(1, tmpH >> 1);
795 tmpD = max(1, tmpD >> 1);
796 object->baseTexture.levels++;
798 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
801 /* Generate all the surfaces */
802 tmpW = Width;
803 tmpH = Height;
804 tmpD = Depth;
806 for (i = 0; i < object->baseTexture.levels; i++)
808 /* Create the volume */
809 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
810 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
811 IWineD3DVolume_SetContainer(object->volumes[i], (IUnknown *)object);
813 tmpW = max(1, tmpW >> 1);
814 tmpH = max(1, tmpH >> 1);
815 tmpD = max(1, tmpD >> 1);
818 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
819 TRACE("(%p) : Created volume texture %p\n", This, object);
820 return D3D_OK;
823 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
824 UINT Width, UINT Height, UINT Depth,
825 DWORD Usage,
826 WINED3DFORMAT Format, D3DPOOL Pool,
827 IWineD3DVolume** ppVolume,
828 HANDLE* pSharedHandle, IUnknown *parent) {
830 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
831 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
833 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, D3DRTYPE_VOLUME, ((Width * D3DFmtGetBpp(This, Format)) * Height * Depth))
835 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
836 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
838 object->currentDesc.Width = Width;
839 object->currentDesc.Height = Height;
840 object->currentDesc.Depth = Depth;
841 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
843 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
844 object->lockable = TRUE;
845 object->locked = FALSE;
846 memset(&object->lockedBox, 0, sizeof(D3DBOX));
847 object->dirty = FALSE;
848 return IWineD3DVolume_CleanDirtyBox((IWineD3DVolume *) object);
851 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
852 UINT Levels, DWORD Usage,
853 WINED3DFORMAT Format, D3DPOOL Pool,
854 IWineD3DCubeTexture** ppCubeTexture,
855 HANDLE* pSharedHandle, IUnknown *parent,
856 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
858 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
859 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
860 unsigned int i,j;
861 UINT tmpW;
862 HRESULT hr;
864 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, D3DRTYPE_CUBETEXTURE, 0);
865 D3DINITILIZEBASETEXTURE(object->baseTexture);
867 TRACE("(%p) Create Cube Texture \n", This);
869 object->edgeLength = EdgeLength;
871 /* Calculate levels for mip mapping */
872 if (Levels == 0) {
873 object->baseTexture.levels++;
874 tmpW = EdgeLength;
875 while (tmpW > 1) {
876 tmpW = max(1, tmpW / 2);
877 object->baseTexture.levels++;
879 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
882 /* Generate all the surfaces */
883 tmpW = EdgeLength;
884 for (i = 0; i < object->baseTexture.levels; i++) {
886 /* Create the 6 faces */
887 for (j = 0; j < 6; j++) {
889 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
890 i /* Level */, &object->surfaces[j][i],pSharedHandle);
892 if(hr!= D3D_OK) {
893 /* clean up */
894 int k;
895 int l;
896 for (l=0;l<j;l++) {
897 IWineD3DSurface_Release(object->surfaces[j][i]);
899 for (k=0;k<i;k++) {
900 for (l=0;l<6;l++) {
901 IWineD3DSurface_Release(object->surfaces[l][j]);
905 FIXME("(%p) Failed to create surface\n",object);
906 HeapFree(GetProcessHeap(),0,object);
907 *ppCubeTexture = NULL;
908 return hr;
910 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IUnknown *)object);
911 TRACE("Created surface level %d @ %p, \n", i, object->surfaces[j][i]);
913 tmpW = max(1, tmpW >> 1);
916 TRACE("(%p) : Created Cube Texture %p\n", This, object);
917 *ppCubeTexture = (IWineD3DCubeTexture *) object;
918 return D3D_OK;
921 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
922 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
923 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
925 if(NULL == ppQuery) {
926 /* Just a check to see if we support this type of query */
927 HRESULT hr = D3DERR_NOTAVAILABLE;
928 /* Lie and say everything is good (we can return ok fake data from a stub) */
929 switch(Type) {
930 case WINED3DQUERYTYPE_VCACHE:
931 case WINED3DQUERYTYPE_RESOURCEMANAGER:
932 case WINED3DQUERYTYPE_VERTEXSTATS:
933 case WINED3DQUERYTYPE_EVENT:
934 case WINED3DQUERYTYPE_OCCLUSION:
935 case WINED3DQUERYTYPE_TIMESTAMP:
936 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
937 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
938 case WINED3DQUERYTYPE_PIPELINETIMINGS:
939 case WINED3DQUERYTYPE_INTERFACETIMINGS:
940 case WINED3DQUERYTYPE_VERTEXTIMINGS:
941 case WINED3DQUERYTYPE_PIXELTIMINGS:
942 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
943 case WINED3DQUERYTYPE_CACHEUTILIZATION:
944 hr = D3D_OK;
945 break;
946 default:
947 FIXME("(%p) Unhandled query type %d\n",This , Type);
949 FIXME("(%p) : Stub request for query type %d returned %ld\n", This, Type, hr);
950 return hr;
953 D3DCREATEOBJECTINSTANCE(object, Query)
954 object->type = Type;
955 object->extendedData = 0;
956 TRACE("(%p) : Created Query %p\n", This, object);
957 return D3D_OK;
960 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
961 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
962 IUnknown* parent,
963 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
964 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
965 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
967 HDC hDc;
968 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
969 int num;
970 XVisualInfo template;
971 GLXContext oldContext;
972 Drawable oldDrawable;
973 HRESULT hr = D3D_OK;
975 TRACE("(%p) : Created Aditional Swap Chain\n", This);
977 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
978 * does a device hold a reference to a swap chain giving them a lifetime of the device
979 * or does the swap chain notify the device of it'd destruction.
980 *******************************/
982 D3DCREATEOBJECTINSTANCE(object, SwapChain)
984 /* Initialize other useful values */
985 object->presentParms.BackBufferCount = 1; /* TODO:? support for gl_aux buffers */
987 /*********************
988 * Lookup the window Handle and the relating X window handle
989 ********************/
991 /* Setup hwnd we are using, plus which display this equates to */
992 object->win_handle = *(pPresentationParameters->hDeviceWindow);
993 if (!object->win_handle) {
994 object->win_handle = This->createParms.hFocusWindow;
997 object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window" );
998 hDc = GetDC(object->win_handle);
999 object->display = get_display(hDc);
1000 ReleaseDC(object->win_handle, hDc);
1001 TRACE("Using a display of %p %p \n", object->display, hDc);
1003 if (NULL == object->display || NULL == hDc) {
1004 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1005 return D3DERR_NOTAVAILABLE;
1008 if (object->win == 0) {
1009 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1010 return D3DERR_NOTAVAILABLE;
1013 * Create an opengl context for the display visual
1014 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1015 * use different properties after that point in time. FIXME: How to handle when requested format
1016 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1017 * it chooses is identical to the one already being used!
1018 **********************************/
1020 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1021 ENTER_GL();
1023 /* Create a new context for this swapchain */
1024 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1025 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1026 (or the best possible if none is requested) */
1027 TRACE("Found x visual ID : %ld\n", template.visualid);
1029 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1030 if (NULL == object->visInfo) {
1031 ERR("cannot really get XVisual\n");
1032 LEAVE_GL();
1033 return D3DERR_NOTAVAILABLE;
1034 } else {
1035 int n, value;
1036 /* Write out some debug info about the visual/s */
1037 TRACE("Using x visual ID : %ld\n", template.visualid);
1038 TRACE(" visual info: %p\n", object->visInfo);
1039 TRACE(" num items : %d\n", num);
1040 for(n = 0;n < num; n++) {
1041 TRACE("=====item=====: %d\n", n + 1);
1042 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1043 TRACE(" screen : %d\n", object->visInfo[n].screen);
1044 TRACE(" depth : %u\n", object->visInfo[n].depth);
1045 TRACE(" class : %d\n", object->visInfo[n].class);
1046 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1047 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1048 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1049 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1050 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1051 /* log some extra glx info */
1052 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1053 TRACE(" gl_aux_buffers : %d\n", value);
1054 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1055 TRACE(" gl_buffer_size : %d\n", value);
1056 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1057 TRACE(" gl_red_size : %d\n", value);
1058 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1059 TRACE(" gl_green_size : %d\n", value);
1060 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1061 TRACE(" gl_blue_size : %d\n", value);
1062 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1063 TRACE(" gl_alpha_size : %d\n", value);
1064 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1065 TRACE(" gl_depth_size : %d\n", value);
1066 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1067 TRACE(" gl_stencil_size : %d\n", value);
1069 /* Now choose a simila visual ID*/
1071 #ifdef USE_CONTEXT_MANAGER
1073 /** TODO: use a context mamager **/
1074 #endif
1077 IWineD3DSwapChain *implSwapChain;
1078 if (D3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1079 /* The first time around we create the context that is shared with all other swapchains and render targets */
1080 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1081 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1082 } else {
1084 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1085 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1086 /* and create a new context with the implicit swapchains context as the shared context */
1087 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1088 IWineD3DSwapChain_Release(implSwapChain);
1092 /* Cleanup */
1093 XFree(object->visInfo);
1094 object->visInfo = NULL;
1096 if (NULL == object->glCtx) {
1097 ERR("cannot create glxContext\n");
1098 LEAVE_GL();
1099 return D3DERR_NOTAVAILABLE;
1102 LEAVE_GL();
1103 if (object->glCtx == NULL) {
1104 ERR("Error in context creation !\n");
1105 return D3DERR_INVALIDCALL;
1106 } else {
1107 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1108 object->win_handle, object->glCtx, object->win, object->visInfo);
1111 /*********************
1112 * Windowed / Fullscreen
1113 *******************/
1116 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1117 * so we should really check to see if their is a fullscreen swapchain already
1118 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1119 **************************************/
1121 if (!*(pPresentationParameters->Windowed)) {
1123 DEVMODEW devmode;
1124 HDC hdc;
1125 int bpp = 0;
1127 /* Get info on the current display setup */
1128 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1129 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1130 DeleteDC(hdc);
1132 /* Change the display settings */
1133 memset(&devmode, 0, sizeof(DEVMODEW));
1134 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1135 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1136 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1137 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1138 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1139 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1141 /* Make popup window */
1142 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1143 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1144 *(pPresentationParameters->BackBufferWidth),
1145 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1151 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1152 * then the corresponding dimension of the client area of the hDeviceWindow
1153 * (or the focus window, if hDeviceWindow is NULL) is taken.
1154 **********************/
1156 if (*(pPresentationParameters->Windowed) &&
1157 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1158 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1160 RECT Rect;
1161 GetClientRect(object->win_handle, &Rect);
1163 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1164 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1165 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1167 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1168 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1169 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1173 /*********************
1174 * finish off parameter initialization
1175 *******************/
1177 /* Put the correct figures in the presentation parameters */
1178 TRACE("Coppying accross presentaion paraneters\n");
1179 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1180 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1181 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1182 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1183 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1184 object->presentParms.MultiSampleQuality = *(pPresentationParameters->MultiSampleQuality);
1185 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1186 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1187 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1188 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1189 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1190 object->presentParms.Flags = *(pPresentationParameters->Flags);
1191 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1192 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1195 /* FIXME: check for any failures */
1196 /*********************
1197 * Create the back, front and stencil buffers
1198 *******************/
1199 TRACE("calling rendertarget CB\n");
1200 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1201 object->presentParms.BackBufferWidth,
1202 object->presentParms.BackBufferHeight,
1203 object->presentParms.BackBufferFormat,
1204 object->presentParms.MultiSampleType,
1205 object->presentParms.MultiSampleQuality,
1206 TRUE /* Lockable */,
1207 &object->frontBuffer,
1208 NULL /* pShared (always null)*/);
1209 if (object->frontBuffer != NULL)
1210 IWineD3DSurface_SetContainer(object->frontBuffer, (IUnknown *)object);
1211 TRACE("calling rendertarget CB\n");
1212 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1213 object->presentParms.BackBufferWidth,
1214 object->presentParms.BackBufferHeight,
1215 object->presentParms.BackBufferFormat,
1216 object->presentParms.MultiSampleType,
1217 object->presentParms.MultiSampleQuality,
1218 TRUE /* Lockable */,
1219 &object->backBuffer,
1220 NULL /* pShared (always null)*/);
1221 if (object->backBuffer != NULL)
1222 IWineD3DSurface_SetContainer(object->backBuffer, (IUnknown *)object);
1224 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1225 if (pPresentationParameters->EnableAutoDepthStencil) {
1226 TRACE("Creating depth stencil buffer\n");
1227 if (This->depthStencilBuffer == NULL ) {
1228 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1229 object->presentParms.BackBufferWidth,
1230 object->presentParms.BackBufferHeight,
1231 object->presentParms.AutoDepthStencilFormat,
1232 object->presentParms.MultiSampleType,
1233 object->presentParms.MultiSampleQuality,
1234 FALSE /* FIXME: Discard */,
1235 &This->depthStencilBuffer,
1236 NULL /* pShared (always null)*/ );
1237 if (This->depthStencilBuffer != NULL)
1238 IWineD3DSurface_SetContainer(This->depthStencilBuffer, (IUnknown *)iface);
1241 /** TODO: A check on width, height and multisample types
1242 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1243 ****************************/
1244 object->wantsDepthStencilBuffer = TRUE;
1245 } else {
1246 object->wantsDepthStencilBuffer = FALSE;
1249 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1252 /*********************
1253 * init the default renderTarget management
1254 *******************/
1255 object->drawable = object->win;
1256 object->render_ctx = object->glCtx;
1258 if(hr == D3D_OK) {
1259 /*********************
1260 * Setup some defaults and clear down the buffers
1261 *******************/
1262 ENTER_GL();
1263 /** save current context and drawable **/
1264 oldContext = glXGetCurrentContext();
1265 oldDrawable = glXGetCurrentDrawable();
1267 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1268 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1269 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1271 checkGLcall("glXMakeCurrent");
1273 TRACE("Setting up the screen\n");
1274 /* Clear the screen */
1275 glClearColor(0.0, 0.0, 0.0, 0.0);
1276 checkGLcall("glClearColor");
1277 glClearIndex(0);
1278 glClearDepth(1);
1279 glClearStencil(0xffff);
1281 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1282 checkGLcall("glClear");
1284 glColor3f(1.0, 1.0, 1.0);
1285 checkGLcall("glColor3f");
1287 glEnable(GL_LIGHTING);
1288 checkGLcall("glEnable");
1290 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1291 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1293 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1294 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1296 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1297 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1299 /* switch back to the original context (unless it was zero)*/
1300 if (This->numberOfSwapChains != 0) {
1301 /** TODO: restore the context and drawable **/
1302 glXMakeCurrent(object->display, oldDrawable, oldContext);
1305 LEAVE_GL();
1307 /* TODO: move this off into a linked list implementation! (add swapchain, remove swapchain or something along those lines) */
1308 #if 0
1309 IListOperator *listOperator;
1310 IListStore_CreateListOperator(This->swapchainStore, &listOperator);
1311 IListOperator_Append(listOperator, (void *)object);
1312 IListOperator_Release(listOperator);
1313 #endif
1315 This->swapchains[This->numberOfSwapChains++] = (IWineD3DSwapChain *)object;
1316 TRACE("Set swapchain to %p\n", object);
1317 } else { /* something went wrong so clean up */
1318 IUnknown* bufferParent;
1319 if (object->frontBuffer) {
1320 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1321 IUnknown_Release(bufferParent); /* once for the get parent */
1322 if(IUnknown_Release(bufferParent) > 0) {
1323 FIXME("(%p) Something's still holding the front buffer\n",This);
1326 if (object->backBuffer) {
1327 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1328 IUnknown_Release(bufferParent); /* once for the get parent */
1329 if(IUnknown_Release(bufferParent) > 0) {
1330 FIXME("(%p) Something's still holding the back buffer\n",This);
1333 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1334 /* Clean up the context */
1335 /* check that we are the current context first (we shouldn't be though!) */
1336 if (object->glCtx != 0) {
1337 if(glXGetCurrentContext() == object->glCtx) {
1338 glXMakeCurrent(object->display, None, NULL);
1340 glXDestroyContext(object->display, object->glCtx);
1342 HeapFree(GetProcessHeap(), 0, object);
1345 return hr;
1348 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1349 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1350 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1352 /* TODO: move over to using a linked list. */
1353 TRACE("(%p) returning %d\n", This, This->numberOfSwapChains);
1354 return This->numberOfSwapChains;
1357 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1358 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1359 TRACE("(%p) : swapchain %d \n", This, iSwapChain);
1361 if(iSwapChain >= IWineD3DDeviceImpl_GetNumberOfSwapChains(iface) || iSwapChain < 0) {
1362 *pSwapChain = NULL;
1363 return D3DERR_INVALIDCALL;
1364 }else{
1365 /** TODO: move off to a linked list implementation **/
1366 *pSwapChain = This->swapchains[iSwapChain];
1369 /* TODO: move over to using stores and linked lists. */
1371 IWineD3DSwapChain_AddRef(*pSwapChain);
1372 TRACE("(%p) returning %p\n", This, *pSwapChain);
1373 return D3D_OK;
1376 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
1377 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1379 FIXME("(%p) : Stub\n",This);
1380 return D3D_OK;
1384 /*****
1385 * Vertex Declaration
1386 *****/
1387 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1388 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1389 IWineD3DVertexDeclarationImpl *object = NULL;
1390 HRESULT hr = D3D_OK;
1391 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1392 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1393 object->allFVF = 0;
1395 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1397 return hr;
1400 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1401 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DVertexShader** ppVertexShader, IUnknown *parent) {
1402 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1403 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1404 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1405 object->function = pFunction;
1406 FIXME("(%p) : STUB: Created Vertex shader %p\n", This, ppVertexShader);
1407 return D3D_OK;
1411 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DPixelShader** ppPixelShader, IUnknown *parent) {
1412 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1413 FIXME("(%p) : Stub\n", This);
1414 return D3D_OK;
1417 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice* iface, IWineD3D** ppD3D) {
1418 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1419 *ppD3D= This->wineD3D;
1420 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1421 IWineD3D_AddRef(*ppD3D);
1422 return D3D_OK;
1426 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1427 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1428 * Into the video ram as possible and seeing how many fit
1429 * you can also get the correct initial value from via X and ATI's driver
1430 *******************/
1431 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1432 static BOOL showfixmes = TRUE;
1433 if (showfixmes) {
1434 FIXME("(%p) : stub, emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1435 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1436 showfixmes = FALSE;
1438 TRACE("(%p) : emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1439 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1440 /* videomemory is simulated videomemory + AGP memory left */
1441 return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1446 /*****
1447 * Get / Set FVF
1448 *****/
1449 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1450 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1452 /* Update the current state block */
1453 This->updateStateBlock->fvf = fvf;
1454 This->updateStateBlock->changed.fvf = TRUE;
1455 This->updateStateBlock->set.fvf = TRUE;
1457 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1458 /* clear down the vertex declaration
1459 NOTE: Axis and Allies doesn't work properly otherwise
1460 (may be a stateblock problem though!)
1462 /* No difference if recording or not */
1463 return IWineD3DDevice_SetVertexDeclaration(iface, NULL);
1468 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1469 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1470 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1471 *pfvf = This->stateBlock->fvf;
1472 return D3D_OK;
1475 /*****
1476 * Get / Set Stream Source
1477 *****/
1478 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1479 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1480 IWineD3DVertexBuffer *oldSrc;
1482 oldSrc = This->stateBlock->streamSource[StreamNumber];
1483 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1485 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
1486 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
1487 This->updateStateBlock->streamStride[StreamNumber] = Stride;
1488 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
1489 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
1491 /* Handle recording of state blocks */
1492 if (This->isRecordingState) {
1493 TRACE("Recording... not performing anything\n");
1494 return D3D_OK;
1497 /* Not recording... */
1498 if (oldSrc != NULL) IWineD3DVertexBuffer_Release(oldSrc);
1499 if (pStreamData != NULL) IWineD3DVertexBuffer_AddRef(pStreamData);
1501 return D3D_OK;
1504 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
1505 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1507 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
1508 *pStream = This->stateBlock->streamSource[StreamNumber];
1509 *pStride = This->stateBlock->streamStride[StreamNumber];
1510 *pOffset = This->stateBlock->streamOffset[StreamNumber];
1511 if (*pStream != NULL) IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
1512 return D3D_OK;
1515 /*Should be quite easy, just an extension of vertexdata
1516 ref...
1517 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1519 The divider is a bit odd though
1521 VertexOffset = StartVertex / Divider * StreamStride +
1522 VertexIndex / Divider * StreamStride + StreamOffset
1525 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
1526 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1528 FIXME("(%p) : stub\n", This);
1529 return D3D_OK;
1532 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
1533 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1535 FIXME("(%p) : stub\n", This);
1536 return D3D_OK;
1539 /*****
1540 * Get / Set & Multiply Transform
1541 *****/
1542 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1543 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1545 /* Most of this routine, comments included copied from ddraw tree initially: */
1546 TRACE("(%p) : Transform State=%d\n", This, d3dts);
1548 /* Handle recording of state blocks */
1549 if (This->isRecordingState) {
1550 TRACE("Recording... not performing anything\n");
1551 This->updateStateBlock->changed.transform[d3dts] = TRUE;
1552 This->updateStateBlock->set.transform[d3dts] = TRUE;
1553 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1554 return D3D_OK;
1558 * If the new matrix is the same as the current one,
1559 * we cut off any further processing. this seems to be a reasonable
1560 * optimization because as was noticed, some apps (warcraft3 for example)
1561 * tend towards setting the same matrix repeatedly for some reason.
1563 * From here on we assume that the new matrix is different, wherever it matters.
1565 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1566 TRACE("The app is setting the same matrix over again\n");
1567 return D3D_OK;
1568 } else {
1569 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1573 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1574 where ViewMat = Camera space, WorldMat = world space.
1576 In OpenGL, camera and world space is combined into GL_MODELVIEW
1577 matrix. The Projection matrix stay projection matrix.
1580 /* Capture the times we can just ignore the change for now */
1581 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1582 This->modelview_valid = FALSE;
1583 return D3D_OK;
1585 } else if (d3dts == D3DTS_PROJECTION) {
1586 This->proj_valid = FALSE;
1587 return D3D_OK;
1589 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1590 /* Indexed Vertex Blending Matrices 256 -> 511 */
1591 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1592 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1593 return D3D_OK;
1596 /* Now we really are going to have to change a matrix */
1597 ENTER_GL();
1599 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1600 if (d3dts < GL_LIMITS(textures)) {
1601 int tex = d3dts - D3DTS_TEXTURE0;
1602 GLACTIVETEXTURE(tex);
1603 set_texture_matrix((float *)lpmatrix,
1604 This->updateStateBlock->textureState[tex][WINED3DTSS_TEXTURETRANSFORMFLAGS]);
1607 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1608 unsigned int k;
1610 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1611 * NOTE: We have to reset the positions even if the light/plane is not currently
1612 * enabled, since the call to enable it will not reset the position.
1613 * NOTE2: Apparently texture transforms do NOT need reapplying
1616 PLIGHTINFOEL *lightChain = NULL;
1617 This->modelview_valid = FALSE;
1618 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
1620 glMatrixMode(GL_MODELVIEW);
1621 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1622 glPushMatrix();
1623 glLoadMatrixf((float *)lpmatrix);
1624 checkGLcall("glLoadMatrixf(...)");
1626 /* Reset lights */
1627 lightChain = This->stateBlock->lights;
1628 while (lightChain && lightChain->glIndex != -1) {
1629 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1630 checkGLcall("glLightfv posn");
1631 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1632 checkGLcall("glLightfv dirn");
1633 lightChain = lightChain->next;
1636 /* Reset Clipping Planes if clipping is enabled */
1637 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1638 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1639 checkGLcall("glClipPlane");
1641 glPopMatrix();
1643 } else { /* What was requested!?? */
1644 WARN("invalid matrix specified: %i\n", d3dts);
1647 /* Release lock, all done */
1648 LEAVE_GL();
1649 return D3D_OK;
1652 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1653 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1654 TRACE("(%p) : for Transform State %d\n", This, State);
1655 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1656 return D3D_OK;
1659 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1660 D3DMATRIX *mat = NULL;
1661 D3DMATRIX temp;
1663 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1664 * below means it will be recorded in a state block change, but it
1665 * works regardless where it is recorded.
1666 * If this is found to be wrong, change to StateBlock.
1668 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1669 TRACE("(%p) : For state %u\n", This, State);
1671 if (State < HIGHEST_TRANSFORMSTATE)
1673 mat = &This->updateStateBlock->transforms[State];
1674 } else {
1675 FIXME("Unhandled transform state!!\n");
1678 /* Copied from ddraw code: */
1679 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);
1680 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);
1681 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);
1682 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);
1684 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);
1685 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);
1686 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);
1687 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);
1689 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);
1690 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);
1691 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);
1692 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);
1694 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);
1695 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);
1696 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);
1697 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);
1699 /* Apply change via set transform - will reapply to eg. lights this way */
1700 IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
1701 return D3D_OK;
1704 /*****
1705 * Get / Set Light
1706 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
1707 *****/
1708 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1709 you can reference any indexes you want as long as that number max are enabled at any
1710 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1711 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1712 but when recording, just build a chain pretty much of commands to be replayed. */
1714 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
1715 float rho;
1716 PLIGHTINFOEL *object, *temp;
1718 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1719 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1721 /* If recording state block, just add to end of lights chain */
1722 if (This->isRecordingState) {
1723 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1724 if (NULL == object) {
1725 return D3DERR_OUTOFVIDEOMEMORY;
1727 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1728 object->OriginalIndex = Index;
1729 object->glIndex = -1;
1730 object->changed = TRUE;
1732 /* Add to the END of the chain of lights changes to be replayed */
1733 if (This->updateStateBlock->lights == NULL) {
1734 This->updateStateBlock->lights = object;
1735 } else {
1736 temp = This->updateStateBlock->lights;
1737 while (temp->next != NULL) temp=temp->next;
1738 temp->next = object;
1740 TRACE("Recording... not performing anything more\n");
1741 return D3D_OK;
1744 /* Ok, not recording any longer so do real work */
1745 object = This->stateBlock->lights;
1746 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1748 /* If we didn't find it in the list of lights, time to add it */
1749 if (object == NULL) {
1750 PLIGHTINFOEL *insertAt,*prevPos;
1752 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1753 if (NULL == object) {
1754 return D3DERR_OUTOFVIDEOMEMORY;
1756 object->OriginalIndex = Index;
1757 object->glIndex = -1;
1759 /* Add it to the front of list with the idea that lights will be changed as needed
1760 BUT after any lights currently assigned GL indexes */
1761 insertAt = This->stateBlock->lights;
1762 prevPos = NULL;
1763 while (insertAt != NULL && insertAt->glIndex != -1) {
1764 prevPos = insertAt;
1765 insertAt = insertAt->next;
1768 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1769 This->stateBlock->lights = object;
1770 } else if (insertAt == NULL) { /* End of list */
1771 prevPos->next = object;
1772 object->prev = prevPos;
1773 } else { /* Middle of chain */
1774 if (prevPos == NULL) {
1775 This->stateBlock->lights = object;
1776 } else {
1777 prevPos->next = object;
1779 object->prev = prevPos;
1780 object->next = insertAt;
1781 insertAt->prev = object;
1785 /* Initialze the object */
1786 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,
1787 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1788 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1789 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1790 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1791 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1792 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1794 /* Save away the information */
1795 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1797 switch (pLight->Type) {
1798 case D3DLIGHT_POINT:
1799 /* Position */
1800 object->lightPosn[0] = pLight->Position.x;
1801 object->lightPosn[1] = pLight->Position.y;
1802 object->lightPosn[2] = pLight->Position.z;
1803 object->lightPosn[3] = 1.0f;
1804 object->cutoff = 180.0f;
1805 /* FIXME: Range */
1806 break;
1808 case D3DLIGHT_DIRECTIONAL:
1809 /* Direction */
1810 object->lightPosn[0] = -pLight->Direction.x;
1811 object->lightPosn[1] = -pLight->Direction.y;
1812 object->lightPosn[2] = -pLight->Direction.z;
1813 object->lightPosn[3] = 0.0;
1814 object->exponent = 0.0f;
1815 object->cutoff = 180.0f;
1816 break;
1818 case D3DLIGHT_SPOT:
1819 /* Position */
1820 object->lightPosn[0] = pLight->Position.x;
1821 object->lightPosn[1] = pLight->Position.y;
1822 object->lightPosn[2] = pLight->Position.z;
1823 object->lightPosn[3] = 1.0;
1825 /* Direction */
1826 object->lightDirn[0] = pLight->Direction.x;
1827 object->lightDirn[1] = pLight->Direction.y;
1828 object->lightDirn[2] = pLight->Direction.z;
1829 object->lightDirn[3] = 1.0;
1832 * opengl-ish and d3d-ish spot lights use too different models for the
1833 * light "intensity" as a function of the angle towards the main light direction,
1834 * so we only can approximate very roughly.
1835 * however spot lights are rather rarely used in games (if ever used at all).
1836 * furthermore if still used, probably nobody pays attention to such details.
1838 if (pLight->Falloff == 0) {
1839 rho = 6.28f;
1840 } else {
1841 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1843 if (rho < 0.0001) rho = 0.0001f;
1844 object->exponent = -0.3/log(cos(rho/2));
1845 object->cutoff = pLight->Phi*90/M_PI;
1847 /* FIXME: Range */
1848 break;
1850 default:
1851 FIXME("Unrecognized light type %d\n", pLight->Type);
1854 /* Update the live definitions if the light is currently assigned a glIndex */
1855 if (object->glIndex != -1) {
1856 setup_light(iface, object->glIndex, object);
1858 return D3D_OK;
1861 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
1862 PLIGHTINFOEL *lightInfo = NULL;
1863 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1864 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1866 /* Locate the light in the live lights */
1867 lightInfo = This->stateBlock->lights;
1868 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1870 if (lightInfo == NULL) {
1871 TRACE("Light information requested but light not defined\n");
1872 return D3DERR_INVALIDCALL;
1875 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
1876 return D3D_OK;
1879 /*****
1880 * Get / Set Light Enable
1881 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
1882 *****/
1883 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
1884 PLIGHTINFOEL *lightInfo = NULL;
1885 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1886 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1888 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1889 if (This->isRecordingState) {
1890 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1891 if (NULL == lightInfo) {
1892 return D3DERR_OUTOFVIDEOMEMORY;
1894 lightInfo->OriginalIndex = Index;
1895 lightInfo->glIndex = -1;
1896 lightInfo->enabledChanged = TRUE;
1898 /* Add to the END of the chain of lights changes to be replayed */
1899 if (This->updateStateBlock->lights == NULL) {
1900 This->updateStateBlock->lights = lightInfo;
1901 } else {
1902 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
1903 while (temp->next != NULL) temp=temp->next;
1904 temp->next = lightInfo;
1906 TRACE("Recording... not performing anything more\n");
1907 return D3D_OK;
1910 /* Not recording... So, locate the light in the live lights */
1911 lightInfo = This->stateBlock->lights;
1912 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1914 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1915 if (lightInfo == NULL) {
1916 D3DLIGHT9 lightParms;
1917 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1918 wait until someone confirms it seems to work! */
1919 TRACE("Light enabled requested but light not defined, so defining one!\n");
1920 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1921 lightParms.Diffuse.r = 1.0;
1922 lightParms.Diffuse.g = 1.0;
1923 lightParms.Diffuse.b = 1.0;
1924 lightParms.Diffuse.a = 0.0;
1925 lightParms.Specular.r = 0.0;
1926 lightParms.Specular.g = 0.0;
1927 lightParms.Specular.b = 0.0;
1928 lightParms.Specular.a = 0.0;
1929 lightParms.Ambient.r = 0.0;
1930 lightParms.Ambient.g = 0.0;
1931 lightParms.Ambient.b = 0.0;
1932 lightParms.Ambient.a = 0.0;
1933 lightParms.Position.x = 0.0;
1934 lightParms.Position.y = 0.0;
1935 lightParms.Position.z = 0.0;
1936 lightParms.Direction.x = 0.0;
1937 lightParms.Direction.y = 0.0;
1938 lightParms.Direction.z = 1.0;
1939 lightParms.Range = 0.0;
1940 lightParms.Falloff = 0.0;
1941 lightParms.Attenuation0 = 0.0;
1942 lightParms.Attenuation1 = 0.0;
1943 lightParms.Attenuation2 = 0.0;
1944 lightParms.Theta = 0.0;
1945 lightParms.Phi = 0.0;
1946 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
1948 /* Search for it again! Should be fairly quick as near head of list */
1949 lightInfo = This->stateBlock->lights;
1950 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1951 if (lightInfo == NULL) {
1952 FIXME("Adding default lights has failed dismally\n");
1953 return D3DERR_INVALIDCALL;
1957 /* OK, we now have a light... */
1958 if (Enable == FALSE) {
1960 /* If we are disabling it, check it was enabled, and
1961 still only do something if it has assigned a glIndex (which it should have!) */
1962 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
1963 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1964 ENTER_GL();
1965 glDisable(GL_LIGHT0 + lightInfo->glIndex);
1966 checkGLcall("glDisable GL_LIGHT0+Index");
1967 LEAVE_GL();
1968 } else {
1969 TRACE("Nothing to do as light was not enabled\n");
1971 lightInfo->lightEnabled = FALSE;
1972 } else {
1974 /* We are enabling it. If it is enabled, it's really simple */
1975 if (lightInfo->lightEnabled) {
1976 /* nop */
1977 TRACE("Nothing to do as light was enabled\n");
1979 /* If it already has a glIndex, it's still simple */
1980 } else if (lightInfo->glIndex != -1) {
1981 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
1982 lightInfo->lightEnabled = TRUE;
1983 ENTER_GL();
1984 glEnable(GL_LIGHT0 + lightInfo->glIndex);
1985 checkGLcall("glEnable GL_LIGHT0+Index already setup");
1986 LEAVE_GL();
1988 /* Otherwise got to find space - lights are ordered gl indexes first */
1989 } else {
1990 PLIGHTINFOEL *bsf = NULL;
1991 PLIGHTINFOEL *pos = This->stateBlock->lights;
1992 PLIGHTINFOEL *prev = NULL;
1993 int Index= 0;
1994 int glIndex = -1;
1996 /* Try to minimize changes as much as possible */
1997 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
1999 /* Try to remember which index can be replaced if necessary */
2000 if (bsf==NULL && pos->lightEnabled == FALSE) {
2001 /* Found a light we can replace, save as best replacement */
2002 bsf = pos;
2005 /* Step to next space */
2006 prev = pos;
2007 pos = pos->next;
2008 Index ++;
2011 /* If we have too many active lights, fail the call */
2012 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2013 FIXME("Program requests too many concurrent lights\n");
2014 return D3DERR_INVALIDCALL;
2016 /* If we have allocated all lights, but not all are enabled,
2017 reuse one which is not enabled */
2018 } else if (Index == This->maxConcurrentLights) {
2019 /* use bsf - Simply swap the new light and the BSF one */
2020 PLIGHTINFOEL *bsfNext = bsf->next;
2021 PLIGHTINFOEL *bsfPrev = bsf->prev;
2023 /* Sort out ends */
2024 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2025 if (bsf->prev != NULL) {
2026 bsf->prev->next = lightInfo;
2027 } else {
2028 This->stateBlock->lights = lightInfo;
2031 /* If not side by side, lots of chains to update */
2032 if (bsf->next != lightInfo) {
2033 lightInfo->prev->next = bsf;
2034 bsf->next->prev = lightInfo;
2035 bsf->next = lightInfo->next;
2036 bsf->prev = lightInfo->prev;
2037 lightInfo->next = bsfNext;
2038 lightInfo->prev = bsfPrev;
2040 } else {
2041 /* Simple swaps */
2042 bsf->prev = lightInfo;
2043 bsf->next = lightInfo->next;
2044 lightInfo->next = bsf;
2045 lightInfo->prev = bsfPrev;
2049 /* Update states */
2050 glIndex = bsf->glIndex;
2051 bsf->glIndex = -1;
2052 lightInfo->glIndex = glIndex;
2053 lightInfo->lightEnabled = TRUE;
2055 /* Finally set up the light in gl itself */
2056 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2057 ENTER_GL();
2058 setup_light(iface, glIndex, lightInfo);
2059 glEnable(GL_LIGHT0 + glIndex);
2060 checkGLcall("glEnable GL_LIGHT0 new setup");
2061 LEAVE_GL();
2063 /* If we reached the end of the allocated lights, with space in the
2064 gl lights, setup a new light */
2065 } else if (pos->glIndex == -1) {
2067 /* We reached the end of the allocated gl lights, so already
2068 know the index of the next one! */
2069 glIndex = Index;
2070 lightInfo->glIndex = glIndex;
2071 lightInfo->lightEnabled = TRUE;
2073 /* In an ideal world, it's already in the right place */
2074 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2075 /* No need to move it */
2076 } else {
2077 /* Remove this light from the list */
2078 lightInfo->prev->next = lightInfo->next;
2079 if (lightInfo->next != NULL) {
2080 lightInfo->next->prev = lightInfo->prev;
2083 /* Add in at appropriate place (inbetween prev and pos) */
2084 lightInfo->prev = prev;
2085 lightInfo->next = pos;
2086 if (prev == NULL) {
2087 This->stateBlock->lights = lightInfo;
2088 } else {
2089 prev->next = lightInfo;
2091 if (pos != NULL) {
2092 pos->prev = lightInfo;
2096 /* Finally set up the light in gl itself */
2097 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2098 ENTER_GL();
2099 setup_light(iface, glIndex, lightInfo);
2100 glEnable(GL_LIGHT0 + glIndex);
2101 checkGLcall("glEnable GL_LIGHT0 new setup");
2102 LEAVE_GL();
2107 return D3D_OK;
2110 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2112 PLIGHTINFOEL *lightInfo = NULL;
2113 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2114 TRACE("(%p) : for idx(%ld)\n", This, Index);
2116 /* Locate the light in the live lights */
2117 lightInfo = This->stateBlock->lights;
2118 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2120 if (lightInfo == NULL) {
2121 TRACE("Light enabled state requested but light not defined\n");
2122 return D3DERR_INVALIDCALL;
2124 *pEnable = lightInfo->lightEnabled;
2125 return D3D_OK;
2128 /*****
2129 * Get / Set Clip Planes
2130 *****/
2131 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2132 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2133 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2135 /* Validate Index */
2136 if (Index >= GL_LIMITS(clipplanes)) {
2137 TRACE("Application has requested clipplane this device doesn't support\n");
2138 return D3DERR_INVALIDCALL;
2141 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2142 This->updateStateBlock->set.clipplane[Index] = TRUE;
2143 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2144 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2145 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2146 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2148 /* Handle recording of state blocks */
2149 if (This->isRecordingState) {
2150 TRACE("Recording... not performing anything\n");
2151 return D3D_OK;
2154 /* Apply it */
2156 ENTER_GL();
2158 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2159 glMatrixMode(GL_MODELVIEW);
2160 glPushMatrix();
2161 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2163 TRACE("Clipplane [%f,%f,%f,%f]\n",
2164 This->updateStateBlock->clipplane[Index][0],
2165 This->updateStateBlock->clipplane[Index][1],
2166 This->updateStateBlock->clipplane[Index][2],
2167 This->updateStateBlock->clipplane[Index][3]);
2168 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2169 checkGLcall("glClipPlane");
2171 glPopMatrix();
2172 LEAVE_GL();
2174 return D3D_OK;
2177 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2178 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2179 TRACE("(%p) : for idx %ld\n", This, Index);
2181 /* Validate Index */
2182 if (Index >= GL_LIMITS(clipplanes)) {
2183 TRACE("Application has requested clipplane this device doesn't support\n");
2184 return D3DERR_INVALIDCALL;
2187 pPlane[0] = This->stateBlock->clipplane[Index][0];
2188 pPlane[1] = This->stateBlock->clipplane[Index][1];
2189 pPlane[2] = This->stateBlock->clipplane[Index][2];
2190 pPlane[3] = This->stateBlock->clipplane[Index][3];
2191 return D3D_OK;
2194 /*****
2195 * Get / Set Clip Plane Status
2196 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2197 *****/
2198 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2199 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2200 FIXME("(%p) : stub\n", This);
2201 if (NULL == pClipStatus) {
2202 return D3DERR_INVALIDCALL;
2204 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2205 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2206 return D3D_OK;
2209 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2210 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2211 FIXME("(%p) : stub\n", This);
2212 if (NULL == pClipStatus) {
2213 return D3DERR_INVALIDCALL;
2215 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2216 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2217 return D3D_OK;
2220 /*****
2221 * Get / Set Material
2222 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2223 *****/
2224 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2225 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2227 This->updateStateBlock->changed.material = TRUE;
2228 This->updateStateBlock->set.material = TRUE;
2229 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2231 /* Handle recording of state blocks */
2232 if (This->isRecordingState) {
2233 TRACE("Recording... not performing anything\n");
2234 return D3D_OK;
2237 ENTER_GL();
2238 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2239 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2240 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2241 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2242 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2244 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2245 checkGLcall("glMaterialfv");
2246 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2247 checkGLcall("glMaterialfv");
2249 /* Only change material color if specular is enabled, otherwise it is set to black */
2250 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2251 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2252 checkGLcall("glMaterialfv");
2253 } else {
2254 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2255 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2256 checkGLcall("glMaterialfv");
2258 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2259 checkGLcall("glMaterialfv");
2260 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2261 checkGLcall("glMaterialf");
2263 LEAVE_GL();
2264 return D3D_OK;
2267 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2268 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2269 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2270 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2271 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2272 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2273 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2274 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2275 return D3D_OK;
2278 /*****
2279 * Get / Set Indices
2280 *****/
2281 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2282 UINT BaseVertexIndex) {
2283 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2284 IWineD3DIndexBuffer *oldIdxs;
2286 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2287 oldIdxs = This->updateStateBlock->pIndexData;
2289 This->updateStateBlock->changed.indices = TRUE;
2290 This->updateStateBlock->set.indices = TRUE;
2291 This->updateStateBlock->pIndexData = pIndexData;
2292 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2294 /* Handle recording of state blocks */
2295 if (This->isRecordingState) {
2296 TRACE("Recording... not performing anything\n");
2297 return D3D_OK;
2300 if (oldIdxs) IWineD3DIndexBuffer_Release(oldIdxs);
2301 if (pIndexData) IWineD3DIndexBuffer_AddRef(This->stateBlock->pIndexData);
2302 return D3D_OK;
2305 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2306 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2308 *ppIndexData = This->stateBlock->pIndexData;
2310 /* up ref count on ppindexdata */
2311 if (*ppIndexData) IWineD3DIndexBuffer_AddRef(*ppIndexData);
2312 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2314 return D3D_OK;
2317 /*****
2318 * Get / Set Viewports
2319 *****/
2320 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2321 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2323 TRACE("(%p)\n", This);
2324 This->updateStateBlock->changed.viewport = TRUE;
2325 This->updateStateBlock->set.viewport = TRUE;
2326 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2328 /* Handle recording of state blocks */
2329 if (This->isRecordingState) {
2330 TRACE("Recording... not performing anything\n");
2331 return D3D_OK;
2334 ENTER_GL();
2336 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2337 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2339 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2340 checkGLcall("glDepthRange");
2341 /* Note: GL requires lower left, DirectX supplies upper left */
2342 /* TODO: replace usage of renderTarget with context management */
2343 glViewport(pViewport->X,
2344 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2345 pViewport->Width, pViewport->Height);
2347 checkGLcall("glViewport");
2349 LEAVE_GL();
2351 return D3D_OK;
2355 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2356 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2357 TRACE("(%p)\n", This);
2358 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2359 return D3D_OK;
2362 /*****
2363 * Get / Set Render States
2364 * TODO: Verify against dx9 definitions
2365 *****/
2366 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2368 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2369 DWORD OldValue = This->stateBlock->renderState[State];
2371 /* Simple way of referring to either a DWORD or a 4 byte float */
2372 union {
2373 DWORD d;
2374 float f;
2375 } tmpvalue;
2377 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2378 This->updateStateBlock->changed.renderState[State] = TRUE;
2379 This->updateStateBlock->set.renderState[State] = TRUE;
2380 This->updateStateBlock->renderState[State] = Value;
2382 /* Handle recording of state blocks */
2383 if (This->isRecordingState) {
2384 TRACE("Recording... not performing anything\n");
2385 return D3D_OK;
2388 ENTER_GL();
2390 switch (State) {
2391 case WINED3DRS_FILLMODE :
2392 switch ((D3DFILLMODE) Value) {
2393 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2394 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2395 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2396 default:
2397 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
2399 checkGLcall("glPolygonMode (fillmode)");
2400 break;
2402 case WINED3DRS_LIGHTING :
2403 if (Value) {
2404 glEnable(GL_LIGHTING);
2405 checkGLcall("glEnable GL_LIGHTING");
2406 } else {
2407 glDisable(GL_LIGHTING);
2408 checkGLcall("glDisable GL_LIGHTING");
2410 break;
2412 case WINED3DRS_ZENABLE :
2413 switch ((D3DZBUFFERTYPE) Value) {
2414 case D3DZB_FALSE:
2415 glDisable(GL_DEPTH_TEST);
2416 checkGLcall("glDisable GL_DEPTH_TEST");
2417 break;
2418 case D3DZB_TRUE:
2419 glEnable(GL_DEPTH_TEST);
2420 checkGLcall("glEnable GL_DEPTH_TEST");
2421 break;
2422 case D3DZB_USEW:
2423 glEnable(GL_DEPTH_TEST);
2424 checkGLcall("glEnable GL_DEPTH_TEST");
2425 FIXME("W buffer is not well handled\n");
2426 break;
2427 default:
2428 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2430 break;
2432 case WINED3DRS_CULLMODE :
2434 /* If we are culling "back faces with clockwise vertices" then
2435 set front faces to be counter clockwise and enable culling
2436 of back faces */
2437 switch ((D3DCULL) Value) {
2438 case D3DCULL_NONE:
2439 glDisable(GL_CULL_FACE);
2440 checkGLcall("glDisable GL_CULL_FACE");
2441 break;
2442 case D3DCULL_CW:
2443 glEnable(GL_CULL_FACE);
2444 checkGLcall("glEnable GL_CULL_FACE");
2445 if (This->renderUpsideDown) {
2446 glFrontFace(GL_CW);
2447 checkGLcall("glFrontFace GL_CW");
2448 } else {
2449 glFrontFace(GL_CCW);
2450 checkGLcall("glFrontFace GL_CCW");
2452 glCullFace(GL_BACK);
2453 break;
2454 case D3DCULL_CCW:
2455 glEnable(GL_CULL_FACE);
2456 checkGLcall("glEnable GL_CULL_FACE");
2457 if (This->renderUpsideDown) {
2458 glFrontFace(GL_CCW);
2459 checkGLcall("glFrontFace GL_CCW");
2460 } else {
2461 glFrontFace(GL_CW);
2462 checkGLcall("glFrontFace GL_CW");
2464 glCullFace(GL_BACK);
2465 break;
2466 default:
2467 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2469 break;
2471 case WINED3DRS_SHADEMODE :
2472 switch ((D3DSHADEMODE) Value) {
2473 case D3DSHADE_FLAT:
2474 glShadeModel(GL_FLAT);
2475 checkGLcall("glShadeModel");
2476 break;
2477 case D3DSHADE_GOURAUD:
2478 glShadeModel(GL_SMOOTH);
2479 checkGLcall("glShadeModel");
2480 break;
2481 case D3DSHADE_PHONG:
2482 FIXME("D3DSHADE_PHONG isn't supported?\n");
2484 LEAVE_GL();
2485 return D3DERR_INVALIDCALL;
2486 default:
2487 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2489 break;
2491 case WINED3DRS_DITHERENABLE :
2492 if (Value) {
2493 glEnable(GL_DITHER);
2494 checkGLcall("glEnable GL_DITHER");
2495 } else {
2496 glDisable(GL_DITHER);
2497 checkGLcall("glDisable GL_DITHER");
2499 break;
2501 case WINED3DRS_ZWRITEENABLE :
2502 if (Value) {
2503 glDepthMask(1);
2504 checkGLcall("glDepthMask");
2505 } else {
2506 glDepthMask(0);
2507 checkGLcall("glDepthMask");
2509 break;
2511 case WINED3DRS_ZFUNC :
2513 int glParm = GL_LESS;
2515 switch ((D3DCMPFUNC) Value) {
2516 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2517 case D3DCMP_LESS: glParm=GL_LESS; break;
2518 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2519 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2520 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2521 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2522 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2523 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2524 default:
2525 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2527 glDepthFunc(glParm);
2528 checkGLcall("glDepthFunc");
2530 break;
2532 case WINED3DRS_AMBIENT :
2534 float col[4];
2535 D3DCOLORTOGLFLOAT4(Value, col);
2536 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2537 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2538 checkGLcall("glLightModel for MODEL_AMBIENT");
2541 break;
2543 case WINED3DRS_ALPHABLENDENABLE :
2544 if (Value) {
2545 glEnable(GL_BLEND);
2546 checkGLcall("glEnable GL_BLEND");
2547 } else {
2548 glDisable(GL_BLEND);
2549 checkGLcall("glDisable GL_BLEND");
2551 break;
2553 case WINED3DRS_SRCBLEND :
2554 case WINED3DRS_DESTBLEND :
2556 int newVal = GL_ZERO;
2557 switch (Value) {
2558 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2559 case D3DBLEND_ONE : newVal = GL_ONE; break;
2560 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2561 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2562 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2563 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2564 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2565 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2566 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2567 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2568 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2570 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2571 This->srcBlend = newVal;
2572 This->dstBlend = newVal;
2573 break;
2575 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2576 This->srcBlend = newVal;
2577 This->dstBlend = newVal;
2578 break;
2579 default:
2580 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2583 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2584 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2585 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2586 glBlendFunc(This->srcBlend, This->dstBlend);
2588 checkGLcall("glBlendFunc");
2590 break;
2592 case WINED3DRS_ALPHATESTENABLE :
2593 if (Value) {
2594 glEnable(GL_ALPHA_TEST);
2595 checkGLcall("glEnable GL_ALPHA_TEST");
2596 } else {
2597 glDisable(GL_ALPHA_TEST);
2598 checkGLcall("glDisable GL_ALPHA_TEST");
2600 break;
2602 case WINED3DRS_ALPHAFUNC :
2604 int glParm = GL_LESS;
2605 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2607 switch ((D3DCMPFUNC) Value) {
2608 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2609 case D3DCMP_LESS: glParm = GL_LESS; break;
2610 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2611 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2612 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2613 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2614 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2615 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2616 default:
2617 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2619 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2620 glAlphaFunc(glParm, ref);
2621 This->alphafunc = glParm;
2622 checkGLcall("glAlphaFunc");
2624 break;
2626 case WINED3DRS_ALPHAREF :
2628 int glParm = This->alphafunc;
2629 float ref = 1.0f;
2631 ref = ((float) Value) / 255.0f;
2632 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2633 glAlphaFunc(glParm, ref);
2634 checkGLcall("glAlphaFunc");
2636 break;
2638 case WINED3DRS_CLIPPLANEENABLE :
2639 case WINED3DRS_CLIPPING :
2641 /* Ensure we only do the changed clip planes */
2642 DWORD enable = 0xFFFFFFFF;
2643 DWORD disable = 0x00000000;
2645 /* If enabling / disabling all */
2646 if (State == WINED3DRS_CLIPPING) {
2647 if (Value) {
2648 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2649 disable = 0x00;
2650 } else {
2651 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2652 enable = 0x00;
2654 } else {
2655 enable = Value & ~OldValue;
2656 disable = ~Value & OldValue;
2659 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2660 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2661 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2662 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2663 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2664 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2666 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2667 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2668 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2669 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2670 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2671 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2673 /** update clipping status */
2674 if (enable) {
2675 This->stateBlock->clip_status.ClipUnion = 0;
2676 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
2677 } else {
2678 This->stateBlock->clip_status.ClipUnion = 0;
2679 This->stateBlock->clip_status.ClipIntersection = 0;
2682 break;
2684 case WINED3DRS_BLENDOP :
2686 int glParm = GL_FUNC_ADD;
2688 switch ((D3DBLENDOP) Value) {
2689 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2690 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2691 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2692 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2693 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2694 default:
2695 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2697 TRACE("glBlendEquation(%x)\n", glParm);
2698 glBlendEquation(glParm);
2699 checkGLcall("glBlendEquation");
2701 break;
2703 case WINED3DRS_TEXTUREFACTOR :
2705 unsigned int i;
2707 /* Note the texture color applies to all textures whereas
2708 GL_TEXTURE_ENV_COLOR applies to active only */
2709 float col[4];
2710 D3DCOLORTOGLFLOAT4(Value, col);
2711 /* Set the default alpha blend color */
2712 glBlendColor(col[0], col[1], col[2], col[3]);
2713 checkGLcall("glBlendColor");
2715 /* And now the default texture color as well */
2716 for (i = 0; i < GL_LIMITS(textures); i++) {
2718 /* Note the D3DRS value applies to all textures, but GL has one
2719 per texture, so apply it now ready to be used! */
2720 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2721 GLACTIVETEXTURE(i);
2722 } else if (i>0) {
2723 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2726 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2727 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2730 break;
2732 case WINED3DRS_SPECULARENABLE :
2734 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2735 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2736 specular color. This is wrong:
2737 Separate specular color means the specular colour is maintained separately, whereas
2738 single color means it is merged in. However in both cases they are being used to
2739 some extent.
2740 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2741 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2742 running 1.4 yet!
2744 if (Value) {
2745 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2746 checkGLcall("glMaterialfv");
2747 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2748 glEnable(GL_COLOR_SUM_EXT);
2749 } else {
2750 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2752 checkGLcall("glEnable(GL_COLOR_SUM)");
2753 } else {
2754 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2756 /* for the case of enabled lighting: */
2757 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2758 checkGLcall("glMaterialfv");
2760 /* for the case of disabled lighting: */
2761 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2762 glDisable(GL_COLOR_SUM_EXT);
2763 } else {
2764 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2766 checkGLcall("glDisable(GL_COLOR_SUM)");
2769 break;
2771 case WINED3DRS_STENCILENABLE :
2772 if (Value) {
2773 glEnable(GL_STENCIL_TEST);
2774 checkGLcall("glEnable GL_STENCIL_TEST");
2775 } else {
2776 glDisable(GL_STENCIL_TEST);
2777 checkGLcall("glDisable GL_STENCIL_TEST");
2779 break;
2781 case WINED3DRS_STENCILFUNC :
2783 int glParm = GL_ALWAYS;
2784 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2785 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2787 switch ((D3DCMPFUNC) Value) {
2788 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2789 case D3DCMP_LESS: glParm=GL_LESS; break;
2790 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2791 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2792 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2793 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2794 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2795 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2796 default:
2797 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2799 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2800 This->stencilfunc = glParm;
2801 glStencilFunc(glParm, ref, mask);
2802 checkGLcall("glStencilFunc");
2804 break;
2806 case WINED3DRS_STENCILREF :
2808 int glParm = This->stencilfunc;
2809 int ref = 0;
2810 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2812 ref = Value;
2813 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2814 glStencilFunc(glParm, ref, mask);
2815 checkGLcall("glStencilFunc");
2817 break;
2819 case WINED3DRS_STENCILMASK :
2821 int glParm = This->stencilfunc;
2822 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2823 GLuint mask = Value;
2825 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2826 glStencilFunc(glParm, ref, mask);
2827 checkGLcall("glStencilFunc");
2829 break;
2831 case WINED3DRS_STENCILFAIL :
2833 GLenum fail ;
2834 GLenum zpass ;
2835 GLenum zfail ;
2837 fail = StencilOp(Value);
2838 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2839 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2840 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2841 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2843 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2844 glStencilOp(fail, zfail, zpass);
2845 checkGLcall("glStencilOp(fail, zfail, zpass);");
2847 break;
2848 case WINED3DRS_STENCILZFAIL :
2850 GLenum fail ;
2851 GLenum zpass ;
2852 GLenum zfail ;
2854 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2855 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2856 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2857 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2858 zfail = StencilOp(Value);
2860 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2861 glStencilOp(fail, zfail, zpass);
2862 checkGLcall("glStencilOp(fail, zfail, zpass);");
2864 break;
2865 case WINED3DRS_STENCILPASS :
2867 GLenum fail ;
2868 GLenum zpass ;
2869 GLenum zfail ;
2871 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2872 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2873 zpass = StencilOp(Value);
2874 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2875 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2877 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2878 glStencilOp(fail, zfail, zpass);
2879 checkGLcall("glStencilOp(fail, zfail, zpass);");
2881 break;
2883 case WINED3DRS_STENCILWRITEMASK :
2885 glStencilMask(Value);
2886 TRACE("glStencilMask(%lu)\n", Value);
2887 checkGLcall("glStencilMask");
2889 break;
2891 case WINED3DRS_FOGENABLE :
2893 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2894 glEnable(GL_FOG);
2895 checkGLcall("glEnable GL_FOG");
2896 } else {
2897 glDisable(GL_FOG);
2898 checkGLcall("glDisable GL_FOG");
2901 break;
2903 case WINED3DRS_RANGEFOGENABLE :
2905 if (Value) {
2906 TRACE("Enabled RANGEFOG");
2907 } else {
2908 TRACE("Disabled RANGEFOG");
2911 break;
2913 case WINED3DRS_FOGCOLOR :
2915 float col[4];
2916 D3DCOLORTOGLFLOAT4(Value, col);
2917 /* Set the default alpha blend color */
2918 glFogfv(GL_FOG_COLOR, &col[0]);
2919 checkGLcall("glFog GL_FOG_COLOR");
2921 break;
2923 case WINED3DRS_FOGTABLEMODE :
2925 glHint(GL_FOG_HINT, GL_NICEST);
2926 switch (Value) {
2927 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2928 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2929 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2930 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2931 default:
2932 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
2934 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2935 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
2938 break;
2940 case WINED3DRS_FOGVERTEXMODE :
2942 glHint(GL_FOG_HINT, GL_FASTEST);
2943 switch (Value) {
2944 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2945 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2946 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2947 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2948 default:
2949 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
2951 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2952 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
2955 break;
2957 case WINED3DRS_FOGSTART :
2959 tmpvalue.d = Value;
2960 glFogfv(GL_FOG_START, &tmpvalue.f);
2961 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2962 TRACE("Fog Start == %f\n", tmpvalue.f);
2964 break;
2966 case WINED3DRS_FOGEND :
2968 tmpvalue.d = Value;
2969 glFogfv(GL_FOG_END, &tmpvalue.f);
2970 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2971 TRACE("Fog End == %f\n", tmpvalue.f);
2973 break;
2975 case WINED3DRS_FOGDENSITY :
2977 tmpvalue.d = Value;
2978 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
2979 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2981 break;
2983 case WINED3DRS_VERTEXBLEND :
2985 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2986 TRACE("Vertex Blending state to %ld\n", Value);
2988 break;
2990 case WINED3DRS_TWEENFACTOR :
2992 tmpvalue.d = Value;
2993 This->updateStateBlock->tween_factor = tmpvalue.f;
2994 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
2996 break;
2998 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
3000 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3002 break;
3004 case WINED3DRS_COLORVERTEX :
3005 case WINED3DRS_DIFFUSEMATERIALSOURCE :
3006 case WINED3DRS_SPECULARMATERIALSOURCE :
3007 case WINED3DRS_AMBIENTMATERIALSOURCE :
3008 case WINED3DRS_EMISSIVEMATERIALSOURCE :
3010 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3012 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3013 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3014 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3015 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3016 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3017 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3019 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3020 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3021 Parm = GL_AMBIENT_AND_DIFFUSE;
3022 } else {
3023 Parm = GL_DIFFUSE;
3025 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3026 Parm = GL_AMBIENT;
3027 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3028 Parm = GL_EMISSION;
3029 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3030 Parm = GL_SPECULAR;
3031 } else {
3032 Parm = -1;
3035 if (Parm == -1) {
3036 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3037 } else {
3038 This->tracking_color = NEEDS_TRACKING;
3039 This->tracking_parm = Parm;
3042 } else {
3043 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3046 break;
3048 case WINED3DRS_LINEPATTERN :
3050 union {
3051 DWORD d;
3052 D3DLINEPATTERN lp;
3053 } tmppattern;
3054 tmppattern.d = Value;
3056 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3058 if (tmppattern.lp.wRepeatFactor) {
3059 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3060 checkGLcall("glLineStipple(repeat, linepattern)");
3061 glEnable(GL_LINE_STIPPLE);
3062 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3063 } else {
3064 glDisable(GL_LINE_STIPPLE);
3065 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3068 break;
3070 case WINED3DRS_ZBIAS :
3072 if (Value) {
3073 tmpvalue.d = Value;
3074 TRACE("ZBias value %f\n", tmpvalue.f);
3075 glPolygonOffset(0, -tmpvalue.f);
3076 checkGLcall("glPolygonOffset(0, -Value)");
3077 glEnable(GL_POLYGON_OFFSET_FILL);
3078 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3079 glEnable(GL_POLYGON_OFFSET_LINE);
3080 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3081 glEnable(GL_POLYGON_OFFSET_POINT);
3082 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3083 } else {
3084 glDisable(GL_POLYGON_OFFSET_FILL);
3085 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3086 glDisable(GL_POLYGON_OFFSET_LINE);
3087 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3088 glDisable(GL_POLYGON_OFFSET_POINT);
3089 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3092 break;
3094 case WINED3DRS_NORMALIZENORMALS :
3095 if (Value) {
3096 glEnable(GL_NORMALIZE);
3097 checkGLcall("glEnable(GL_NORMALIZE);");
3098 } else {
3099 glDisable(GL_NORMALIZE);
3100 checkGLcall("glDisable(GL_NORMALIZE);");
3102 break;
3104 case WINED3DRS_POINTSIZE :
3105 tmpvalue.d = Value;
3106 TRACE("Set point size to %f\n", tmpvalue.f);
3107 glPointSize(tmpvalue.f);
3108 checkGLcall("glPointSize(...);");
3109 break;
3111 case WINED3DRS_POINTSIZE_MIN :
3112 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3113 tmpvalue.d = Value;
3114 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3115 checkGLcall("glPointParameterfEXT(...);");
3116 } else {
3117 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3119 break;
3121 case WINED3DRS_POINTSIZE_MAX :
3122 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3123 tmpvalue.d = Value;
3124 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3125 checkGLcall("glPointParameterfEXT(...);");
3126 } else {
3127 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3129 break;
3131 case WINED3DRS_POINTSCALE_A :
3132 case WINED3DRS_POINTSCALE_B :
3133 case WINED3DRS_POINTSCALE_C :
3134 case WINED3DRS_POINTSCALEENABLE :
3136 /* If enabled, supply the parameters, otherwise fall back to defaults */
3137 if (This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3138 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3139 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]);
3140 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]);
3141 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]);
3143 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3144 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3145 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3146 } else {
3147 TRACE("WINED3DRS_POINTSCALEENABLE not supported on this opengl\n");
3149 } else {
3150 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3151 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3152 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3153 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3154 } else {
3155 TRACE("WINED3DRS_POINTSCALEENABLE not supported, but not on either\n");
3158 break;
3161 case WINED3DRS_COLORWRITEENABLE :
3163 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3164 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3165 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3166 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3167 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3168 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3169 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3170 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3171 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3172 checkGLcall("glColorMask(...)");
3174 break;
3176 case WINED3DRS_LOCALVIEWER :
3178 GLint state = (Value) ? 1 : 0;
3179 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3180 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3182 break;
3184 case WINED3DRS_LASTPIXEL :
3186 if (Value) {
3187 TRACE("Last Pixel Drawing Enabled\n");
3188 } else {
3189 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3192 break;
3194 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3196 if (Value) {
3197 TRACE("Software Processing Enabled\n");
3198 } else {
3199 TRACE("Software Processing Disabled\n");
3202 break;
3204 /** not supported */
3205 case WINED3DRS_ZVISIBLE :
3207 LEAVE_GL();
3208 return D3DERR_INVALIDCALL;
3211 /* Unhandled yet...! */
3212 case WINED3DRS_EDGEANTIALIAS :
3213 case WINED3DRS_WRAP0 :
3214 case WINED3DRS_WRAP1 :
3215 case WINED3DRS_WRAP2 :
3216 case WINED3DRS_WRAP3 :
3217 case WINED3DRS_WRAP4 :
3218 case WINED3DRS_WRAP5 :
3219 case WINED3DRS_WRAP6 :
3220 case WINED3DRS_WRAP7 :
3221 case WINED3DRS_POINTSPRITEENABLE :
3222 case WINED3DRS_MULTISAMPLEANTIALIAS :
3223 case WINED3DRS_MULTISAMPLEMASK :
3224 case WINED3DRS_PATCHEDGESTYLE :
3225 case WINED3DRS_PATCHSEGMENTS :
3226 case WINED3DRS_DEBUGMONITORTOKEN :
3227 case WINED3DRS_POSITIONORDER :
3228 case WINED3DRS_NORMALORDER :
3229 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3230 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3231 break;
3232 default:
3233 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3236 LEAVE_GL();
3238 return D3D_OK;
3241 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3242 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3243 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3244 *pValue = This->stateBlock->renderState[State];
3245 return D3D_OK;
3248 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3249 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3251 * SetSampler is designed to allow for more than the standard up to 8 textures
3252 * and Geforce has stopped supporting more than 6 standard textures in openGL.
3253 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3255 * http://developer.nvidia.com/object/General_FAQ.html#t6
3257 * There are two new settings for GForce
3258 * the sampler one:
3259 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3260 * and the texture one:
3261 * GL_MAX_TEXTURE_COORDS_ARB.
3262 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3263 ******************/
3264 union {
3265 float f;
3266 DWORD d;
3267 } tmpvalue;
3269 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
3271 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > HIGHEST_SAMPLER_STATE || Type < 0) {
3272 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), HIGHEST_SAMPLER_STATE, Sampler, Type);
3273 return D3DERR_INVALIDCALL;
3276 This->updateStateBlock->changed.samplerState[Sampler][Type] = TRUE;
3277 This->updateStateBlock->set.samplerState[Sampler][Type] = TRUE;
3278 TRACE("Setting sampler %ld %d to %ld \n", Sampler, Type, Value);
3279 This->updateStateBlock->samplerState[Sampler][Type] = Value;
3281 /* Handle recording of state blocks */
3282 if (This->isRecordingState) {
3283 TRACE("Recording... not performing anything\n");
3284 return D3D_OK;
3287 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
3288 clamping, MIPLOD, etc. This will work for up to 16 samplers.
3289 is this just GL_TEXTURE_2D or is it GL_TEXTURE_1D and GL_TEXTURE_3D as well?
3291 ENTER_GL();
3292 VTRACE(("Activating appropriate texture state %ld\n", Sampler));
3293 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3294 GLACTIVETEXTURE(Sampler);
3295 } else if (Sampler > 0) {
3296 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3300 switch (Type) {
3302 case WINED3DSAMP_ADDRESSU : /* 1 */
3303 case WINED3DSAMP_ADDRESSV : /* 2 */
3304 case WINED3DSAMP_ADDRESSW : /* 3 */
3306 GLint wrapParm = GL_REPEAT;
3307 switch (Value) {
3308 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3309 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3310 case D3DTADDRESS_BORDER:
3312 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3313 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3314 } else {
3315 /* FIXME: Not right, but better */
3316 TRACE("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3317 wrapParm = GL_REPEAT;
3320 break;
3321 case D3DTADDRESS_MIRROR:
3323 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3324 wrapParm = GL_MIRRORED_REPEAT_ARB;
3325 } else {
3326 /* Unsupported in OpenGL pre-1.4 */
3327 TRACE("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3328 wrapParm = GL_REPEAT;
3331 break;
3332 case D3DTADDRESS_MIRRORONCE:
3334 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3335 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3336 } else {
3337 TRACE("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3338 wrapParm = GL_REPEAT;
3341 break;
3343 default:
3344 /* This is for the whole context, not just the sampler,
3345 so we should warn if two states are baing set for any given scene */
3346 if (Type!=0)
3347 TRACE("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3348 wrapParm = GL_REPEAT;
3350 switch (Type) {
3351 case WINED3DSAMP_ADDRESSU:
3352 TRACE("Setting WRAP_S for %ld to %d \n", Sampler, wrapParm);
3353 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_WRAP_S, wrapParm);
3354 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3355 break;
3356 case WINED3DSAMP_ADDRESSV:
3357 TRACE("Setting WRAP_T for %ld to %d\n", Sampler, wrapParm);
3358 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_WRAP_T, wrapParm);
3359 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3360 break;
3362 case WINED3DSAMP_ADDRESSW:
3363 TRACE("Setting WRAP_R for %ld to %d\n", Sampler, wrapParm);
3364 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_WRAP_R, wrapParm);
3365 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3366 break;
3367 default: /* nop */
3368 break; /** stupic compilator */
3371 break;
3373 case WINED3DSAMP_BORDERCOLOR : /* 4 */
3375 float col[4];
3376 D3DCOLORTOGLFLOAT4(Value, col);
3377 TRACE("Setting border color for %ld to %lx\n", Sampler, Value);
3378 glTexParameterfv(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_BORDER_COLOR, &col[0]);
3379 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3381 break;
3383 case WINED3DSAMP_MAGFILTER : /* 5 */
3385 DWORD ValueMAG = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAGFILTER];
3386 GLint realVal = GL_NEAREST;
3388 if (ValueMAG == D3DTEXF_POINT) {
3389 realVal = GL_NEAREST;
3390 } else if (ValueMAG == D3DTEXF_LINEAR) {
3391 realVal = GL_LINEAR;
3392 } else if (ValueMAG == D3DTEXF_ANISOTROPIC) {
3393 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3394 realVal = GL_LINEAR;
3395 } else {
3396 FIXME("Trying to use ANISOTROPIC_FILTERING for WINED3DTSS_MAGFILTER. But not supported by current OpenGL driver\n");
3397 realVal = GL_NEAREST;
3399 } else {
3400 FIXME("Unhandled WINED3DTSS_MAGFILTER value of %ld\n", ValueMAG);
3401 realVal = GL_NEAREST;
3403 TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", ValueMAG, realVal);
3404 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_MAG_FILTER, realVal);
3405 checkGLcall("glTexParameter GL_TEXTURE_MAG_FILTER, ...");
3407 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3409 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMAG) {
3410 glTexParameteri(This->stateBlock->textureDimensions[Sampler],
3411 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3412 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXANISOTROPY]);
3413 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3416 break;
3418 case WINED3DSAMP_MINFILTER: /* 6 */
3419 case WINED3DSAMP_MIPFILTER: /* 7 */
3421 DWORD ValueMIN = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MINFILTER];
3422 DWORD ValueMIP = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPFILTER];
3423 GLint realVal = GL_LINEAR;
3425 if (ValueMIN == D3DTEXF_NONE) {
3426 /* Doesn't really make sense - Windows just seems to disable
3427 mipmapping when this occurs */
3428 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3429 realVal = GL_LINEAR;
3430 } else if (ValueMIN == D3DTEXF_POINT) {
3431 /* GL_NEAREST_* */
3432 if (ValueMIP == D3DTEXF_NONE) {
3433 realVal = GL_NEAREST;
3434 } else if (ValueMIP == D3DTEXF_POINT) {
3435 realVal = GL_NEAREST_MIPMAP_NEAREST;
3436 } else if (ValueMIP == D3DTEXF_LINEAR) {
3437 realVal = GL_NEAREST_MIPMAP_LINEAR;
3438 } else {
3439 FIXME("Unhandled WINED3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3440 realVal = GL_NEAREST;
3442 } else if (ValueMIN == D3DTEXF_LINEAR) {
3443 /* GL_LINEAR_* */
3444 if (ValueMIP == D3DTEXF_NONE) {
3445 realVal = GL_LINEAR;
3446 } else if (ValueMIP == D3DTEXF_POINT) {
3447 realVal = GL_LINEAR_MIPMAP_NEAREST;
3448 } else if (ValueMIP == D3DTEXF_LINEAR) {
3449 realVal = GL_LINEAR_MIPMAP_LINEAR;
3450 } else {
3451 FIXME("Unhandled WINED3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3452 realVal = GL_LINEAR;
3454 } else if (ValueMIN == D3DTEXF_ANISOTROPIC) {
3455 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3456 if (ValueMIP == D3DTEXF_NONE) {
3457 realVal = GL_LINEAR_MIPMAP_LINEAR;
3458 } else if (ValueMIP == D3DTEXF_POINT) {
3459 realVal = GL_LINEAR_MIPMAP_NEAREST;
3460 } else if (ValueMIP == D3DTEXF_LINEAR) {
3461 realVal = GL_LINEAR_MIPMAP_LINEAR;
3462 } else {
3463 FIXME("Unhandled WINED3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3464 realVal = GL_LINEAR;
3466 } else {
3467 WARN("Trying to use ANISOTROPIC_FILTERING for WINED3DTSS_MINFILTER. But not supported by OpenGL driver\n");
3468 realVal = GL_LINEAR;
3470 } else {
3471 FIXME("Unhandled WINED3DTSS_MINFILTER value of %ld\n", ValueMIN);
3472 realVal = GL_LINEAR_MIPMAP_LINEAR;
3475 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3476 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_MIN_FILTER, realVal);
3477 checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
3479 * if we just choose to use ANISOTROPIC filtering, refresh openGL state
3481 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMIN) {
3482 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_MAX_ANISOTROPY_EXT,
3483 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXANISOTROPY]);
3484 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3487 break;
3489 case WINED3DSAMP_MIPMAPLODBIAS : /* 8 */
3491 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3492 tmpvalue.d = Value;
3493 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3494 GL_TEXTURE_LOD_BIAS_EXT,
3495 tmpvalue.f);
3496 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
3499 break;
3501 case WINED3DSAMP_MAXMIPLEVEL : /* 9 */
3504 * Not really the same, but the more apprioprate than nothing
3506 glTexParameteri(This->stateBlock->textureDimensions[Sampler],
3507 GL_TEXTURE_BASE_LEVEL,
3508 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXMIPLEVEL]);
3509 checkGLcall("glTexParameteri GL_TEXTURE_BASE_LEVEL ...");
3511 break;
3513 case WINED3DSAMP_MAXANISOTROPY : /* 10 */
3515 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3516 glTexParameteri(This->stateBlock->textureDimensions[Sampler],
3517 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3518 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXANISOTROPY]);
3519 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3522 break;
3523 case WINED3DSAMP_SRGBTEXTURE : /* 11 */
3524 /* Per texture gamma correction, default 0 */
3525 case WINED3DSAMP_ELEMENTINDEX : /* 12 */
3526 /* When a multi-element textures is used this indicates the element, (what's a multielement texture?) */
3527 case WINED3DSAMP_DMAPOFFSET : /* 13 */
3528 /* Value of a precompiled displacement map used by the tesselator, default 0 */
3529 TRACE("Unsupported sampler setting, Sampler=%ld, Type=%d, Value =%ld\n", Sampler, Type, Value);
3530 break;
3531 default:
3533 TRACE("invalid sampler setting, Sampler=%ld, Type=%d, Value =%ld\n", Sampler, Type, Value);
3535 LEAVE_GL();
3536 return D3D_OK;
3539 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3540 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3541 /** TODO: check that sampler is in range **/
3542 *Value = This->updateStateBlock->samplerState[Sampler][Type];
3543 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
3544 return D3D_OK;
3548 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3549 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3550 ENTER_GL();
3552 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3553 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3554 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3555 LEAVE_GL();
3556 return D3D_OK;
3559 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3560 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3561 GLint scissorBox[4];
3563 ENTER_GL();
3564 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3565 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
3566 pRect->left = scissorBox[1];
3567 pRect->top = scissorBox[2];
3568 pRect->right = scissorBox[1] + scissorBox[3];
3569 pRect->bottom = scissorBox[2] + scissorBox[4];
3570 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3571 LEAVE_GL();
3572 return D3D_OK;
3575 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3576 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3578 TRACE("(%p) : pDecl=%p\n", This, pDecl);
3580 /* TODO: what about recording stateblocks? */
3581 if (NULL != pDecl) {
3582 IWineD3DVertexDeclaration_AddRef(pDecl);
3584 if (NULL != This->updateStateBlock->vertexDecl) {
3585 IWineD3DVertexDeclaration_Release(This->updateStateBlock->vertexDecl);
3587 This->updateStateBlock->vertexDecl = pDecl;
3588 This->updateStateBlock->changed.vertexDecl = TRUE;
3589 This->updateStateBlock->set.vertexDecl = TRUE;
3590 return D3D_OK;
3593 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3594 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3596 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3598 *ppDecl = This->updateStateBlock->vertexDecl;
3599 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3600 return D3D_OK;
3603 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
3604 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3606 static BOOL showFixmes = TRUE;
3608 This->updateStateBlock->vertexShader = pShader;
3609 This->updateStateBlock->changed.vertexShader = TRUE;
3610 This->updateStateBlock->set.vertexShader = TRUE;
3612 if(pShader == NULL) {
3613 /* clear down the shader */
3614 TRACE("Clear down the shader\n");
3615 }else{
3616 if(showFixmes) {
3617 FIXME("(%p) : stub pShader(%p)\n", This, pShader);
3618 showFixmes = FALSE;
3622 return D3D_OK;
3624 /** FIXME: refernece counting? **/
3625 if (pShader == NULL) { /* only valid with non FVF shaders */
3626 TRACE_(d3d_shader)("(%p) : FVF Shader, pShader=%p\n", This, pShader);
3627 This->updateStateBlock->vertexShader = NULL;
3628 } else {
3629 TRACE_(d3d_shader)("(%p) : Created shader, pShader=%p\n", This, pShader);
3630 This->updateStateBlock->vertexShader = pShader;
3633 This->updateStateBlock->changed.vertexShader = TRUE;
3634 This->updateStateBlock->set.vertexShader = TRUE;
3636 /* Handle recording of state blocks */
3637 if (This->isRecordingState) {
3638 TRACE("Recording... not performing anything\n");
3639 return D3D_OK;
3642 * TODO: merge HAL shaders context switching from prototype
3644 return D3D_OK;
3648 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
3649 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3650 *ppShader = This->stateBlock->vertexShader;
3651 if(*ppShader != NULL)
3652 IWineD3DVertexShader_AddRef(*ppShader);
3653 TRACE("(%p) : returning %p\n", This, *ppShader);
3654 return D3D_OK;
3657 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
3658 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3660 TRACE("(%p) : stub\n", This);
3661 return D3D_OK;
3664 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
3665 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3666 TRACE("(%p) : stub\n", This);
3667 return D3D_OK;
3670 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
3671 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3672 TRACE("(%p) : stub\n", This);
3673 return D3D_OK;
3676 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
3677 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3678 TRACE("(%p) : stub\n", This);
3679 return D3D_OK;
3682 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
3683 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3684 TRACE("(%p) : stub\n", This);
3685 return D3D_OK;
3688 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
3689 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3690 TRACE("(%p) : stub\n", This);
3691 return D3D_OK;
3694 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
3695 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3696 TRACE("(%p) : stub\n", This);
3697 return D3D_OK;
3700 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3701 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3702 TRACE("(%p) : stub\n", This);
3703 return D3D_OK;
3707 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
3708 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3709 TRACE("(%p) : stub\n", This);
3710 return D3D_OK;
3713 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
3714 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3715 TRACE("(%p) : stub\n", This);
3716 return D3D_OK;
3719 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
3720 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3721 TRACE("(%p) : stub\n", This);
3722 return D3D_OK;
3725 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
3726 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3727 TRACE("(%p) : stub\n", This);
3728 return D3D_OK;
3731 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
3732 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3733 TRACE("(%p) : stub\n", This);
3734 return D3D_OK;
3737 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
3738 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3739 TRACE("(%p) : stub\n", This);
3740 return D3D_OK;
3743 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
3744 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3745 FIXME("(%p) : stub\n", This);
3746 return D3D_OK;
3749 /*****
3750 * Get / Set Texture Stage States
3751 * TODO: Verify against dx9 definitions
3752 *****/
3753 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3754 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3756 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3758 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3760 /* Reject invalid texture units */
3761 if (Stage >= GL_LIMITS(textures)) {
3762 TRACE("Attempt to access invalid texture rejected\n");
3763 return D3DERR_INVALIDCALL;
3766 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
3767 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
3768 This->updateStateBlock->textureState[Stage][Type] = Value;
3770 /* Handle recording of state blocks */
3771 if (This->isRecordingState) {
3772 TRACE("Recording... not performing anything\n");
3773 return D3D_OK;
3776 ENTER_GL();
3778 /* Make appropriate texture active */
3779 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3780 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3781 GLACTIVETEXTURE(Stage);
3782 } else if (Stage > 0) {
3783 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3786 switch (Type) {
3787 case WINED3DTSS_ALPHAOP :
3788 case WINED3DTSS_COLOROP :
3791 if ((Value == D3DTOP_DISABLE) && (Type == WINED3DTSS_COLOROP)) {
3792 /* TODO: Disable by making this and all later levels disabled */
3793 glDisable(GL_TEXTURE_1D);
3794 checkGLcall("Disable GL_TEXTURE_1D");
3795 glDisable(GL_TEXTURE_2D);
3796 checkGLcall("Disable GL_TEXTURE_2D");
3797 glDisable(GL_TEXTURE_3D);
3798 checkGLcall("Disable GL_TEXTURE_3D");
3799 break; /* Don't bother setting the texture operations */
3800 } else {
3801 /* Enable only the appropriate texture dimension */
3802 if (Type == WINED3DTSS_COLOROP) {
3803 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3804 glEnable(GL_TEXTURE_1D);
3805 checkGLcall("Enable GL_TEXTURE_1D");
3806 } else {
3807 glDisable(GL_TEXTURE_1D);
3808 checkGLcall("Disable GL_TEXTURE_1D");
3810 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3811 if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
3812 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
3813 checkGLcall("Enable GL_TEXTURE_2D");
3814 } else {
3815 glEnable(GL_TEXTURE_2D);
3816 checkGLcall("Enable GL_TEXTURE_2D");
3818 } else {
3819 glDisable(GL_TEXTURE_2D);
3820 checkGLcall("Disable GL_TEXTURE_2D");
3822 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3823 glEnable(GL_TEXTURE_3D);
3824 checkGLcall("Enable GL_TEXTURE_3D");
3825 } else {
3826 glDisable(GL_TEXTURE_3D);
3827 checkGLcall("Disable GL_TEXTURE_3D");
3829 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3830 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3831 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3832 } else {
3833 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3834 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3838 /* Drop through... (Except disable case) */
3839 case WINED3DTSS_COLORARG0 :
3840 case WINED3DTSS_COLORARG1 :
3841 case WINED3DTSS_COLORARG2 :
3842 case WINED3DTSS_ALPHAARG0 :
3843 case WINED3DTSS_ALPHAARG1 :
3844 case WINED3DTSS_ALPHAARG2 :
3846 BOOL isAlphaArg = (Type == WINED3DTSS_ALPHAOP || Type == WINED3DTSS_ALPHAARG1 ||
3847 Type == WINED3DTSS_ALPHAARG2 || Type == WINED3DTSS_ALPHAARG0);
3848 if (isAlphaArg) {
3849 set_tex_op(iface, TRUE, Stage, This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAOP],
3850 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG1],
3851 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG2],
3852 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG0]);
3853 } else {
3854 set_tex_op(iface, FALSE, Stage, This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP],
3855 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG1],
3856 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG2],
3857 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG0]);
3860 break;
3863 case WINED3DTSS_ADDRESSW :
3865 GLint wrapParm = GL_REPEAT;
3867 switch (Value) {
3868 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3869 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3870 case D3DTADDRESS_BORDER:
3872 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3873 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3874 } else {
3875 /* FIXME: Not right, but better */
3876 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3877 wrapParm = GL_REPEAT;
3880 break;
3881 case D3DTADDRESS_MIRROR:
3883 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3884 wrapParm = GL_MIRRORED_REPEAT_ARB;
3885 } else {
3886 /* Unsupported in OpenGL pre-1.4 */
3887 FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3888 wrapParm = GL_REPEAT;
3891 break;
3892 case D3DTADDRESS_MIRRORONCE:
3894 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3895 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3896 } else {
3897 FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3898 wrapParm = GL_REPEAT;
3901 break;
3903 default:
3904 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3905 wrapParm = GL_REPEAT;
3908 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
3909 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3910 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3912 break;
3914 case WINED3DTSS_TEXCOORDINDEX :
3916 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3918 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
3919 one flag, you can still specify an index value, which the system uses to
3920 determine the texture wrapping mode.
3921 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3922 means use the vertex position (camera-space) as the input texture coordinates
3923 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
3924 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3925 to the TEXCOORDINDEX value */
3928 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3930 switch (Value & 0xFFFF0000) {
3931 case D3DTSS_TCI_PASSTHRU:
3932 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3933 glDisable(GL_TEXTURE_GEN_S);
3934 glDisable(GL_TEXTURE_GEN_T);
3935 glDisable(GL_TEXTURE_GEN_R);
3936 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3937 break;
3939 case D3DTSS_TCI_CAMERASPACEPOSITION:
3940 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3941 as the input texture coordinates for this stage's texture transformation. This
3942 equates roughly to EYE_LINEAR */
3944 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3945 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3946 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3947 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3948 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3950 glMatrixMode(GL_MODELVIEW);
3951 glPushMatrix();
3952 glLoadIdentity();
3953 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3954 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3955 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3956 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3957 glPopMatrix();
3959 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3960 glEnable(GL_TEXTURE_GEN_S);
3961 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3962 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3963 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3964 glEnable(GL_TEXTURE_GEN_T);
3965 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3966 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3967 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3968 glEnable(GL_TEXTURE_GEN_R);
3969 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3970 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3971 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3973 break;
3975 case D3DTSS_TCI_CAMERASPACENORMAL:
3977 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3978 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3979 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3980 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3981 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3982 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3984 glMatrixMode(GL_MODELVIEW);
3985 glPushMatrix();
3986 glLoadIdentity();
3987 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3988 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3989 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3990 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3991 glPopMatrix();
3993 glEnable(GL_TEXTURE_GEN_S);
3994 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3995 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3996 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3997 glEnable(GL_TEXTURE_GEN_T);
3998 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3999 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4000 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4001 glEnable(GL_TEXTURE_GEN_R);
4002 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4003 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4004 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4007 break;
4009 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
4011 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4012 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4013 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4014 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4015 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4016 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4018 glMatrixMode(GL_MODELVIEW);
4019 glPushMatrix();
4020 glLoadIdentity();
4021 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4022 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4023 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4024 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4025 glPopMatrix();
4027 glEnable(GL_TEXTURE_GEN_S);
4028 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4029 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4030 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4031 glEnable(GL_TEXTURE_GEN_T);
4032 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4033 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4034 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4035 glEnable(GL_TEXTURE_GEN_R);
4036 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4037 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4038 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4041 break;
4043 /* Unhandled types: */
4044 default:
4045 /* Todo: */
4046 /* ? disable GL_TEXTURE_GEN_n ? */
4047 glDisable(GL_TEXTURE_GEN_S);
4048 glDisable(GL_TEXTURE_GEN_T);
4049 glDisable(GL_TEXTURE_GEN_R);
4050 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
4051 break;
4054 break;
4056 /* Unhandled */
4057 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
4058 set_texture_matrix((float *)&This->stateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
4059 break;
4061 case WINED3DTSS_BUMPENVMAT00 :
4062 case WINED3DTSS_BUMPENVMAT01 :
4063 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
4064 break;
4065 case WINED3DTSS_BUMPENVMAT10 :
4066 case WINED3DTSS_BUMPENVMAT11 :
4067 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
4068 break;
4070 case WINED3DTSS_BUMPENVLSCALE :
4071 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4072 break;
4074 case WINED3DTSS_BUMPENVLOFFSET :
4075 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4076 break;
4078 case WINED3DTSS_RESULTARG :
4079 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4080 break;
4082 default:
4083 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
4084 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4087 LEAVE_GL();
4089 return D3D_OK;
4092 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4093 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4094 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4095 *pValue = This->updateStateBlock->textureState[Stage][Type];
4096 return D3D_OK;
4099 /*****
4100 * Get / Set Texture
4101 *****/
4102 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4104 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4105 IWineD3DBaseTexture *oldTexture;
4106 BOOL reapplyStates = TRUE;
4107 DWORD reapplyFlags = 0;
4108 INT oldTextureDimensions = -1;
4109 D3DRESOURCETYPE textureType;
4111 oldTexture = This->updateStateBlock->textures[Stage];
4112 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
4114 /* Reject invalid texture units */
4115 if (Stage >= GL_LIMITS(textures)) {
4116 TRACE("Attempt to access invalid texture rejected\n");
4117 return D3DERR_INVALIDCALL;
4120 This->updateStateBlock->set.textures[Stage] = TRUE;
4121 This->updateStateBlock->changed.textures[Stage] = TRUE;
4122 This->updateStateBlock->textures[Stage] = pTexture;
4124 /* Handle recording of state blocks */
4125 if (This->isRecordingState) {
4126 TRACE("Recording... not performing anything\n");
4127 return D3D_OK;
4130 oldTextureDimensions = This->updateStateBlock->textureDimensions[Stage];
4132 ENTER_GL();
4134 /* Make appropriate texture active */
4135 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
4136 GLACTIVETEXTURE(Stage);
4138 } else if (Stage>0) {
4139 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
4142 /** NOTE: MSDN says that setTexture increases the reference count,
4143 * and the the application nust set the texture back to null (or have a leaky application),
4144 * This means we should pass the refcount upto the parent
4145 *******************************/
4146 if (NULL != oldTexture) {
4148 IUnknown *textureParent;
4149 IWineD3DBaseTexture_GetParent(oldTexture, (IUnknown **)&textureParent);
4150 IUnknown_Release(textureParent);
4151 IUnknown_Release(textureParent); /** NOTE: Twice because GetParent adds a ref **/
4152 oldTexture = NULL;
4156 if (NULL != pTexture) {
4157 IUnknown *textureParent;
4158 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[Stage], (IUnknown **)&textureParent);
4159 /** NOTE: GetParent will increase the ref count for me, I won't clean up untill the texture is set to NULL **/
4161 /* Now setup the texture appropraitly */
4162 textureType = IWineD3DBaseTexture_GetType(pTexture);
4164 if (textureType == D3DRTYPE_TEXTURE) {
4166 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
4167 TRACE("Skipping setting texture as old == new\n");
4168 reapplyStates = FALSE;
4170 } else {
4172 /* Standard 2D texture */
4173 TRACE("Standard 2d texture\n");
4174 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
4176 /* Load up the texture now */
4177 IWineD3DTexture_PreLoad((IWineD3DTexture *) pTexture);
4180 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
4182 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
4183 TRACE("Skipping setting texture as old == new\n");
4184 reapplyStates = FALSE;
4186 } else {
4188 /* Standard 3D (volume) texture */
4189 TRACE("Standard 3d texture\n");
4190 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
4192 /* Load up the texture now */
4193 IWineD3DVolumeTexture_PreLoad((IWineD3DVolumeTexture *) pTexture);
4196 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
4198 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
4199 TRACE("Skipping setting texture as old == new\n");
4200 reapplyStates = FALSE;
4202 } else {
4204 /* Standard Cube texture */
4205 TRACE("Standard Cube texture\n");
4206 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
4208 /* Load up the texture now */
4209 IWineD3DCubeTexture_PreLoad((IWineD3DCubeTexture *) pTexture);
4212 } else {
4213 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dresourcetype(textureType));
4216 } else {
4218 TRACE("Setting to no texture (ie default texture)\n");
4219 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
4220 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
4221 checkGLcall("glBindTexture");
4222 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
4225 /* Disable the old texture binding and enable the new one (unless operations are disabled) */
4226 if (oldTextureDimensions != This->updateStateBlock->textureDimensions[Stage]) {
4228 glDisable(oldTextureDimensions);
4229 checkGLcall("Disable oldTextureDimensions");
4231 if (This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP] != D3DTOP_DISABLE) {
4232 glEnable(This->updateStateBlock->textureDimensions[Stage]);
4233 checkGLcall("glEnable new texture dimensions");
4236 /* If Alpha arg1 is texture then handle the special case when there changes between a
4237 texture and no texture - See comments in set_tex_op */
4238 if ((This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
4239 (((oldTexture == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTexture != NULL))))
4241 reapplyFlags |= REAPPLY_ALPHAOP;
4246 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
4247 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
4248 if (reapplyStates) {
4249 IWineD3DDeviceImpl_SetupTextureStates(iface, Stage, reapplyFlags);
4252 LEAVE_GL();
4253 TRACE("Texture now fully setup\n");
4255 return D3D_OK;
4258 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4259 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4260 TRACE("(%p) : returning %p for stage %ld\n", This, This->updateStateBlock->textures[Stage], Stage);
4261 *ppTexture = (IWineD3DBaseTexture *) This->updateStateBlock->textures[Stage];
4262 if (*ppTexture)
4263 IWineD3DBaseTexture_AddRef(*ppTexture);
4264 return D3D_OK;
4267 /*****
4268 * Get Back Buffer
4269 *****/
4270 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type,
4271 IWineD3DSurface** ppBackBuffer) {
4272 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4273 IWineD3DSwapChain *swapChain;
4274 HRESULT hr;
4276 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4278 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4279 if(hr == D3D_OK) {
4280 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4281 IWineD3DSwapChain_Release(swapChain);
4282 }else{
4283 *ppBackBuffer = NULL;
4285 return hr;
4288 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4289 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4290 WARN("(%p) : stub, calling idirect3d for now\n", This);
4291 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4294 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
4295 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4296 IWineD3DSwapChain *swapChain;
4297 HRESULT hr;
4299 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4300 if (hr == D3D_OK) {
4301 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4302 IWineD3DSwapChain_Release(swapChain);
4303 }else{
4304 FIXME("(%p) Error getting display mode\n", This);
4306 return hr;
4308 /*****
4309 * Stateblock related functions
4310 *****/
4312 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4313 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4314 IWineD3DStateBlockImpl *object;
4315 TRACE("(%p)", This);
4316 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4317 if(NULL == object ) {
4318 FIXME("(%p)Error allocating memory for stateblock\n", This);
4319 return E_OUTOFMEMORY;
4321 TRACE("(%p) creted object %p\n", This, object);
4322 object->wineD3DDevice= This;
4323 /** FIXME: object->parent = parent; **/
4324 object->parent = NULL;
4325 object->blockType = D3DSBT_ALL;
4326 object->ref = 1;
4327 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
4329 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4330 This->updateStateBlock = object;
4331 This->isRecordingState = TRUE;
4333 TRACE("(%p) recording stateblock %p\n",This , object);
4334 return D3D_OK;
4337 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4338 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4340 if (!This->isRecordingState) {
4341 FIXME("(%p) not recording! returning error\n", This);
4342 *ppStateBlock = NULL;
4343 return D3DERR_INVALIDCALL;
4346 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4347 This->isRecordingState = FALSE;
4348 This->updateStateBlock = This->stateBlock;
4349 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4350 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4351 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4352 return D3D_OK;
4355 /*****
4356 * Scene related functions
4357 *****/
4358 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4359 /* At the moment we have no need for any functionality at the beginning
4360 of a scene */
4361 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4362 TRACE("(%p) : stub\n", This);
4363 return D3D_OK;
4366 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4367 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4368 TRACE("(%p)\n", This);
4369 ENTER_GL();
4370 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4371 glFlush();
4372 checkGLcall("glFlush");
4374 TRACE("End Scene\n");
4375 if(This->renderTarget != NULL) {
4377 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4378 IUnknown *targetContainer = NULL;
4379 if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
4380 || D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
4381 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
4382 /** always dirtify for now. we must find a better way to see that surface have been modified
4383 (Modifications should will only occur via draw-primitive, but we do need better locking
4384 switching to render-to-texture should remove the overhead though.
4386 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4387 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
4388 IWineD3DSurface_PreLoad(This->renderTarget);
4389 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4390 IUnknown_Release(targetContainer);
4393 This->sceneEnded = TRUE;
4394 LEAVE_GL();
4395 return D3D_OK;
4398 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4399 CONST RECT* pSourceRect, CONST RECT* pDestRect,
4400 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4401 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4402 IWineD3DSwapChain *swapChain = NULL;
4403 int i;
4404 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4406 TRACE("(%p) Presenting the frame\n", This);
4408 for(i = 0 ; i < swapchains ; i ++) {
4410 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4411 TRACE("presentinng chain %d, %p\n", i, swapChain);
4412 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4413 IWineD3DSwapChain_Release(swapChain);
4416 return D3D_OK;
4419 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4420 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4421 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4423 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4424 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4425 when the depth-buffer format does not contain stencil buffer information, this method fails. */
4426 GLbitfield glMask = 0;
4427 GLboolean old_ztest;
4428 GLfloat old_z_clear_value;
4429 GLint old_stencil_clear_value;
4430 GLfloat old_color_clear_value[4];
4431 unsigned int i;
4432 CONST D3DRECT* curRect;
4434 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4435 Count, pRects, Flags, Z, Stencil);
4437 ENTER_GL();
4439 glEnable(GL_SCISSOR_TEST);
4440 checkGLcall("glEnable GL_SCISSOR_TEST");
4442 if (Count > 0 && pRects) {
4443 curRect = pRects;
4444 } else {
4445 curRect = NULL;
4448 /* Only set the values up once, as they are not changing */
4449 if (Flags & D3DCLEAR_STENCIL) {
4450 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4451 glClearStencil(Stencil);
4452 checkGLcall("glClearStencil");
4453 glMask = glMask | GL_STENCIL_BUFFER_BIT;
4454 glStencilMask(0xFFFFFFFF);
4457 if (Flags & D3DCLEAR_ZBUFFER) {
4458 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4459 glDepthMask(GL_TRUE);
4460 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4461 glClearDepth(Z);
4462 checkGLcall("glClearDepth");
4463 glMask = glMask | GL_DEPTH_BUFFER_BIT;
4466 if (Flags & D3DCLEAR_TARGET) {
4467 TRACE("Clearing screen with glClear to color %lx\n", Color);
4468 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4469 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
4470 ((Color >> 8) & 0xFF) / 255.0f,
4471 ((Color >> 0) & 0xFF) / 255.0f,
4472 ((Color >> 24) & 0xFF) / 255.0f);
4473 checkGLcall("glClearColor");
4475 /* Clear ALL colors! */
4476 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4477 glMask = glMask | GL_COLOR_BUFFER_BIT;
4480 /* Now process each rect in turn */
4481 for (i = 0; i < Count || i == 0; i++) {
4483 if (curRect) {
4484 /* Note gl uses lower left, width/height */
4485 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4486 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4487 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4488 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4489 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4490 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4491 checkGLcall("glScissor");
4492 } else {
4493 glScissor(This->stateBlock->viewport.X,
4494 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4495 This->stateBlock->viewport.Width,
4496 This->stateBlock->viewport.Height);
4497 checkGLcall("glScissor");
4500 /* Clear the selected rectangle (or full screen) */
4501 glClear(glMask);
4502 checkGLcall("glClear");
4504 /* Step to the next rectangle */
4505 if (curRect) curRect = curRect + sizeof(D3DRECT);
4508 /* Restore the old values (why..?) */
4509 if (Flags & D3DCLEAR_STENCIL) {
4510 glClearStencil(old_stencil_clear_value);
4511 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4513 if (Flags & D3DCLEAR_ZBUFFER) {
4514 glDepthMask(old_ztest);
4515 glClearDepth(old_z_clear_value);
4517 if (Flags & D3DCLEAR_TARGET) {
4518 glClearColor(old_color_clear_value[0],
4519 old_color_clear_value[1],
4520 old_color_clear_value[2],
4521 old_color_clear_value[3]);
4522 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4523 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4524 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4525 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4528 glDisable(GL_SCISSOR_TEST);
4529 checkGLcall("glDisable");
4530 LEAVE_GL();
4532 return D3D_OK;
4535 /*****
4536 * Drawing functions
4537 *****/
4538 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4539 UINT PrimitiveCount) {
4541 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4542 This->stateBlock->streamIsUP = FALSE;
4544 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4545 debug_d3dprimitivetype(PrimitiveType),
4546 StartVertex, PrimitiveCount);
4547 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
4549 return D3D_OK;
4552 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4553 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4554 D3DPRIMITIVETYPE PrimitiveType,
4555 INT baseVIndex, UINT minIndex,
4556 UINT NumVertices,UINT startIndex,UINT primCount) {
4558 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4559 UINT idxStride = 2;
4560 IWineD3DIndexBuffer *pIB;
4561 D3DINDEXBUFFER_DESC IdxBufDsc;
4563 pIB = This->stateBlock->pIndexData;
4564 This->stateBlock->streamIsUP = FALSE;
4566 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d \n", This,
4567 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4568 minIndex, NumVertices, startIndex, baseVIndex, primCount);
4570 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4571 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4572 idxStride = 2;
4573 } else {
4574 idxStride = 4;
4577 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex,
4578 startIndex, idxStride,
4579 ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory,
4580 minIndex);
4582 return D3D_OK;
4585 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4586 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4587 UINT VertexStreamZeroStride) {
4588 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4590 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4591 debug_d3dprimitivetype(PrimitiveType),
4592 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4594 if (This->stateBlock->streamSource[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
4596 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4597 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4598 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4599 This->stateBlock->streamIsUP = TRUE;
4600 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
4601 This->stateBlock->streamStride[0] = 0;
4602 This->stateBlock->streamSource[0] = NULL;
4604 /*stream zero settings set to null at end, as per the msdn */
4605 return D3D_OK;
4608 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4609 UINT MinVertexIndex,
4610 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
4611 WINED3DFORMAT IndexDataFormat, CONST void* pVertexStreamZeroData,
4612 UINT VertexStreamZeroStride) {
4613 int idxStride;
4614 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4616 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4617 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4618 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData,
4619 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4621 if (This->stateBlock->streamSource[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
4623 if (IndexDataFormat == WINED3DFMT_INDEX16) {
4624 idxStride = 2;
4625 } else {
4626 idxStride = 4;
4629 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4630 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4631 This->stateBlock->streamIsUP = TRUE;
4632 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4634 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, idxStride, pIndexData, MinVertexIndex);
4636 /* stream zero settings set to null at end as per the msdn */
4637 This->stateBlock->streamSource[0] = NULL;
4638 This->stateBlock->streamStride[0] = 0;
4639 IWineD3DDevice_SetIndices(iface, NULL, 0);
4641 return D3D_OK;
4644 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4645 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
4646 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4647 D3DRESOURCETYPE sourceType;
4648 D3DRESOURCETYPE destinationType;
4649 IWineD3DTextureImpl *pDestTexture = (IWineD3DTextureImpl *)pDestinationTexture;
4650 IWineD3DTextureImpl *pSrcTexture = (IWineD3DTextureImpl *)pSourceTexture;
4651 int i;
4653 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
4654 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
4655 if(sourceType != D3DRTYPE_TEXTURE && destinationType != D3DRTYPE_TEXTURE){
4656 FIXME("(%p) Only D3DRTYPE_TEXTURE to D3DRTYPE_TEXTURE supported\n", This);
4657 return D3DERR_INVALIDCALL;
4659 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
4661 /** TODO: Get rid of the casts to IWineD3DBaseTextureImpl
4662 repalce surfaces[x] with GetSurfaceLevel, or GetCubeMapSurface etc..
4663 think about moving the code into texture, and adding a member to base texture to occomplish this **/
4665 /* Make sure that the destination texture is loaded */
4666 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
4667 TRACE("Loading source texture\n");
4669 if(pSrcTexture->surfaces[0] == NULL || pDestTexture->surfaces[0] == NULL){
4670 FIXME("(%p) Texture src %p or dest %p has not surface %p %p\n", This, pSrcTexture, pDestTexture,
4671 pSrcTexture->surfaces[0], pDestTexture->surfaces[0]);
4674 if(((IWineD3DSurfaceImpl *)pSrcTexture->surfaces[0])->resource.pool != D3DPOOL_SYSTEMMEM ||
4675 ((IWineD3DSurfaceImpl *)pDestTexture->surfaces[0])->resource.pool != D3DPOOL_DEFAULT){
4677 FIXME("(%p) source %p must be SYSTEMMEM and dest %p must be DEFAULT\n",This, pSrcTexture, pDestTexture);
4678 return D3DERR_INVALIDCALL;
4680 /** TODO: check that both textures have the same number of levels **/
4681 #if 0
4682 if(IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) !=IWineD3DBaseTexture_GetLevelCount(pSourceTexture))
4683 return D3DERR_INVALIDCALL;
4684 #endif
4685 /** TODO: move this code into baseTexture? device should never touch impl*'s **/
4686 for(i = 0 ; i < IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) ; i++){
4687 IWineD3DDevice_UpdateSurface(iface, pSrcTexture->surfaces[i], NULL, pDestTexture->surfaces[i], NULL);
4690 return D3D_OK;
4693 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
4694 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
4695 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
4696 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4698 TRACE("(%p) : stub\n", This);
4699 return D3D_OK;
4701 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
4702 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4704 TRACE("(%p) : stub\n", This);
4705 return D3D_OK;
4708 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
4709 IWineD3DSwapChain *swapChain;
4710 HRESULT hr;
4711 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4712 if(hr == D3D_OK) {
4713 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
4714 IWineD3DSwapChain_Release(swapChain);
4716 return hr;
4719 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4720 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4721 /* return a sensible default */
4722 *pNumPasses = 1;
4723 FIXME("(%p) : stub\n", This);
4724 return D3D_OK;
4727 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4728 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4729 FIXME("(%p) : stub\n", This);
4730 return D3D_OK;
4733 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4734 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4735 FIXME("(%p) : stub\n", This);
4736 return D3D_OK;
4739 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4740 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4741 FIXME("(%p) : stub\n", This);
4742 return D3D_OK;
4745 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4746 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4747 FIXME("(%p) : stub\n", This);
4748 return D3D_OK;
4751 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4752 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4753 FIXME("(%p) : stub\n", This);
4754 return D3D_OK;
4758 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4759 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4760 FIXME("(%p) : stub\n", This);
4761 return FALSE;
4765 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
4766 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4768 pRasterStatus->InVBlank = TRUE;
4769 pRasterStatus->ScanLine = 0;
4770 FIXME("(%p) : stub\n", This);
4771 return D3D_OK;
4775 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4776 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4777 static BOOL showfixmes = TRUE;
4778 if(nSegments != 0.0f) {
4779 if( showfixmes) {
4780 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4781 showfixmes = FALSE;
4784 return D3D_OK;
4787 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4788 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4789 static BOOL showfixmes = TRUE;
4790 if( showfixmes) {
4791 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4792 showfixmes = FALSE;
4794 return 0.0f;
4798 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4799 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4800 /** TODO: remove casts to IWineD3DSurfaceImpl
4801 * NOTE: move code to surface to accomplish this
4802 ****************************************/
4803 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
4804 int srcWidth, srcHeight, srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
4805 WINED3DFORMAT destFormat, srcFormat;
4806 UINT destSize;
4807 int destLeft, destTop;
4808 D3DPOOL srcPool, destPool;
4809 int offset = 0;
4810 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
4811 glDescriptor *glDescription = NULL;
4812 GLenum textureDimensions = GL_TEXTURE_2D;
4813 IWineD3DBaseTexture *baseTexture;
4815 WINED3DSURFACE_DESC winedesc;
4817 memset(&winedesc, 0, sizeof(winedesc));
4818 winedesc.Width = &srcSurfaceWidth;
4819 winedesc.Height = &srcSurfaceHeight;
4820 winedesc.Pool = &srcPool;
4821 winedesc.Format = &srcFormat;
4823 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
4825 winedesc.Width = &destSurfaceWidth;
4826 winedesc.Height = &destSurfaceHeight;
4827 winedesc.Pool = &destPool;
4828 winedesc.Format = &destFormat;
4829 winedesc.Size = &destSize;
4831 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
4833 if(srcPool != D3DPOOL_SYSTEMMEM || destPool != D3DPOOL_DEFAULT){
4834 FIXME("source %p must be SYSTEMMEM and dest %p must be DEFAULT\n", pSourceSurface, pDestinationSurface);
4835 return D3DERR_INVALIDCALL;
4837 /* TODO: change this to use bindTexture */
4838 /* Make sure the surface is loaded and upto date */
4839 IWineD3DSurface_PreLoad(pDestinationSurface);
4841 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
4843 ENTER_GL();
4845 /* this needs to be done in lines if the sourceRect != the sourceWidth */
4846 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
4847 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
4848 destLeft = pDestPoint ? pDestPoint->x : 0;
4849 destTop = pDestPoint ? pDestPoint->y : 0;
4852 /* This function doesn't support compressed textures
4853 the pitch is just bytesPerPixel * width */
4855 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
4856 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
4857 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
4858 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
4860 /* TODO DXT formats */
4862 if(pSourceRect != NULL && pSourceRect->top != 0){
4863 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
4865 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
4866 ,This
4867 ,glDescription->level
4868 ,destLeft
4869 ,destTop
4870 ,srcWidth
4871 ,srcHeight
4872 ,glDescription->glFormat
4873 ,glDescription->glType
4874 ,IWineD3DSurface_GetData(pSourceSurface)
4877 /* Sanity check */
4878 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
4879 /* need to lock the surface to get the data */
4880 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
4882 /* TODO: Cube and volume support */
4883 if(rowoffset != 0){
4884 /* not a whole row so we have to do it a line at a time */
4885 int j;
4886 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
4887 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
4889 for(j = destTop ; j < (srcHeight + destTop) ; j++){
4891 glTexSubImage2D(glDescription->target
4892 ,glDescription->level
4893 ,destLeft
4895 ,srcWidth
4897 ,glDescription->glFormat
4898 ,glDescription->glType
4899 ,data/* could be quicker using */
4901 data += rowoffset;
4904 } else { /* Full width, so just write out the whole texture */
4906 if (WINED3DFMT_DXT1 == destFormat ||
4907 WINED3DFMT_DXT3 == destFormat ||
4908 WINED3DFMT_DXT5 == destFormat) {
4909 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
4910 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
4911 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
4912 FIXME("Updating part of a compressed texture is not supported at the moment\n");
4913 } if (destFormat != srcFormat) {
4914 FIXME("Updating mixed format compressed texture is not curretly support\n");
4915 } else {
4916 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
4917 glDescription->level,
4918 glDescription->glFormatInternal,
4919 srcWidth,
4920 srcHeight,
4922 destSize,
4923 IWineD3DSurface_GetData(pSourceSurface));
4925 } else {
4926 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
4930 } else {
4931 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
4932 to repack the data from pow2Width/Height to expected Width,Height, this makes the
4933 data returned by GetData non-power2 width/height with hardware non-power2
4934 pow2Width/height are set to surface width height, repacking isn't needed so it
4935 doesn't matter which function gets called. */
4936 glTexSubImage2D(glDescription->target
4937 ,glDescription->level
4938 ,destLeft
4939 ,destTop
4940 ,srcWidth
4941 ,srcHeight
4942 ,glDescription->glFormat
4943 ,glDescription->glType
4944 ,IWineD3DSurface_GetData(pSourceSurface)
4949 checkGLcall("glTexSubImage2D");
4950 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
4951 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
4952 * surface bigger than it needs to be hmm.. */
4953 if (D3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
4954 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
4955 IWineD3DBaseTexture_Release(baseTexture);
4958 glDisable(textureDimensions); /* This needs to be managed better.... */
4959 LEAVE_GL();
4961 return D3D_OK;
4964 /* Implementation details at http://developer.nvidia.com/attach/6494
4966 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
4967 hmm.. no longer supported use
4968 OpenGL evaluators or tessellate surfaces within your application.
4971 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
4972 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4973 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4974 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p) \n", This, Handle, pNumSegs, pRectPatchInfo);
4975 FIXME("(%p) : Stub\n", This);
4976 return D3D_OK;
4980 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
4981 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4982 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4983 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p) \n", This, Handle, pNumSegs, pTriPatchInfo);
4984 FIXME("(%p) : Stub\n", This);
4985 return D3D_OK;
4988 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
4989 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4990 TRACE("(%p) Handle(%d)\n", This, Handle);
4991 FIXME("(%p) : Stub\n", This);
4992 return D3D_OK;
4995 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
4996 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
4997 fill a surface with a block of color! */
4998 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4999 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
5000 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
5001 IWineD3DSwapChainImpl *container = NULL;
5002 BOOL isRenderTarget = FALSE;
5003 unsigned int width, height;
5004 unsigned int top, left;
5005 unsigned int u, v;
5006 DWORD *data;
5007 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
5008 if (surface->resource.pool != D3DPOOL_DEFAULT) {
5009 FIXME("call to colorfill with non D3DPOOL_DEFAULT surface\n");
5010 return D3DERR_INVALIDCALL;
5013 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
5014 if (D3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
5015 if (D3DUSAGE_RENDERTARGET & surface->resource.usage) {
5016 /* TODO: make sure we set everything back to the way it was, and context management!
5017 glGetIntegerv(GL_READ_BUFFER, &prev_read);
5018 vcheckGLcall("glIntegerv");
5019 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
5020 vcheckGLcall("glIntegerv");
5022 TRACE("Color fill to render targets may cause some graphics issues\n");
5023 if (pSurface == container->frontBuffer) {
5024 glDrawBuffer(GL_FRONT);
5025 } else {
5026 glDrawBuffer(GL_BACK);
5028 } else {
5029 if (D3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
5030 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld \n", surface, surface->resource.usage);
5031 } else {
5032 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
5034 if (container != NULL) {
5035 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5037 /* we can use GL_STENCIL_INDEX etc...*/
5038 return D3D_OK;
5040 if (container != NULL) {
5041 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5043 isRenderTarget = TRUE;
5045 /* TODO: drawing to GL_FRONT and GL_BACK */
5046 /* TODO: see if things can be speeded up by using the correct
5047 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
5048 if (pRect == NULL) {
5049 top = 0;
5050 left = 0;
5051 width = surface->currentDesc.Width;
5052 height = surface->currentDesc.Height;
5053 } else {
5054 left = pRect->x1;
5055 top = pRect->y1;
5056 width = pRect->x2 - left;
5057 height = pRect->y2 - top;
5060 data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
5061 /* Create a 'line' of color color, in the correct format for the surface */
5062 for (u = 0 ; u < width ; u ++) {
5063 data[u] = color;
5066 ENTER_GL();
5067 if (isRenderTarget == FALSE) {
5068 glDescriptor *glDesc;
5069 IWineD3DSurface_PreLoad(pSurface);
5071 /* draw a block of the coloured line on the sufrace */
5072 IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
5073 for (v = 0 ; v< height;v++) {
5074 glTexSubImage2D(glDesc->target
5075 ,glDesc->level /* level */
5076 ,left
5077 ,top + v
5078 ,width
5079 ,1 /* height */
5080 ,GL_RGBA
5081 ,GL_UNSIGNED_BYTE
5082 ,data
5085 checkGLcall("glTexSubImage2D");
5086 /* clean up */
5087 glDisable(glDesc->target);
5088 } else {
5089 /** FIXME: Using GLClear may be faster **/
5090 glRasterPos2i(left, top);
5091 glPixelZoom((float)width ,(float)height);
5092 glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
5093 checkGLcall("glDrawPixels");
5095 HeapFree(GetProcessHeap(), 0, data);
5096 LEAVE_GL();
5097 return D3D_OK;
5101 /* rendertarget and deptth stencil functions */
5102 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
5103 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5105 /* FIXME: Implelent RenderTargetIndex >0 */
5106 if(RenderTargetIndex > 0)
5107 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
5109 *ppRenderTarget = (IWineD3DSurface *)This->renderTarget;
5110 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
5111 /* Note inc ref on returned surface */
5112 if(*ppRenderTarget != NULL)
5113 IWineD3DSurface_AddRef(*ppRenderTarget);
5114 return D3D_OK;
5117 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5118 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5119 *ppZStencilSurface = (IWineD3DSurface *)This->depthStencilBuffer;
5120 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
5122 if(*ppZStencilSurface != NULL) {
5123 /* Note inc ref on returned surface */
5124 IWineD3DSurface_AddRef(*ppZStencilSurface);
5126 return D3D_OK;
5129 /* internal static helper functions */
5130 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5131 IWineD3DSurface *RenderSurface);
5133 HRESULT WINAPI static IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain);
5135 HRESULT WINAPI static IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context);
5137 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5138 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5139 HRESULT hr = D3D_OK;
5140 WINED3DVIEWPORT viewport;
5142 TRACE("(%p) Swapping rendertarget\n",This);
5143 if (RenderTargetIndex > 0) {
5144 FIXME("(%p) Render targets other than the first are not supported\n",This);
5145 RenderTargetIndex = 0;
5148 /* MSDN says that null disables the render target
5149 but a device must always be associated with a render target
5150 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5152 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5153 for more details
5155 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5156 FIXME("Trying to set render target 0 to NULL\n");
5157 return D3DERR_INVALIDCALL;
5159 /* TODO: replace Impl* usage with interface usage */
5160 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & D3DUSAGE_RENDERTARGET) {
5161 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);
5162 return D3DERR_INVALIDCALL;
5164 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
5165 * builds, but I think wine counts as a 'debug' build for now.
5166 ******************************/
5167 /* If we are trying to set what we already have, don't bother */
5168 if (pRenderTarget == This->renderTarget) {
5169 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5170 } else {
5171 /* Otherwise, set the render target up */
5173 if (FALSE == This->sceneEnded) {
5174 IWineD3DDevice_EndScene(iface);
5176 TRACE("clearing renderer\n");
5177 /* IWineD3DDeviceImpl_CleanRender(iface); */
5178 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5179 depending on the renter target implementation being used.
5180 A shared context implementation will share all buffers between all rendertargets (including swapchains),
5181 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5182 stencil buffer and incure an extra memory overhead */
5183 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
5186 if (SUCCEEDED(hr)) {
5187 /* Finally, reset the viewport as the MSDN states. */
5188 /* TODO: Replace impl usage */
5189 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
5190 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
5191 viewport.X = 0;
5192 viewport.Y = 0;
5193 viewport.MaxZ = 1.0f;
5194 viewport.MinZ = 0.0f;
5195 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
5196 } else {
5197 FIXME("Unknown error setting the render target\n");
5199 This->sceneEnded = FALSE;
5200 return hr;
5203 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
5204 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5205 HRESULT hr = D3D_OK;
5206 IWineD3DSurface *tmp;
5208 TRACE("(%p) Swapping z-buffer\n",This);
5210 if (pNewZStencil == This->stencilBufferTarget) {
5211 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5212 } else {
5213 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5214 * depending on the renter target implementation being used.
5215 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5216 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5217 * stencil buffer and incure an extra memory overhead
5218 ******************************************************/
5221 tmp = This->stencilBufferTarget;
5222 This->stencilBufferTarget = pNewZStencil;
5223 /* should we be calling the parent or the wined3d surface? */
5224 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
5225 if (NULL != tmp) IWineD3DSurface_Release(tmp);
5226 hr = D3D_OK;
5227 /** TODO: glEnable/glDisable on depth/stencil depending on
5228 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
5229 **********************************************************/
5232 return hr;
5236 /* Internal functions not in DirectX */
5237 /** TODO: move this off to the opengl context manager
5238 *(the swapchain doesn't need to know anything about offscreen rendering!)
5239 ****************************************************/
5241 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
5243 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5245 TRACE("(%p), %p\n", This, swapchain);
5247 if (swapchain->win != swapchain->drawable) {
5248 /* Set everything back the way it ws */
5249 swapchain->render_ctx = swapchain->glCtx;
5250 swapchain->drawable = swapchain->win;
5252 return D3D_OK;
5254 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
5255 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
5256 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5257 int i;
5258 int width;
5259 int height;
5260 WINED3DFORMAT format;
5261 WINED3DSURFACE_DESC surfaceDesc;
5262 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5263 surfaceDesc.Width = &width;
5264 surfaceDesc.Height = &height;
5265 surfaceDesc.Format = &format;
5266 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5267 *context = NULL;
5268 /* I need a get width/height function (and should do something with the format) */
5269 for (i = 0; i < CONTEXT_CACHE; ++i) {
5270 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
5271 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
5272 the pSurface can be set to 0 allowing it to be reused from cache **/
5273 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
5274 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
5275 *context = &This->contextCache[i];
5276 break;
5278 if (This->contextCache[i].Width == 0) {
5279 This->contextCache[i].pSurface = pSurface;
5280 This->contextCache[i].Width = width;
5281 This->contextCache[i].Height = height;
5282 *context = &This->contextCache[i];
5283 break;
5286 if (i == CONTEXT_CACHE) {
5287 int minUsage = 0x7FFFFFFF; /* MAX_INT */
5288 glContext *dropContext = 0;
5289 for (i = 0; i < CONTEXT_CACHE; i++) {
5290 if (This->contextCache[i].usedcount < minUsage) {
5291 dropContext = &This->contextCache[i];
5292 minUsage = This->contextCache[i].usedcount;
5295 /* clean up the context (this doesn't work for ATI at the moment */
5296 #if 0
5297 glXDestroyContext(swapchain->display, dropContext->context);
5298 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
5299 #endif
5300 FIXME("Leak\n");
5301 dropContext->Width = 0;
5302 dropContext->pSurface = pSurface;
5303 *context = dropContext;
5304 } else {
5305 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
5306 for (i = 0; i < CONTEXT_CACHE; i++) {
5307 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
5311 if (*context != NULL)
5312 return D3D_OK;
5313 else
5314 return E_OUTOFMEMORY;
5317 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
5318 * the functionality needs splitting up so that we don't do more than we should do.
5319 * this only seems to impact performance a little.
5320 ******************************/
5321 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5322 IWineD3DSurface *RenderSurface) {
5323 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5325 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
5326 HRESULT ret = D3DERR_INVALIDCALL;
5327 IWineD3DSurface *tmp;
5329 * Currently only active for GLX >= 1.3
5330 * for others versions we'll have to use GLXPixmaps
5332 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
5333 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
5334 * so only check OpenGL version
5335 * ..........................
5336 * I don't believe that it is a problem with NVidia headers,
5337 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
5338 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
5339 * ATI Note:
5340 * Your application will report GLX version 1.2 on glXQueryVersion.
5341 * However, it is safe to call the GLX 1.3 functions as described below.
5343 #if defined(GL_VERSION_1_3)
5345 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
5346 GLXFBConfig* cfgs = NULL;
5347 int nCfgs = 0;
5348 int attribs[256];
5349 int nAttribs = 0;
5350 IWineD3DSwapChain *currentSwapchain;
5351 IWineD3DSwapChainImpl *swapchain;
5352 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
5353 * but switch them off if the StencilSurface is set to NULL
5354 ** *********************************************************/
5355 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
5356 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
5358 /**TODO:
5359 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
5360 it StencilSurface != NULL && zBufferTarget == NULL switch it on
5363 #define PUSH1(att) attribs[nAttribs++] = (att);
5364 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
5366 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
5368 /** TODO: remove the reff to Impl (context manager should fix this!) **/
5369 IWineD3DSwapChainImpl *impSwapChain;
5370 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
5371 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
5372 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
5375 ENTER_GL();
5377 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
5378 PUSH2(GLX_X_RENDERABLE, TRUE);
5379 PUSH2(GLX_DOUBLEBUFFER, TRUE);
5380 TRACE("calling makeglcfg\n");
5381 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
5382 PUSH1(None);
5384 TRACE("calling chooseFGConfig\n");
5385 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5386 attribs, &nCfgs);
5388 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
5389 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
5390 why we failed and only show this message once! */
5391 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"); /**/
5392 nAttribs = 0;
5393 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
5394 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
5395 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
5396 PUSH2(GLX_DOUBLEBUFFER, FALSE);
5397 TRACE("calling makeglcfg\n");
5398 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
5399 PUSH1(None);
5400 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5401 attribs, &nCfgs);
5404 if (NULL != cfgs) {
5405 #ifdef EXTRA_TRACES
5406 int i;
5407 for (i = 0; i < nCfgs; ++i) {
5408 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
5409 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
5410 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
5413 if (NULL != This->renderTarget) {
5414 glFlush();
5415 vcheckGLcall("glFlush");
5416 /** This is only useful if the old render target was a swapchain,
5417 * we need to supercede this with a function that displays
5418 * the current buffer on the screen. This is easy to do in glx1.3 but
5419 * we need to do copy-write pixels in glx 1.2.
5420 ************************************************/
5421 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
5423 printf("Hit Enter to get next frame ...\n");
5424 getchar();
5426 #endif
5429 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&currentSwapchain) != D3D_OK) {
5430 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
5431 IWineD3DDevice_GetSwapChain(iface, 0, &currentSwapchain);
5435 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
5436 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
5437 **********************************************************************/
5438 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == D3D_OK) {
5439 /* We also need to make sure that the lights &co are also in the context of the swapchains */
5440 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
5441 TRACE("making swapchain active\n");
5442 if (RenderSurface != This->renderTarget) {
5443 if (RenderSurface == swapchain->backBuffer) {
5444 } else {
5445 /* This could be flagged so that some operations work directly with the front buffer */
5446 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
5448 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
5449 == False) {
5450 TRACE("Error in setting current context: context %p drawable %ld !\n",
5451 impSwapChain->glCtx, impSwapChain->win);
5454 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5456 checkGLcall("glXMakeContextCurrent");
5458 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5460 else if (pbuffer_support == TRUE && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
5462 /** ********************************************************************
5463 * This is a quickly hacked out implementation of offscreen textures.
5464 * It will work in most cases but there may be problems if the client
5465 * modifies the texture directly, or expects the contents of the rendertarget
5466 * to be persistent.
5468 * There are some real speed vs compatibility issues here:
5469 * we should really use a new context for every texture, but that eats ram.
5470 * we should also be restoring the texture to the pbuffer but that eats CPU
5471 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
5472 * but if this means reusing the display backbuffer then we need to make sure that
5473 * states are correctly preserved.
5474 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
5475 * and gain a good performance increase at the cost of compatibility.
5476 * I would suggest that, when this is the case, a user configurable flag be made
5477 * available, allowing the user to choose the best emmulated experience for them.
5478 *********************************************************************/
5480 XVisualInfo *visinfo;
5481 glContext *newContext;
5483 /* Here were using a shared context model */
5484 if (D3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
5485 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5488 /* If the context doesn't exist then create a new one */
5489 /* TODO: This should really be part of findGlContext */
5490 if (NULL == newContext->context) {
5492 TRACE("making new buffer\n");
5493 nAttribs = 0;
5494 PUSH2(GLX_PBUFFER_WIDTH, newContext->Width);
5495 PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
5496 PUSH1(None);
5498 newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
5500 /** ****************************************
5501 *GLX1.3 isn't supported by XFree 'yet' untill that point ATI emulates pBuffers
5502 *they note:
5503 * In future releases, we may provide the calls glXCreateNewContext,
5504 * glXQueryDrawable and glXMakeContextCurrent.
5505 * so until then we have to use glXGetVisualFromFBConfig &co..
5506 ********************************************/
5509 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
5510 if (!visinfo) {
5511 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
5512 } else {
5513 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
5514 XFree(visinfo);
5517 if (NULL == newContext || NULL == newContext->context) {
5518 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5519 } else {
5520 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
5521 if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
5522 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
5525 /* Clean up the old context */
5526 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5527 /* Set the current context of the swapchain to the new context */
5528 impSwapChain->drawable = newContext->drawable;
5529 impSwapChain->render_ctx = newContext->context;
5533 #if 0 /* Apply the stateblock to the new context
5534 FIXME: This is a bit of a hack, each context should know it's own state,
5535 the directX current directX state should then be applied to the context */
5537 BOOL oldRecording;
5538 IWineD3DStateBlockImpl *oldUpdateStateBlock;
5539 oldUpdateStateBlock = This->updateStateBlock;
5540 oldRecording= This->isRecordingState;
5541 This->isRecordingState = FALSE;
5542 This->updateStateBlock = This->stateBlock;
5543 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
5545 This->isRecordingState = oldRecording;
5546 This->updateStateBlock = oldUpdateStateBlock;
5547 #endif
5550 /* clean up the current rendertargets swapchain (if it belonged to one) */
5551 if (currentSwapchain != NULL) {
5552 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
5555 /* Were done with the opengl context management, setup the rendertargets */
5557 tmp = This->renderTarget;
5558 This->renderTarget = RenderSurface;
5559 IWineD3DSurface_AddRef(This->renderTarget);
5560 IWineD3DSurface_Release(tmp);
5565 DWORD value;
5566 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
5567 /* Check that the container is not a swapchain member */
5569 IWineD3DSwapChain *tmpSwapChain;
5570 if (D3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
5571 This->renderUpsideDown = TRUE;
5572 }else{
5573 This->renderUpsideDown = FALSE;
5574 IWineD3DSwapChain_Release(tmpSwapChain);
5576 /* Force updating the cull mode */
5577 TRACE("setting render state\n");
5578 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
5579 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
5581 /* Force updating projection matrix */
5582 This->last_was_rhw = FALSE;
5583 This->proj_valid = FALSE;
5586 ret = D3D_OK;
5588 if (cfgs != NULL) {
5589 XFree(cfgs);
5590 } else {
5591 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
5592 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
5595 #undef PUSH1
5596 #undef PUSH2
5597 if ( NULL != impSwapChain) {
5598 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
5600 LEAVE_GL();
5602 #endif
5603 return ret;
5606 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
5607 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
5608 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5609 /* TODO: the use of Impl is deprecated. */
5610 /* some basic validation checks */
5611 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
5613 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
5615 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
5616 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
5617 return D3DERR_INVALIDCALL;
5619 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
5620 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
5621 return D3DERR_INVALIDCALL;
5623 /* TODO: make the cursor 'real' */
5625 This->xHotSpot = XHotSpot;
5626 This->yHotSpot = YHotSpot;
5628 return D3D_OK;
5631 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
5632 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5633 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
5635 This->xScreenSpace = XScreenSpace;
5636 This->yScreenSpace = YScreenSpace;
5638 return;
5642 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
5643 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5644 TRACE("(%p) : visible(%d)\n", This, bShow);
5646 This->bCursorVisible = bShow;
5648 return D3D_OK;
5651 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
5652 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5653 FIXME("(%p) : stub\n", This); /* No way of notifying yet! */
5654 return D3D_OK;
5658 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
5659 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5660 /** FIXME: Resource tracking needs to be done,
5661 * The closes we can do to this is set the priorities of all managed textures low
5662 * and then reset them.
5663 ***********************************************************/
5664 FIXME("(%p) : stub\n", This);
5665 return D3D_OK;
5668 HRESULT WINAPI IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
5669 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5670 /** FIXME: Resource trascking needs to be done.
5671 * in effect this pulls all non only default
5672 * textures out of video memory and deletes all glTextures (glDeleteTextures)
5673 * and should clear down the context and set it up according to pPresentationParameters
5674 ***********************************************************/
5675 FIXME("(%p) : stub\n", This);
5676 return D3D_OK;
5679 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
5680 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5681 /** FIXME: always true at the moment **/
5682 if(bEnableDialogs == FALSE) {
5683 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
5685 return D3D_OK;
5689 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
5690 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5692 FIXME("(%p) : stub\n", This);
5693 /* Setup some reasonable defaults */
5694 pParameters->AdapterOrdinal = 0; /* always for now */
5695 pParameters->DeviceType = D3DDEVTYPE_HAL; /* always for now */
5696 pParameters->hFocusWindow = 0;
5697 pParameters->BehaviorFlags =0;
5698 return D3D_OK;
5701 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
5702 IWineD3DSwapChain *swapchain;
5703 HRESULT hrc = D3D_OK;
5705 TRACE("Relaying to swapchain\n");
5707 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
5708 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (D3DGAMMARAMP *)pRamp);
5709 IWineD3DSwapChain_Release(swapchain);
5711 return;
5714 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
5715 IWineD3DSwapChain *swapchain;
5716 HRESULT hrc = D3D_OK;
5718 TRACE("Relaying to swapchain\n");
5720 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
5721 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
5722 IWineD3DSwapChain_Release(swapchain);
5724 return;
5727 /**********************************************************
5728 * IWineD3DDevice VTbl follows
5729 **********************************************************/
5731 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
5733 /*** IUnknown methods ***/
5734 IWineD3DDeviceImpl_QueryInterface,
5735 IWineD3DDeviceImpl_AddRef,
5736 IWineD3DDeviceImpl_Release,
5737 /*** IWineD3DDevice methods ***/
5738 IWineD3DDeviceImpl_GetParent,
5739 /*** Creation methods**/
5740 IWineD3DDeviceImpl_CreateVertexBuffer,
5741 IWineD3DDeviceImpl_CreateIndexBuffer,
5742 IWineD3DDeviceImpl_CreateStateBlock,
5743 IWineD3DDeviceImpl_CreateSurface,
5744 IWineD3DDeviceImpl_CreateTexture,
5745 IWineD3DDeviceImpl_CreateVolumeTexture,
5746 IWineD3DDeviceImpl_CreateVolume,
5747 IWineD3DDeviceImpl_CreateCubeTexture,
5748 IWineD3DDeviceImpl_CreateQuery,
5749 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
5750 IWineD3DDeviceImpl_CreateVertexDeclaration,
5751 IWineD3DDeviceImpl_CreateVertexShader,
5752 IWineD3DDeviceImpl_CreatePixelShader,
5754 /*** Odd functions **/
5755 IWineD3DDeviceImpl_EvictManagedResources,
5756 IWineD3DDeviceImpl_GetAvailableTextureMem,
5757 IWineD3DDeviceImpl_GetBackBuffer,
5758 IWineD3DDeviceImpl_GetCreationParameters,
5759 IWineD3DDeviceImpl_GetDeviceCaps,
5760 IWineD3DDeviceImpl_GetDirect3D,
5761 IWineD3DDeviceImpl_GetDisplayMode,
5762 IWineD3DDeviceImpl_GetNumberOfSwapChains,
5763 IWineD3DDeviceImpl_GetRasterStatus,
5764 IWineD3DDeviceImpl_GetSwapChain,
5765 IWineD3DDeviceImpl_Reset,
5766 IWineD3DDeviceImpl_SetDialogBoxMode,
5767 IWineD3DDeviceImpl_SetCursorProperties,
5768 IWineD3DDeviceImpl_SetCursorPosition,
5769 IWineD3DDeviceImpl_ShowCursor,
5770 IWineD3DDeviceImpl_TestCooperativeLevel,
5771 /*** Getters and setters **/
5772 IWineD3DDeviceImpl_SetClipPlane,
5773 IWineD3DDeviceImpl_GetClipPlane,
5774 IWineD3DDeviceImpl_SetClipStatus,
5775 IWineD3DDeviceImpl_GetClipStatus,
5776 IWineD3DDeviceImpl_SetCurrentTexturePalette,
5777 IWineD3DDeviceImpl_GetCurrentTexturePalette,
5778 IWineD3DDeviceImpl_SetDepthStencilSurface,
5779 IWineD3DDeviceImpl_GetDepthStencilSurface,
5780 IWineD3DDeviceImpl_SetFVF,
5781 IWineD3DDeviceImpl_GetFVF,
5782 IWineD3DDeviceImpl_SetGammaRamp,
5783 IWineD3DDeviceImpl_GetGammaRamp,
5784 IWineD3DDeviceImpl_SetIndices,
5785 IWineD3DDeviceImpl_GetIndices,
5786 IWineD3DDeviceImpl_SetLight,
5787 IWineD3DDeviceImpl_GetLight,
5788 IWineD3DDeviceImpl_SetLightEnable,
5789 IWineD3DDeviceImpl_GetLightEnable,
5790 IWineD3DDeviceImpl_SetMaterial,
5791 IWineD3DDeviceImpl_GetMaterial,
5792 IWineD3DDeviceImpl_SetNPatchMode,
5793 IWineD3DDeviceImpl_GetNPatchMode,
5794 IWineD3DDeviceImpl_SetPaletteEntries,
5795 IWineD3DDeviceImpl_GetPaletteEntries,
5796 IWineD3DDeviceImpl_SetPixelShader,
5797 IWineD3DDeviceImpl_GetPixelShader,
5798 IWineD3DDeviceImpl_SetPixelShaderConstantB,
5799 IWineD3DDeviceImpl_GetPixelShaderConstantB,
5800 IWineD3DDeviceImpl_SetPixelShaderConstantI,
5801 IWineD3DDeviceImpl_GetPixelShaderConstantI,
5802 IWineD3DDeviceImpl_SetPixelShaderConstantF,
5803 IWineD3DDeviceImpl_GetPixelShaderConstantF,
5804 IWineD3DDeviceImpl_SetRenderState,
5805 IWineD3DDeviceImpl_GetRenderState,
5806 IWineD3DDeviceImpl_SetRenderTarget,
5807 IWineD3DDeviceImpl_GetRenderTarget,
5808 IWineD3DDeviceImpl_SetSamplerState,
5809 IWineD3DDeviceImpl_GetSamplerState,
5810 IWineD3DDeviceImpl_SetScissorRect,
5811 IWineD3DDeviceImpl_GetScissorRect,
5812 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
5813 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
5814 IWineD3DDeviceImpl_SetStreamSource,
5815 IWineD3DDeviceImpl_GetStreamSource,
5816 IWineD3DDeviceImpl_SetStreamSourceFreq,
5817 IWineD3DDeviceImpl_GetStreamSourceFreq,
5818 IWineD3DDeviceImpl_SetTexture,
5819 IWineD3DDeviceImpl_GetTexture,
5820 IWineD3DDeviceImpl_SetTextureStageState,
5821 IWineD3DDeviceImpl_GetTextureStageState,
5822 IWineD3DDeviceImpl_SetTransform,
5823 IWineD3DDeviceImpl_GetTransform,
5824 IWineD3DDeviceImpl_SetVertexDeclaration,
5825 IWineD3DDeviceImpl_GetVertexDeclaration,
5826 IWineD3DDeviceImpl_SetVertexShader,
5827 IWineD3DDeviceImpl_GetVertexShader,
5828 IWineD3DDeviceImpl_SetVertexShaderConstantB,
5829 IWineD3DDeviceImpl_GetVertexShaderConstantB,
5830 IWineD3DDeviceImpl_SetVertexShaderConstantI,
5831 IWineD3DDeviceImpl_GetVertexShaderConstantI,
5832 IWineD3DDeviceImpl_SetVertexShaderConstantF,
5833 IWineD3DDeviceImpl_GetVertexShaderConstantF,
5834 IWineD3DDeviceImpl_SetViewport,
5835 IWineD3DDeviceImpl_GetViewport,
5836 IWineD3DDeviceImpl_MultiplyTransform,
5837 IWineD3DDeviceImpl_ValidateDevice,
5838 IWineD3DDeviceImpl_ProcessVertices,
5839 /*** State block ***/
5840 IWineD3DDeviceImpl_BeginStateBlock,
5841 IWineD3DDeviceImpl_EndStateBlock,
5842 /*** Scene management ***/
5843 IWineD3DDeviceImpl_BeginScene,
5844 IWineD3DDeviceImpl_EndScene,
5845 IWineD3DDeviceImpl_Present,
5846 IWineD3DDeviceImpl_Clear,
5847 /*** Drawing ***/
5848 IWineD3DDeviceImpl_DrawPrimitive,
5849 IWineD3DDeviceImpl_DrawIndexedPrimitive,
5850 IWineD3DDeviceImpl_DrawPrimitiveUP,
5851 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
5852 IWineD3DDeviceImpl_DrawRectPatch,
5853 IWineD3DDeviceImpl_DrawTriPatch,
5854 IWineD3DDeviceImpl_DeletePatch,
5855 IWineD3DDeviceImpl_ColorFill,
5856 IWineD3DDeviceImpl_UpdateTexture,
5857 IWineD3DDeviceImpl_UpdateSurface,
5858 IWineD3DDeviceImpl_StretchRect,
5859 IWineD3DDeviceImpl_GetRenderTargetData,
5860 IWineD3DDeviceImpl_GetFrontBufferData,
5861 /*** Internal use IWineD3DDevice methods ***/
5862 IWineD3DDeviceImpl_SetupTextureStates
5866 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
5867 WINED3DRS_ALPHABLENDENABLE ,
5868 WINED3DRS_ALPHAFUNC ,
5869 WINED3DRS_ALPHAREF ,
5870 WINED3DRS_ALPHATESTENABLE ,
5871 WINED3DRS_BLENDOP ,
5872 WINED3DRS_COLORWRITEENABLE ,
5873 WINED3DRS_DESTBLEND ,
5874 WINED3DRS_DITHERENABLE ,
5875 WINED3DRS_FILLMODE ,
5876 WINED3DRS_FOGDENSITY ,
5877 WINED3DRS_FOGEND ,
5878 WINED3DRS_FOGSTART ,
5879 WINED3DRS_LASTPIXEL ,
5880 WINED3DRS_SHADEMODE ,
5881 WINED3DRS_SRCBLEND ,
5882 WINED3DRS_STENCILENABLE ,
5883 WINED3DRS_STENCILFAIL ,
5884 WINED3DRS_STENCILFUNC ,
5885 WINED3DRS_STENCILMASK ,
5886 WINED3DRS_STENCILPASS ,
5887 WINED3DRS_STENCILREF ,
5888 WINED3DRS_STENCILWRITEMASK ,
5889 WINED3DRS_STENCILZFAIL ,
5890 WINED3DRS_TEXTUREFACTOR ,
5891 WINED3DRS_WRAP0 ,
5892 WINED3DRS_WRAP1 ,
5893 WINED3DRS_WRAP2 ,
5894 WINED3DRS_WRAP3 ,
5895 WINED3DRS_WRAP4 ,
5896 WINED3DRS_WRAP5 ,
5897 WINED3DRS_WRAP6 ,
5898 WINED3DRS_WRAP7 ,
5899 WINED3DRS_ZENABLE ,
5900 WINED3DRS_ZFUNC ,
5901 WINED3DRS_ZWRITEENABLE
5904 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
5905 WINED3DTSS_ADDRESSW ,
5906 WINED3DTSS_ALPHAARG0 ,
5907 WINED3DTSS_ALPHAARG1 ,
5908 WINED3DTSS_ALPHAARG2 ,
5909 WINED3DTSS_ALPHAOP ,
5910 WINED3DTSS_BUMPENVLOFFSET ,
5911 WINED3DTSS_BUMPENVLSCALE ,
5912 WINED3DTSS_BUMPENVMAT00 ,
5913 WINED3DTSS_BUMPENVMAT01 ,
5914 WINED3DTSS_BUMPENVMAT10 ,
5915 WINED3DTSS_BUMPENVMAT11 ,
5916 WINED3DTSS_COLORARG0 ,
5917 WINED3DTSS_COLORARG1 ,
5918 WINED3DTSS_COLORARG2 ,
5919 WINED3DTSS_COLOROP ,
5920 WINED3DTSS_RESULTARG ,
5921 WINED3DTSS_TEXCOORDINDEX ,
5922 WINED3DTSS_TEXTURETRANSFORMFLAGS
5925 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
5926 WINED3DSAMP_ADDRESSU ,
5927 WINED3DSAMP_ADDRESSV ,
5928 WINED3DSAMP_ADDRESSW ,
5929 WINED3DSAMP_BORDERCOLOR ,
5930 WINED3DSAMP_MAGFILTER ,
5931 WINED3DSAMP_MINFILTER ,
5932 WINED3DSAMP_MIPFILTER ,
5933 WINED3DSAMP_MIPMAPLODBIAS ,
5934 WINED3DSAMP_MAXMIPLEVEL ,
5935 WINED3DSAMP_MAXANISOTROPY ,
5936 WINED3DSAMP_SRGBTEXTURE ,
5937 WINED3DSAMP_ELEMENTINDEX
5940 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
5941 WINED3DRS_AMBIENT ,
5942 WINED3DRS_AMBIENTMATERIALSOURCE ,
5943 WINED3DRS_CLIPPING ,
5944 WINED3DRS_CLIPPLANEENABLE ,
5945 WINED3DRS_COLORVERTEX ,
5946 WINED3DRS_DIFFUSEMATERIALSOURCE ,
5947 WINED3DRS_EMISSIVEMATERIALSOURCE ,
5948 WINED3DRS_FOGDENSITY ,
5949 WINED3DRS_FOGEND ,
5950 WINED3DRS_FOGSTART ,
5951 WINED3DRS_FOGTABLEMODE ,
5952 WINED3DRS_FOGVERTEXMODE ,
5953 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
5954 WINED3DRS_LIGHTING ,
5955 WINED3DRS_LOCALVIEWER ,
5956 WINED3DRS_MULTISAMPLEANTIALIAS ,
5957 WINED3DRS_MULTISAMPLEMASK ,
5958 WINED3DRS_NORMALIZENORMALS ,
5959 WINED3DRS_PATCHEDGESTYLE ,
5960 WINED3DRS_POINTSCALE_A ,
5961 WINED3DRS_POINTSCALE_B ,
5962 WINED3DRS_POINTSCALE_C ,
5963 WINED3DRS_POINTSCALEENABLE ,
5964 WINED3DRS_POINTSIZE ,
5965 WINED3DRS_POINTSIZE_MAX ,
5966 WINED3DRS_POINTSIZE_MIN ,
5967 WINED3DRS_POINTSPRITEENABLE ,
5968 WINED3DRS_RANGEFOGENABLE ,
5969 WINED3DRS_SPECULARMATERIALSOURCE ,
5970 WINED3DRS_TWEENFACTOR ,
5971 WINED3DRS_VERTEXBLEND
5974 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
5975 WINED3DTSS_TEXCOORDINDEX ,
5976 WINED3DTSS_TEXTURETRANSFORMFLAGS
5979 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
5980 WINED3DSAMP_DMAPOFFSET