Add support for vertex shader constants to the stateblock.
[wine/gsoc_dplay.git] / dlls / wined3d / device.c
blob17fe5cd37acb81c03aa37662ab7ebe59e3b62346
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 = FALSE;
59 /* allocate one pbuffer per surface */
60 BOOL pbuffer_per_surface = FALSE;
62 /* static function declarations */
63 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
65 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type);
67 /* helper macros */
68 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return D3DERR_OUTOFVIDEOMEMORY;}
70 #define D3DCREATEOBJECTINSTANCE(object, type) { \
71 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
72 D3DMEMCHECK(object, pp##type); \
73 object->lpVtbl = &IWineD3D##type##_Vtbl; \
74 object->wineD3DDevice = This; \
75 object->parent = parent; \
76 object->ref = 1; \
77 *pp##type = (IWineD3D##type *) object; \
80 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
81 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
82 D3DMEMCHECK(object, pp##type); \
83 object->lpVtbl = &IWineD3D##type##_Vtbl; \
84 object->resource.wineD3DDevice = This; \
85 object->resource.parent = parent; \
86 object->resource.resourceType = d3dtype; \
87 object->resource.ref = 1; \
88 object->resource.pool = Pool; \
89 object->resource.format = Format; \
90 object->resource.usage = Usage; \
91 object->resource.size = _size; \
92 /* Check that we have enough video ram left */ \
93 if (Pool == D3DPOOL_DEFAULT) { \
94 if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
95 WARN("Out of 'bogus' video memory\n"); \
96 HeapFree(GetProcessHeap(), 0, object); \
97 *pp##type = NULL; \
98 return D3DERR_OUTOFVIDEOMEMORY; \
99 } \
100 globalChangeGlRam(_size); \
102 object->resource.allocatedMemory = (0 == _size ? NULL : Pool == D3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
103 if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != D3DPOOL_DEFAULT) { \
104 FIXME("Out of memory!\n"); \
105 HeapFree(GetProcessHeap(), 0, object); \
106 *pp##type = NULL; \
107 return D3DERR_OUTOFVIDEOMEMORY; \
109 *pp##type = (IWineD3D##type *) object; \
110 IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
111 TRACE("(%p) : Created resource %p\n", This, object); \
114 #define D3DINITILIZEBASETEXTURE(_basetexture) { \
115 _basetexture.levels = Levels; \
116 _basetexture.filterType = (Usage & D3DUSAGE_AUTOGENMIPMAP) ? D3DTEXF_LINEAR : D3DTEXF_NONE; \
117 _basetexture.LOD = 0; \
118 _basetexture.dirty = TRUE; \
121 /**********************************************************
122 * Global variable / Constants follow
123 **********************************************************/
124 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
126 /**********************************************************
127 * Utility functions follow
128 **********************************************************/
129 /* Convert the D3DLIGHT properties into equivalent gl lights */
130 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
132 float quad_att;
133 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
134 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
136 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
137 glMatrixMode(GL_MODELVIEW);
138 glPushMatrix();
139 glLoadMatrixf((float *)&This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
141 /* Diffuse: */
142 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
143 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
144 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
145 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
146 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
147 checkGLcall("glLightfv");
149 /* Specular */
150 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
151 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
152 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
153 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
154 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
155 checkGLcall("glLightfv");
157 /* Ambient */
158 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
159 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
160 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
161 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
162 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
163 checkGLcall("glLightfv");
165 /* Attenuation - Are these right? guessing... */
166 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
167 checkGLcall("glLightf");
168 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
169 checkGLcall("glLightf");
171 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) != 0) {
172 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
173 } else {
174 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
177 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
178 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
179 checkGLcall("glLightf");
181 switch (lightInfo->OriginalParms.Type) {
182 case D3DLIGHT_POINT:
183 /* Position */
184 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
185 checkGLcall("glLightfv");
186 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
187 checkGLcall("glLightf");
188 /* FIXME: Range */
189 break;
191 case D3DLIGHT_SPOT:
192 /* Position */
193 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
194 checkGLcall("glLightfv");
195 /* Direction */
196 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
197 checkGLcall("glLightfv");
198 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
199 checkGLcall("glLightf");
200 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
201 checkGLcall("glLightf");
202 /* FIXME: Range */
203 break;
205 case D3DLIGHT_DIRECTIONAL:
206 /* Direction */
207 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
208 checkGLcall("glLightfv");
209 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
210 checkGLcall("glLightf");
211 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
212 checkGLcall("glLightf");
213 break;
215 default:
216 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
219 /* Restore the modelview matrix */
220 glPopMatrix();
223 /* Apply the current values to the specified texture stage */
224 void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Sampler, DWORD Flags) {
225 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
226 float col[4];
228 union {
229 float f;
230 DWORD d;
231 } tmpvalue;
233 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
234 clamping, MIPLOD, etc. This will work for up to 16 samplers.
237 if (Sampler >= GL_LIMITS(samplers)) {
238 FIXME("Trying to set the state of more samplers %ld than are supported %d by this openGL implementation\n", Sampler, GL_LIMITS(samplers));
239 return;
241 VTRACE(("Activating appropriate texture state %ld\n", Sampler));
242 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
243 ENTER_GL();
244 GLACTIVETEXTURE(Sampler);
245 LEAVE_GL();
246 /* Could we use bindTexture and then apply the states instead of GLACTIVETEXTURE */
247 } else if (Sampler > 0) {
248 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
249 return;
252 /* TODO: change this to a lookup table
253 LOOKUP_TEXTURE_STATES lists all texture states that should be applied.
254 LOOKUP_CONTEXT_SATES list all context applicable states that can be applied
255 etc.... it's a lot cleaner, quicker and possibly easier to maintain than running a switch and setting a skip flag...
256 especially when there are a number of groups of states. */
258 TRACE("-----------------------> Updating the texture at Sampler %ld to have new texture state information\n", Sampler);
260 /* The list of states not to apply is a big as the list of states to apply, so it makes sense to produce an inclusive list */
261 #define APPLY_STATE(_state) IWineD3DDeviceImpl_ApplyTextureUnitState(iface, Sampler, _state)
262 /* these are the only two supported states that need to be applied */
263 APPLY_STATE(WINED3DTSS_TEXCOORDINDEX);
264 APPLY_STATE(WINED3DTSS_TEXTURETRANSFORMFLAGS);
265 #if 0 /* not supported at the moment */
266 APPLY_STATE(WINED3DTSS_BUMPENVMAT00);
267 APPLY_STATE(WINED3DTSS_BUMPENVMAT01);
268 APPLY_STATE(WINED3DTSS_BUMPENVMAT10);
269 APPLY_STATE(WINED3DTSS_BUMPENVMAT11);
270 APPLY_STATE(WINED3DTSS_BUMPENVLSCALE);
271 APPLY_STATE(WINED3DTSS_BUMPENVLOFFSET);
272 APPLY_STATE(WINED3DTSS_RESULTARG);
273 APPLY_STATE(WINED3DTSS_CONSTANT);
274 #endif
275 /* a quick sanity check in case someone forgot to update this function */
276 if (WINED3D_HIGHEST_TEXTURE_STATE > WINED3DTSS_CONSTANT) {
277 FIXME("(%p) : There are more texture states than expected, update device.c to match\n", This);
279 #undef APPLY_STATE
281 /* apply any sampler states that always need applying */
282 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
283 tmpvalue.d = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPMAPLODBIAS];
284 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
285 GL_TEXTURE_LOD_BIAS_EXT,
286 tmpvalue.f);
287 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
290 /* Note the D3DRS value applies to all textures, but GL has one
291 * per texture, so apply it now ready to be used!
293 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
294 /* Set the default alpha blend color */
295 glBlendColor(col[0], col[1], col[2], col[3]);
296 checkGLcall("glBlendColor");
298 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
299 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
300 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
302 TRACE("-----------------------> Updated the texture at Sampler %ld to have new texture state information\n", Sampler);
305 /**********************************************************
306 * IUnknown parts follows
307 **********************************************************/
309 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
311 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
312 /* FIXME: This needs to extend an IWineD3DBaseObject */
314 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
315 if (IsEqualGUID(riid, &IID_IUnknown)
316 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
317 IUnknown_AddRef(iface);
318 *ppobj = This;
319 return D3D_OK;
322 return E_NOINTERFACE;
325 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
326 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
327 ULONG refCount = InterlockedIncrement(&This->ref);
329 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
330 return refCount;
333 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
334 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
335 ULONG refCount = InterlockedDecrement(&This->ref);
337 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
339 if (!refCount) {
340 /* TODO: Clean up all the surfaces and textures! */
341 /* FIXME: Create targets and state blocks in d3d8 */
342 if (((IWineD3DImpl *)This->wineD3D)->dxVersion > 8) { /*We don't create a state block in d3d8 yet*/
343 /* NOTE: You must release the parent if the object was created via a callback
344 ** ***************************/
345 IUnknown* swapChainParent;
347 /* NOTE: Don't release swapchain 0 here, it's 'special' */
348 SwapChainList *nextSwapchain = This->swapchains;
349 if (nextSwapchain != NULL) {
350 nextSwapchain = nextSwapchain->next;
351 } else {
352 WARN("Expected to find the implicit swapchain\n");
355 /* release all the other swapchains */
356 while (nextSwapchain != NULL) {
357 SwapChainList *prevSwapchain = nextSwapchain;
358 nextSwapchain = nextSwapchain->next;
359 IWineD3DSwapChain_Release(prevSwapchain->swapchain);
360 /* NOTE: no need to free the list element, it will be done by the release callback
361 HeapFree(GetProcessHeap(), 0, prevSwapchain); */
364 if (This->stateBlock != NULL) {
365 IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->stateBlock);
368 if (This->swapchains != NULL) {
369 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
370 IWineD3DSwapChain_GetParent(This->swapchains->swapchain, &swapChainParent);
371 IUnknown_Release(swapChainParent); /* once for the get parent */
372 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
373 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
378 IWineD3D_Release(This->wineD3D);
379 HeapFree(GetProcessHeap(), 0, This);
381 return refCount;
384 /**********************************************************
385 * IWineD3DDevice implementation follows
386 **********************************************************/
387 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
388 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
389 *pParent = This->parent;
390 IUnknown_AddRef(This->parent);
391 return D3D_OK;
394 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
395 DWORD FVF, D3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
396 IUnknown *parent) {
397 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
398 IWineD3DVertexBufferImpl *object;
399 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
400 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, D3DRTYPE_VERTEXBUFFER, Size)
402 /*TODO: use VBO's */
403 if (Pool == D3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
404 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
406 object->fvf = FVF;
408 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
409 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
411 return D3D_OK;
414 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
415 WINED3DFORMAT Format, D3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
416 HANDLE *sharedHandle, IUnknown *parent) {
417 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
418 IWineD3DIndexBufferImpl *object;
419 TRACE("(%p) Creating index buffer\n", This);
421 /* Allocate the storage for the device */
422 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,D3DRTYPE_INDEXBUFFER, Length)
424 /*TODO: use VBO's */
425 if (Pool == D3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
426 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
429 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
430 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
431 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
433 return D3D_OK;
436 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
438 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
439 IWineD3DStateBlockImpl *object;
440 int i;
442 D3DCREATEOBJECTINSTANCE(object, StateBlock)
443 object->blockType = Type;
445 /* Special case - Used during initialization to produce a placeholder stateblock
446 so other functions called can update a state block */
447 if (Type == WINED3DSBT_INIT) {
448 /* Don't bother increasing the reference count otherwise a device will never
449 be freed due to circular dependencies */
450 return D3D_OK;
453 /* Otherwise, might as well set the whole state block to the appropriate values */
454 IWineD3DDevice_AddRef(iface);
455 /* Otherwise, might as well set the whole state block to the appropriate values */
456 if ( This->stateBlock != NULL) {
457 memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
458 } else {
459 memset(object->streamFreq, 1, sizeof(object->streamFreq));
462 /* Reset the ref and type after kludging it */
463 object->wineD3DDevice = This;
464 object->ref = 1;
465 object->blockType = Type;
467 TRACE("Updating changed flags appropriate for type %d\n", Type);
469 if (Type == WINED3DSBT_ALL) {
470 TRACE("ALL => Pretend everything has changed\n");
471 memset(&object->changed, TRUE, sizeof(This->stateBlock->changed));
472 } else if (Type == WINED3DSBT_PIXELSTATE) {
474 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
475 /* TODO: Pixel Shader Constants */
476 object->changed.pixelShader = TRUE;
477 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
478 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
481 } else if (Type == WINED3DSBT_VERTEXSTATE) {
483 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
484 /* TODO: Vertex Shader Constants */
485 object->changed.vertexShader = TRUE;
486 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
487 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
490 /* Duplicate light chain */
492 PLIGHTINFOEL *src = NULL;
493 PLIGHTINFOEL *dst = NULL;
494 PLIGHTINFOEL *newEl = NULL;
495 src = This->stateBlock->lights;
496 object->lights = NULL;
499 while (src) {
500 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
501 if (newEl == NULL) return D3DERR_OUTOFVIDEOMEMORY;
502 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
503 newEl->prev = dst;
504 newEl->changed = TRUE;
505 newEl->enabledChanged = TRUE;
506 if (dst == NULL) {
507 object->lights = newEl;
508 } else {
509 dst->next = newEl;
511 dst = newEl;
512 src = src->next;
517 } else {
518 FIXME("Unrecognized state block type %d\n", Type);
521 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
522 return D3D_OK;
526 /* ************************************
527 MSDN:
528 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
530 Discard
531 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
533 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.
535 ******************************** */
537 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) {
538 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
539 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
540 unsigned int pow2Width, pow2Height;
541 unsigned int Size = 1;
542 TRACE("(%p) Create surface\n",This);
544 /** FIXME: Check ranges on the inputs are valid
545 * MSDN
546 * MultisampleQuality
547 * [in] Quality level. The valid range is between zero and one less than the level
548 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
549 * Passing a larger value returns the error D3DERR_INVALIDCALL. The MultisampleQuality
550 * values of paired render targets, depth stencil surfaces, and the MultiSample type
551 * must all match.
552 *******************************/
556 * TODO: Discard MSDN
557 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
559 * If this flag is set, the contents of the depth stencil buffer will be
560 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
561 * with a different depth surface.
563 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
564 ***************************/
566 if(MultisampleQuality < 0) {
567 FIXME("Invalid multisample level %ld \n", MultisampleQuality);
568 return D3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
571 if(MultisampleQuality > 0) {
572 FIXME("MultisampleQuality set to %ld, substituting 0 \n" , MultisampleQuality);
573 MultisampleQuality=0;
576 /** FIXME: Check that the format is supported
577 * by the device.
578 *******************************/
579 /* TODO: add support for dxt2 and dxt4 formats */
580 if (Format == D3DFMT_DXT2 || Format == D3DFMT_DXT4) return D3DERR_NOTAVAILABLE;
582 /* Non-power2 support */
584 /* Find the nearest pow2 match */
585 pow2Width = pow2Height = 1;
586 while (pow2Width < Width) pow2Width <<= 1;
587 while (pow2Height < Height) pow2Height <<= 1;
589 if (pow2Width > Width || pow2Height > Height) {
590 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
591 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
592 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
593 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d) \n",
594 This, Width, Height);
595 return D3DERR_NOTAVAILABLE;
599 /** Check against the maximum texture sizes supported by the video card **/
600 if (pow2Width > GL_LIMITS(texture_size) || pow2Height > GL_LIMITS(texture_size)) {
601 /* one of three options
602 1: Do the same as we do with nonpow 2 and scale the texture, (any texture ops would require the texture to be scaled which is potentially slow)
603 2: Set the texture to the maxium size (bad idea)
604 3: WARN and return D3DERR_NOTAVAILABLE;
606 WARN("(%p) Application requested a surface w %d, h %d, but the graphics card only supports %d\n", This, Width, Height, GL_LIMITS(texture_size));
607 return D3DERR_NOTAVAILABLE;
612 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
613 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
614 * space!
615 *********************************/
616 if (Format == WINED3DFMT_DXT1) {
617 /* DXT1 is half byte per pixel */
618 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4)) >> 1;
620 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
621 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
622 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4));
623 } else {
624 Size = (pow2Width * D3DFmtGetBpp(This, Format)) * pow2Height;
627 /** Create the and initilise surface resource **/
628 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,D3DRTYPE_SURFACE, Size)
629 object->container = (IUnknown*) This;
631 object->currentDesc.Width = Width;
632 object->currentDesc.Height = Height;
633 object->currentDesc.MultiSampleType = MultiSample;
634 object->currentDesc.MultiSampleQuality = MultisampleQuality;
636 /* Setup some glformat defaults */
637 object->glDescription.glFormat = D3DFmt2GLFmt(This, object->resource.format);
638 object->glDescription.glFormatInternal = D3DFmt2GLIntFmt(This, object->resource.format);
639 object->glDescription.glType = D3DFmt2GLType(This, object->resource.format);
640 object->glDescription.textureName = 0;
641 object->glDescription.level = Level;
642 object->glDescription.target = GL_TEXTURE_2D;
644 /* Internal data */
645 object->pow2Width = pow2Width;
646 object->pow2Height = pow2Height;
647 object->nonpow2 = (pow2Width != Width || pow2Height != Height) ? TRUE : FALSE;
648 object->discard = Discard;
649 object->activeLock = FALSE;
650 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
651 object->pow2Size = (pow2Width * object->bytesPerPixel) * pow2Height;
653 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
655 TRACE("Pool %d %d %d %d",Pool, D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM);
657 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
658 * this function is too deap to need to care about things like this.
659 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
660 * ****************************************/
661 switch(Pool) {
662 case D3DPOOL_SCRATCH:
663 if(Lockable == FALSE)
664 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
665 which are mutually exclusive, setting lockable to true\n");
666 Lockable = TRUE;
667 break;
668 case D3DPOOL_SYSTEMMEM:
669 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
670 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
671 case D3DPOOL_MANAGED:
672 if(Usage == D3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
673 Usage of DYNAMIC which are mutually exclusive, not doing \
674 anything just telling you.\n");
675 break;
676 case D3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
677 if(!(Usage & D3DUSAGE_DYNAMIC) && !(Usage & D3DUSAGE_RENDERTARGET)
678 && !(Usage && D3DUSAGE_DEPTHSTENCIL ) && Lockable == TRUE)
679 FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
680 break;
681 default:
682 FIXME("(%p) Unknown pool %d\n", This, Pool);
683 break;
686 if (Usage & D3DUSAGE_RENDERTARGET && Pool != D3DPOOL_DEFAULT) {
687 FIXME("Trying to create a render target that isn't in the default pool\n");
691 object->locked = FALSE;
692 object->lockable = (WINED3DFMT_D16_LOCKABLE == Format) ? TRUE : Lockable;
694 /* mark the texture as dirty so that it get's loaded first time around*/
695 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
696 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
697 This, Width, Height, Format, debug_d3dformat(Format),
698 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
699 return D3D_OK;
703 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
704 DWORD Usage, WINED3DFORMAT Format, D3DPOOL Pool,
705 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
706 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
708 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
709 IWineD3DTextureImpl *object;
710 unsigned int i;
711 UINT tmpW;
712 UINT tmpH;
713 HRESULT hr;
714 unsigned int pow2Width = Width;
715 unsigned int pow2Height = Height;
718 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) .... \n", This, Width, Height, Levels, Usage);
720 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, D3DRTYPE_TEXTURE, 0);
721 D3DINITILIZEBASETEXTURE(object->baseTexture);
722 object->width = Width;
723 object->height = Height;
725 /** Non-power2 support **/
726 /* Find the nearest pow2 match */
727 pow2Width = pow2Height = 1;
728 while (pow2Width < Width) pow2Width <<= 1;
729 while (pow2Height < Height) pow2Height <<= 1;
731 /** FIXME: add support for real non-power-two if it's provided by the video card **/
732 /* Precalculated scaling for 'faked' non power of two texture coords */
733 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
734 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
735 TRACE(" xf(%f) yf(%f) \n", object->pow2scalingFactorX, object->pow2scalingFactorY);
737 /* Calculate levels for mip mapping */
738 if (Levels == 0) {
739 TRACE("calculating levels %d\n", object->baseTexture.levels);
740 object->baseTexture.levels++;
741 tmpW = Width;
742 tmpH = Height;
743 while (tmpW > 1 && tmpH > 1) {
744 tmpW = max(1, tmpW >> 1);
745 tmpH = max(1, tmpH >> 1);
746 object->baseTexture.levels++;
748 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
751 /* Generate all the surfaces */
752 tmpW = Width;
753 tmpH = Height;
754 for (i = 0; i < object->baseTexture.levels; i++)
756 /* use the callback to create the texture surface */
757 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
758 if(hr!= D3D_OK) {
759 int j;
760 FIXME("Failed to create surface %p \n",object);
761 /* clean up */
762 for(j = 0 ; j < i ; j++) {
763 IWineD3DSurface_Release(object->surfaces[j]);
765 /* heap free object */
766 HeapFree(GetProcessHeap(),0,object);
768 *ppTexture = NULL;
769 return hr;
772 IWineD3DSurface_SetContainer(object->surfaces[i], (IUnknown *)object);
773 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
774 /* calculate the next mipmap level */
775 tmpW = max(1, tmpW >> 1);
776 tmpH = max(1, tmpH >> 1);
779 TRACE("(%p) : Created texture %p\n", This, object);
780 return D3D_OK;
783 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
784 UINT Width, UINT Height, UINT Depth,
785 UINT Levels, DWORD Usage,
786 WINED3DFORMAT Format, D3DPOOL Pool,
787 IWineD3DVolumeTexture** ppVolumeTexture,
788 HANDLE* pSharedHandle, IUnknown *parent,
789 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
791 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
792 IWineD3DVolumeTextureImpl *object;
793 unsigned int i;
794 UINT tmpW;
795 UINT tmpH;
796 UINT tmpD;
798 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, D3DRTYPE_VOLUMETEXTURE, 0);
799 D3DINITILIZEBASETEXTURE(object->baseTexture);
801 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
802 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
804 object->width = Width;
805 object->height = Height;
806 object->depth = Depth;
808 /* Calculate levels for mip mapping */
809 if (Levels == 0) {
810 object->baseTexture.levels++;
811 tmpW = Width;
812 tmpH = Height;
813 tmpD = Depth;
814 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
815 tmpW = max(1, tmpW >> 1);
816 tmpH = max(1, tmpH >> 1);
817 tmpD = max(1, tmpD >> 1);
818 object->baseTexture.levels++;
820 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
823 /* Generate all the surfaces */
824 tmpW = Width;
825 tmpH = Height;
826 tmpD = Depth;
828 for (i = 0; i < object->baseTexture.levels; i++)
830 /* Create the volume */
831 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
832 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
834 /* Set it's container to this object */
835 IWineD3DVolume_SetContainer(object->volumes[i], (IUnknown *)object);
837 /* calcualte the next mipmap level */
838 tmpW = max(1, tmpW >> 1);
839 tmpH = max(1, tmpH >> 1);
840 tmpD = max(1, tmpD >> 1);
843 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
844 TRACE("(%p) : Created volume texture %p\n", This, object);
845 return D3D_OK;
848 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
849 UINT Width, UINT Height, UINT Depth,
850 DWORD Usage,
851 WINED3DFORMAT Format, D3DPOOL Pool,
852 IWineD3DVolume** ppVolume,
853 HANDLE* pSharedHandle, IUnknown *parent) {
855 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
856 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
858 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, D3DRTYPE_VOLUME, ((Width * D3DFmtGetBpp(This, Format)) * Height * Depth))
860 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
861 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
863 object->currentDesc.Width = Width;
864 object->currentDesc.Height = Height;
865 object->currentDesc.Depth = Depth;
866 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
868 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
869 object->lockable = TRUE;
870 object->locked = FALSE;
871 memset(&object->lockedBox, 0, sizeof(D3DBOX));
872 object->dirty = TRUE;
874 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
877 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
878 UINT Levels, DWORD Usage,
879 WINED3DFORMAT Format, D3DPOOL Pool,
880 IWineD3DCubeTexture** ppCubeTexture,
881 HANDLE* pSharedHandle, IUnknown *parent,
882 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
884 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
885 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
886 unsigned int i,j;
887 UINT tmpW;
888 HRESULT hr;
889 unsigned int pow2EdgeLength = EdgeLength;
891 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, D3DRTYPE_CUBETEXTURE, 0);
892 D3DINITILIZEBASETEXTURE(object->baseTexture);
894 TRACE("(%p) Create Cube Texture \n", This);
896 object->edgeLength = EdgeLength;
898 /** Non-power2 support **/
900 /* Find the nearest pow2 match */
901 pow2EdgeLength = 1;
902 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
904 /* TODO: support for native non-power 2 */
905 /* Precalculated scaling for 'faked' non power of two texture coords */
906 object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
908 /* Calculate levels for mip mapping */
909 if (Levels == 0) {
910 object->baseTexture.levels++;
911 tmpW = EdgeLength;
912 while (tmpW > 1) {
913 tmpW = max(1, tmpW / 2);
914 object->baseTexture.levels++;
916 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
919 /* Generate all the surfaces */
920 tmpW = EdgeLength;
921 for (i = 0; i < object->baseTexture.levels; i++) {
923 /* Create the 6 faces */
924 for (j = 0; j < 6; j++) {
926 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
927 i /* Level */, &object->surfaces[j][i],pSharedHandle);
929 if(hr!= D3D_OK) {
930 /* clean up */
931 int k;
932 int l;
933 for (l=0;l<j;l++) {
934 IWineD3DSurface_Release(object->surfaces[j][i]);
936 for (k=0;k<i;k++) {
937 for (l=0;l<6;l++) {
938 IWineD3DSurface_Release(object->surfaces[l][j]);
942 FIXME("(%p) Failed to create surface\n",object);
943 HeapFree(GetProcessHeap(),0,object);
944 *ppCubeTexture = NULL;
945 return hr;
947 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IUnknown *)object);
948 TRACE("Created surface level %d @ %p, \n", i, object->surfaces[j][i]);
950 tmpW = max(1, tmpW >> 1);
953 TRACE("(%p) : Created Cube Texture %p\n", This, object);
954 *ppCubeTexture = (IWineD3DCubeTexture *) object;
955 return D3D_OK;
958 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
959 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
960 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
962 if(NULL == ppQuery) {
963 /* Just a check to see if we support this type of query */
964 HRESULT hr = D3DERR_NOTAVAILABLE;
965 /* Lie and say everything is good (we can return ok fake data from a stub) */
966 switch(Type) {
967 case WINED3DQUERYTYPE_VCACHE:
968 case WINED3DQUERYTYPE_RESOURCEMANAGER:
969 case WINED3DQUERYTYPE_VERTEXSTATS:
970 case WINED3DQUERYTYPE_EVENT:
971 case WINED3DQUERYTYPE_OCCLUSION:
972 case WINED3DQUERYTYPE_TIMESTAMP:
973 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
974 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
975 case WINED3DQUERYTYPE_PIPELINETIMINGS:
976 case WINED3DQUERYTYPE_INTERFACETIMINGS:
977 case WINED3DQUERYTYPE_VERTEXTIMINGS:
978 case WINED3DQUERYTYPE_PIXELTIMINGS:
979 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
980 case WINED3DQUERYTYPE_CACHEUTILIZATION:
981 hr = D3D_OK;
982 break;
983 default:
984 FIXME("(%p) Unhandled query type %d\n",This , Type);
986 FIXME("(%p) : Stub request for query type %d returned %ld\n", This, Type, hr);
987 return hr;
990 D3DCREATEOBJECTINSTANCE(object, Query)
991 object->type = Type;
992 object->extendedData = 0;
993 TRACE("(%p) : Created Query %p\n", This, object);
994 return D3D_OK;
997 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
998 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
999 IUnknown* parent,
1000 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1001 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1002 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1004 HDC hDc;
1005 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1006 int num;
1007 XVisualInfo template;
1008 GLXContext oldContext;
1009 Drawable oldDrawable;
1010 HRESULT hr = D3D_OK;
1012 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1014 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1015 * does a device hold a reference to a swap chain giving them a lifetime of the device
1016 * or does the swap chain notify the device of it'd destruction.
1017 *******************************/
1019 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1021 /* Initialize other useful values */
1022 object->presentParms.BackBufferCount = 1; /* TODO:? support for gl_aux buffers */
1024 /*********************
1025 * Lookup the window Handle and the relating X window handle
1026 ********************/
1028 /* Setup hwnd we are using, plus which display this equates to */
1029 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1030 if (!object->win_handle) {
1031 object->win_handle = This->createParms.hFocusWindow;
1034 object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window" );
1035 hDc = GetDC(object->win_handle);
1036 object->display = get_display(hDc);
1037 ReleaseDC(object->win_handle, hDc);
1038 TRACE("Using a display of %p %p \n", object->display, hDc);
1040 if (NULL == object->display || NULL == hDc) {
1041 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1042 return D3DERR_NOTAVAILABLE;
1045 if (object->win == 0) {
1046 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1047 return D3DERR_NOTAVAILABLE;
1050 * Create an opengl context for the display visual
1051 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1052 * use different properties after that point in time. FIXME: How to handle when requested format
1053 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1054 * it chooses is identical to the one already being used!
1055 **********************************/
1057 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1058 ENTER_GL();
1060 /* Create a new context for this swapchain */
1061 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1062 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1063 (or the best possible if none is requested) */
1064 TRACE("Found x visual ID : %ld\n", template.visualid);
1066 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1067 if (NULL == object->visInfo) {
1068 ERR("cannot really get XVisual\n");
1069 LEAVE_GL();
1070 return D3DERR_NOTAVAILABLE;
1071 } else {
1072 int n, value;
1073 /* Write out some debug info about the visual/s */
1074 TRACE("Using x visual ID : %ld\n", template.visualid);
1075 TRACE(" visual info: %p\n", object->visInfo);
1076 TRACE(" num items : %d\n", num);
1077 for(n = 0;n < num; n++) {
1078 TRACE("=====item=====: %d\n", n + 1);
1079 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1080 TRACE(" screen : %d\n", object->visInfo[n].screen);
1081 TRACE(" depth : %u\n", object->visInfo[n].depth);
1082 TRACE(" class : %d\n", object->visInfo[n].class);
1083 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1084 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1085 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1086 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1087 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1088 /* log some extra glx info */
1089 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1090 TRACE(" gl_aux_buffers : %d\n", value);
1091 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1092 TRACE(" gl_buffer_size : %d\n", value);
1093 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1094 TRACE(" gl_red_size : %d\n", value);
1095 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1096 TRACE(" gl_green_size : %d\n", value);
1097 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1098 TRACE(" gl_blue_size : %d\n", value);
1099 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1100 TRACE(" gl_alpha_size : %d\n", value);
1101 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1102 TRACE(" gl_depth_size : %d\n", value);
1103 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1104 TRACE(" gl_stencil_size : %d\n", value);
1106 /* Now choose a simila visual ID*/
1108 #ifdef USE_CONTEXT_MANAGER
1110 /** TODO: use a context mamager **/
1111 #endif
1114 IWineD3DSwapChain *implSwapChain;
1115 if (D3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1116 /* The first time around we create the context that is shared with all other swapchains and render targets */
1117 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1118 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1119 } else {
1121 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1122 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1123 /* and create a new context with the implicit swapchains context as the shared context */
1124 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1125 IWineD3DSwapChain_Release(implSwapChain);
1129 /* Cleanup */
1130 XFree(object->visInfo);
1131 object->visInfo = NULL;
1133 if (NULL == object->glCtx) {
1134 ERR("cannot create glxContext\n");
1135 LEAVE_GL();
1136 return D3DERR_NOTAVAILABLE;
1139 LEAVE_GL();
1140 if (object->glCtx == NULL) {
1141 ERR("Error in context creation !\n");
1142 return D3DERR_INVALIDCALL;
1143 } else {
1144 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1145 object->win_handle, object->glCtx, object->win, object->visInfo);
1148 /*********************
1149 * Windowed / Fullscreen
1150 *******************/
1153 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1154 * so we should really check to see if their is a fullscreen swapchain already
1155 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1156 **************************************/
1158 if (!*(pPresentationParameters->Windowed)) {
1160 DEVMODEW devmode;
1161 HDC hdc;
1162 int bpp = 0;
1164 /* Get info on the current display setup */
1165 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1166 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1167 DeleteDC(hdc);
1169 /* Change the display settings */
1170 memset(&devmode, 0, sizeof(DEVMODEW));
1171 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1172 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1173 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1174 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1175 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1176 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1178 /* Make popup window */
1179 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1180 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1181 *(pPresentationParameters->BackBufferWidth),
1182 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1188 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1189 * then the corresponding dimension of the client area of the hDeviceWindow
1190 * (or the focus window, if hDeviceWindow is NULL) is taken.
1191 **********************/
1193 if (*(pPresentationParameters->Windowed) &&
1194 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1195 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1197 RECT Rect;
1198 GetClientRect(object->win_handle, &Rect);
1200 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1201 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1202 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1204 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1205 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1206 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1210 /*********************
1211 * finish off parameter initialization
1212 *******************/
1214 /* Put the correct figures in the presentation parameters */
1215 TRACE("Coppying accross presentaion paraneters\n");
1216 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1217 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1218 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1219 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1220 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1221 object->presentParms.MultiSampleQuality = *(pPresentationParameters->MultiSampleQuality);
1222 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1223 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1224 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1225 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1226 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1227 object->presentParms.Flags = *(pPresentationParameters->Flags);
1228 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1229 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1232 /*********************
1233 * Create the back, front and stencil buffers
1234 *******************/
1235 TRACE("calling rendertarget CB\n");
1236 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1237 object->presentParms.BackBufferWidth,
1238 object->presentParms.BackBufferHeight,
1239 object->presentParms.BackBufferFormat,
1240 object->presentParms.MultiSampleType,
1241 object->presentParms.MultiSampleQuality,
1242 TRUE /* Lockable */,
1243 &object->frontBuffer,
1244 NULL /* pShared (always null)*/);
1245 if (object->frontBuffer != NULL)
1246 IWineD3DSurface_SetContainer(object->frontBuffer, (IUnknown *)object);
1247 TRACE("calling rendertarget CB\n");
1248 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1249 object->presentParms.BackBufferWidth,
1250 object->presentParms.BackBufferHeight,
1251 object->presentParms.BackBufferFormat,
1252 object->presentParms.MultiSampleType,
1253 object->presentParms.MultiSampleQuality,
1254 TRUE /* Lockable */,
1255 &object->backBuffer,
1256 NULL /* pShared (always null)*/);
1257 if (object->backBuffer != NULL)
1258 IWineD3DSurface_SetContainer(object->backBuffer, (IUnknown *)object);
1260 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1261 if (pPresentationParameters->EnableAutoDepthStencil) {
1262 TRACE("Creating depth stencil buffer\n");
1263 if (This->depthStencilBuffer == NULL ) {
1264 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1265 object->presentParms.BackBufferWidth,
1266 object->presentParms.BackBufferHeight,
1267 object->presentParms.AutoDepthStencilFormat,
1268 object->presentParms.MultiSampleType,
1269 object->presentParms.MultiSampleQuality,
1270 FALSE /* FIXME: Discard */,
1271 &This->depthStencilBuffer,
1272 NULL /* pShared (always null)*/ );
1273 if (This->depthStencilBuffer != NULL)
1274 IWineD3DSurface_SetContainer(This->depthStencilBuffer, (IUnknown *)iface);
1277 /** TODO: A check on width, height and multisample types
1278 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1279 ****************************/
1280 object->wantsDepthStencilBuffer = TRUE;
1281 } else {
1282 object->wantsDepthStencilBuffer = FALSE;
1285 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1288 /*********************
1289 * init the default renderTarget management
1290 *******************/
1291 object->drawable = object->win;
1292 object->render_ctx = object->glCtx;
1294 if(hr == D3D_OK) {
1295 /*********************
1296 * Setup some defaults and clear down the buffers
1297 *******************/
1298 ENTER_GL();
1299 /** save current context and drawable **/
1300 oldContext = glXGetCurrentContext();
1301 oldDrawable = glXGetCurrentDrawable();
1303 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1304 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1305 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1307 checkGLcall("glXMakeCurrent");
1309 TRACE("Setting up the screen\n");
1310 /* Clear the screen */
1311 glClearColor(0.0, 0.0, 0.0, 0.0);
1312 checkGLcall("glClearColor");
1313 glClearIndex(0);
1314 glClearDepth(1);
1315 glClearStencil(0xffff);
1317 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1318 checkGLcall("glClear");
1320 glColor3f(1.0, 1.0, 1.0);
1321 checkGLcall("glColor3f");
1323 glEnable(GL_LIGHTING);
1324 checkGLcall("glEnable");
1326 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1327 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1329 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1330 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1332 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1333 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1335 /* switch back to the original context (unless it was zero)*/
1336 if (This->swapchains != NULL) {
1337 /** TODO: restore the context and drawable **/
1338 glXMakeCurrent(object->display, oldDrawable, oldContext);
1341 LEAVE_GL();
1343 { /* Finally add the swapchain to the end of the devices' swapchain list */
1344 SwapChainList **nextSwapchain;
1345 nextSwapchain = &This->swapchains;
1346 while(*nextSwapchain != NULL) {
1347 nextSwapchain = &((*nextSwapchain)->next);
1349 (*nextSwapchain) = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->swapchains));
1350 (*nextSwapchain)->swapchain = (IWineD3DSwapChain *)object;
1352 TRACE("Set swapchain to %p\n", object);
1353 } else { /* something went wrong so clean up */
1354 IUnknown* bufferParent;
1355 if (object->frontBuffer) {
1356 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1357 IUnknown_Release(bufferParent); /* once for the get parent */
1358 if(IUnknown_Release(bufferParent) > 0) {
1359 FIXME("(%p) Something's still holding the front buffer\n",This);
1362 if (object->backBuffer) {
1363 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1364 IUnknown_Release(bufferParent); /* once for the get parent */
1365 if(IUnknown_Release(bufferParent) > 0) {
1366 FIXME("(%p) Something's still holding the back buffer\n",This);
1369 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1370 /* Clean up the context */
1371 /* check that we are the current context first (we shouldn't be though!) */
1372 if (object->glCtx != 0) {
1373 if(glXGetCurrentContext() == object->glCtx) {
1374 glXMakeCurrent(object->display, None, NULL);
1376 glXDestroyContext(object->display, object->glCtx);
1378 HeapFree(GetProcessHeap(), 0, object);
1381 return hr;
1384 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1385 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1386 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1387 unsigned int numberOfSwapChains = 0;
1388 SwapChainList *swapchain;
1390 swapchain = This->swapchains;
1391 /* itterate through the list to get a count */
1392 while (swapchain != NULL) {
1393 swapchain = swapchain->next;
1394 numberOfSwapChains++;
1397 TRACE("(%p) returning %d\n", This, numberOfSwapChains);
1398 return numberOfSwapChains;
1401 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1402 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1403 SwapChainList *swapchain;
1404 HRESULT hr = D3DERR_INVALIDCALL;
1405 swapchain = This->swapchains;
1406 TRACE("(%p) : swapchain %d \n", This, iSwapChain);
1409 TRACE("(%p) Finding swapchain %d\n", This, iSwapChain);
1410 while (iSwapChain > 0 && swapchain != NULL) {
1411 swapchain = swapchain->next;
1412 iSwapChain--;
1415 if (iSwapChain > 0 || swapchain == NULL) {
1416 FIXME("(%p) Unable to find swapchain %d\n", This, iSwapChain);
1417 *pSwapChain = NULL;
1418 } else {
1419 /** TODO: move off to a linkesList implementation **/
1420 *pSwapChain = swapchain->swapchain;
1421 IWineD3DSwapChain_AddRef(*pSwapChain);
1422 hr = D3D_OK;
1425 TRACE("(%p) returning %p\n", This, *pSwapChain);
1426 return hr;
1429 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
1430 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1432 FIXME("(%p) : Stub\n",This);
1433 return D3D_OK;
1437 /*****
1438 * Vertex Declaration
1439 *****/
1440 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1441 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1442 IWineD3DVertexDeclarationImpl *object = NULL;
1443 HRESULT hr = D3D_OK;
1444 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1445 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1446 object->allFVF = 0;
1448 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1450 return hr;
1453 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1454 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DVertexShader** ppVertexShader, IUnknown *parent) {
1455 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1456 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1457 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1458 object->function = pFunction;
1459 FIXME("(%p) : STUB: Created Vertex shader %p\n", This, ppVertexShader);
1460 return D3D_OK;
1464 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DPixelShader** ppPixelShader, IUnknown *parent) {
1465 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1466 FIXME("(%p) : Stub\n", This);
1467 return D3D_OK;
1470 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice* iface, IWineD3D** ppD3D) {
1471 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1472 *ppD3D= This->wineD3D;
1473 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1474 IWineD3D_AddRef(*ppD3D);
1475 return D3D_OK;
1479 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1480 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1481 * Into the video ram as possible and seeing how many fit
1482 * you can also get the correct initial value from via X and ATI's driver
1483 *******************/
1484 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1485 static BOOL showfixmes = TRUE;
1486 if (showfixmes) {
1487 FIXME("(%p) : stub, emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1488 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1489 showfixmes = FALSE;
1491 TRACE("(%p) : emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1492 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1493 /* videomemory is simulated videomemory + AGP memory left */
1494 return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1499 /*****
1500 * Get / Set FVF
1501 *****/
1502 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1503 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1505 /* Update the current state block */
1506 This->updateStateBlock->fvf = fvf;
1507 This->updateStateBlock->changed.fvf = TRUE;
1508 This->updateStateBlock->set.fvf = TRUE;
1510 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1511 /* clear down the vertex declaration
1512 NOTE: Axis and Allies doesn't work properly otherwise
1513 (may be a stateblock problem though!)
1515 /* No difference if recording or not */
1516 return IWineD3DDevice_SetVertexDeclaration(iface, NULL);
1521 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1522 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1523 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1524 *pfvf = This->stateBlock->fvf;
1525 return D3D_OK;
1528 /*****
1529 * Get / Set Stream Source
1530 *****/
1531 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1532 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1533 IWineD3DVertexBuffer *oldSrc;
1535 oldSrc = This->stateBlock->streamSource[StreamNumber];
1536 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1538 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
1539 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
1540 This->updateStateBlock->streamStride[StreamNumber] = Stride;
1541 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
1542 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
1544 /* Handle recording of state blocks */
1545 if (This->isRecordingState) {
1546 TRACE("Recording... not performing anything\n");
1547 return D3D_OK;
1550 /* Not recording... */
1551 if (pStreamData != NULL) {
1552 IUnknown *newVertexBufferParent;
1553 /* GetParent will add a ref, so leave it hanging until the vertex buffer is cleared */
1554 IWineD3DVertexBuffer_GetParent(pStreamData, &newVertexBufferParent);
1556 if (oldSrc != NULL) {
1557 IUnknown *oldVertexBufferParent;
1558 IWineD3DVertexBuffer_GetParent(oldSrc, &oldVertexBufferParent);
1559 IUnknown_Release(oldVertexBufferParent);
1560 IUnknown_Release(oldVertexBufferParent);
1563 return D3D_OK;
1566 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
1567 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1569 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
1570 *pStream = This->stateBlock->streamSource[StreamNumber];
1571 *pStride = This->stateBlock->streamStride[StreamNumber];
1572 *pOffset = This->stateBlock->streamOffset[StreamNumber];
1573 if (*pStream != NULL) IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
1574 return D3D_OK;
1577 /*Should be quite easy, just an extension of vertexdata
1578 ref...
1579 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1581 The divider is a bit odd though
1583 VertexOffset = StartVertex / Divider * StreamStride +
1584 VertexIndex / Divider * StreamStride + StreamOffset
1587 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
1588 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1590 FIXME("(%p) : stub\n", This);
1591 return D3D_OK;
1594 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
1595 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1597 FIXME("(%p) : stub\n", This);
1598 return D3D_OK;
1601 /*****
1602 * Get / Set & Multiply Transform
1603 *****/
1604 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1605 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1607 /* Most of this routine, comments included copied from ddraw tree initially: */
1608 TRACE("(%p) : Transform State=%d\n", This, d3dts);
1610 /* Handle recording of state blocks */
1611 if (This->isRecordingState) {
1612 TRACE("Recording... not performing anything\n");
1613 This->updateStateBlock->changed.transform[d3dts] = TRUE;
1614 This->updateStateBlock->set.transform[d3dts] = TRUE;
1615 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1616 return D3D_OK;
1620 * If the new matrix is the same as the current one,
1621 * we cut off any further processing. this seems to be a reasonable
1622 * optimization because as was noticed, some apps (warcraft3 for example)
1623 * tend towards setting the same matrix repeatedly for some reason.
1625 * From here on we assume that the new matrix is different, wherever it matters.
1627 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1628 TRACE("The app is setting the same matrix over again\n");
1629 return D3D_OK;
1630 } else {
1631 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1635 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1636 where ViewMat = Camera space, WorldMat = world space.
1638 In OpenGL, camera and world space is combined into GL_MODELVIEW
1639 matrix. The Projection matrix stay projection matrix.
1642 /* Capture the times we can just ignore the change for now */
1643 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1644 This->modelview_valid = FALSE;
1645 return D3D_OK;
1647 } else if (d3dts == D3DTS_PROJECTION) {
1648 This->proj_valid = FALSE;
1649 return D3D_OK;
1651 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1652 /* Indexed Vertex Blending Matrices 256 -> 511 */
1653 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1654 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1655 return D3D_OK;
1658 /* Now we really are going to have to change a matrix */
1659 ENTER_GL();
1661 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1662 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
1663 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1664 unsigned int k;
1666 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1667 * NOTE: We have to reset the positions even if the light/plane is not currently
1668 * enabled, since the call to enable it will not reset the position.
1669 * NOTE2: Apparently texture transforms do NOT need reapplying
1672 PLIGHTINFOEL *lightChain = NULL;
1673 This->modelview_valid = FALSE;
1674 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
1676 glMatrixMode(GL_MODELVIEW);
1677 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1678 glPushMatrix();
1679 glLoadMatrixf((float *)lpmatrix);
1680 checkGLcall("glLoadMatrixf(...)");
1682 /* Reset lights */
1683 lightChain = This->stateBlock->lights;
1684 while (lightChain && lightChain->glIndex != -1) {
1685 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1686 checkGLcall("glLightfv posn");
1687 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1688 checkGLcall("glLightfv dirn");
1689 lightChain = lightChain->next;
1692 /* Reset Clipping Planes if clipping is enabled */
1693 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1694 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1695 checkGLcall("glClipPlane");
1697 glPopMatrix();
1699 } else { /* What was requested!?? */
1700 WARN("invalid matrix specified: %i\n", d3dts);
1703 /* Release lock, all done */
1704 LEAVE_GL();
1705 return D3D_OK;
1708 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1709 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1710 TRACE("(%p) : for Transform State %d\n", This, State);
1711 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1712 return D3D_OK;
1715 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1716 D3DMATRIX *mat = NULL;
1717 D3DMATRIX temp;
1719 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1720 * below means it will be recorded in a state block change, but it
1721 * works regardless where it is recorded.
1722 * If this is found to be wrong, change to StateBlock.
1724 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1725 TRACE("(%p) : For state %u\n", This, State);
1727 if (State < HIGHEST_TRANSFORMSTATE)
1729 mat = &This->updateStateBlock->transforms[State];
1730 } else {
1731 FIXME("Unhandled transform state!!\n");
1734 /* Copied from ddraw code: */
1735 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);
1736 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);
1737 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);
1738 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);
1740 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);
1741 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);
1742 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);
1743 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);
1745 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);
1746 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);
1747 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);
1748 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);
1750 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);
1751 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);
1752 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);
1753 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);
1755 /* Apply change via set transform - will reapply to eg. lights this way */
1756 IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
1757 return D3D_OK;
1760 /*****
1761 * Get / Set Light
1762 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
1763 *****/
1764 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1765 you can reference any indexes you want as long as that number max are enabled at any
1766 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1767 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1768 but when recording, just build a chain pretty much of commands to be replayed. */
1770 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
1771 float rho;
1772 PLIGHTINFOEL *object, *temp;
1774 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1775 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1777 /* If recording state block, just add to end of lights chain */
1778 if (This->isRecordingState) {
1779 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1780 if (NULL == object) {
1781 return D3DERR_OUTOFVIDEOMEMORY;
1783 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1784 object->OriginalIndex = Index;
1785 object->glIndex = -1;
1786 object->changed = TRUE;
1788 /* Add to the END of the chain of lights changes to be replayed */
1789 if (This->updateStateBlock->lights == NULL) {
1790 This->updateStateBlock->lights = object;
1791 } else {
1792 temp = This->updateStateBlock->lights;
1793 while (temp->next != NULL) temp=temp->next;
1794 temp->next = object;
1796 TRACE("Recording... not performing anything more\n");
1797 return D3D_OK;
1800 /* Ok, not recording any longer so do real work */
1801 object = This->stateBlock->lights;
1802 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1804 /* If we didn't find it in the list of lights, time to add it */
1805 if (object == NULL) {
1806 PLIGHTINFOEL *insertAt,*prevPos;
1808 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1809 if (NULL == object) {
1810 return D3DERR_OUTOFVIDEOMEMORY;
1812 object->OriginalIndex = Index;
1813 object->glIndex = -1;
1815 /* Add it to the front of list with the idea that lights will be changed as needed
1816 BUT after any lights currently assigned GL indexes */
1817 insertAt = This->stateBlock->lights;
1818 prevPos = NULL;
1819 while (insertAt != NULL && insertAt->glIndex != -1) {
1820 prevPos = insertAt;
1821 insertAt = insertAt->next;
1824 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1825 This->stateBlock->lights = object;
1826 } else if (insertAt == NULL) { /* End of list */
1827 prevPos->next = object;
1828 object->prev = prevPos;
1829 } else { /* Middle of chain */
1830 if (prevPos == NULL) {
1831 This->stateBlock->lights = object;
1832 } else {
1833 prevPos->next = object;
1835 object->prev = prevPos;
1836 object->next = insertAt;
1837 insertAt->prev = object;
1841 /* Initialze the object */
1842 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,
1843 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1844 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1845 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1846 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1847 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1848 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1850 /* Save away the information */
1851 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1853 switch (pLight->Type) {
1854 case D3DLIGHT_POINT:
1855 /* Position */
1856 object->lightPosn[0] = pLight->Position.x;
1857 object->lightPosn[1] = pLight->Position.y;
1858 object->lightPosn[2] = pLight->Position.z;
1859 object->lightPosn[3] = 1.0f;
1860 object->cutoff = 180.0f;
1861 /* FIXME: Range */
1862 break;
1864 case D3DLIGHT_DIRECTIONAL:
1865 /* Direction */
1866 object->lightPosn[0] = -pLight->Direction.x;
1867 object->lightPosn[1] = -pLight->Direction.y;
1868 object->lightPosn[2] = -pLight->Direction.z;
1869 object->lightPosn[3] = 0.0;
1870 object->exponent = 0.0f;
1871 object->cutoff = 180.0f;
1872 break;
1874 case D3DLIGHT_SPOT:
1875 /* Position */
1876 object->lightPosn[0] = pLight->Position.x;
1877 object->lightPosn[1] = pLight->Position.y;
1878 object->lightPosn[2] = pLight->Position.z;
1879 object->lightPosn[3] = 1.0;
1881 /* Direction */
1882 object->lightDirn[0] = pLight->Direction.x;
1883 object->lightDirn[1] = pLight->Direction.y;
1884 object->lightDirn[2] = pLight->Direction.z;
1885 object->lightDirn[3] = 1.0;
1888 * opengl-ish and d3d-ish spot lights use too different models for the
1889 * light "intensity" as a function of the angle towards the main light direction,
1890 * so we only can approximate very roughly.
1891 * however spot lights are rather rarely used in games (if ever used at all).
1892 * furthermore if still used, probably nobody pays attention to such details.
1894 if (pLight->Falloff == 0) {
1895 rho = 6.28f;
1896 } else {
1897 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1899 if (rho < 0.0001) rho = 0.0001f;
1900 object->exponent = -0.3/log(cos(rho/2));
1901 object->cutoff = pLight->Phi*90/M_PI;
1903 /* FIXME: Range */
1904 break;
1906 default:
1907 FIXME("Unrecognized light type %d\n", pLight->Type);
1910 /* Update the live definitions if the light is currently assigned a glIndex */
1911 if (object->glIndex != -1) {
1912 setup_light(iface, object->glIndex, object);
1914 return D3D_OK;
1917 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
1918 PLIGHTINFOEL *lightInfo = NULL;
1919 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1920 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1922 /* Locate the light in the live lights */
1923 lightInfo = This->stateBlock->lights;
1924 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1926 if (lightInfo == NULL) {
1927 TRACE("Light information requested but light not defined\n");
1928 return D3DERR_INVALIDCALL;
1931 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
1932 return D3D_OK;
1935 /*****
1936 * Get / Set Light Enable
1937 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
1938 *****/
1939 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
1940 PLIGHTINFOEL *lightInfo = NULL;
1941 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1942 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1944 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1945 if (This->isRecordingState) {
1946 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1947 if (NULL == lightInfo) {
1948 return D3DERR_OUTOFVIDEOMEMORY;
1950 lightInfo->OriginalIndex = Index;
1951 lightInfo->glIndex = -1;
1952 lightInfo->enabledChanged = TRUE;
1954 /* Add to the END of the chain of lights changes to be replayed */
1955 if (This->updateStateBlock->lights == NULL) {
1956 This->updateStateBlock->lights = lightInfo;
1957 } else {
1958 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
1959 while (temp->next != NULL) temp=temp->next;
1960 temp->next = lightInfo;
1962 TRACE("Recording... not performing anything more\n");
1963 return D3D_OK;
1966 /* Not recording... So, locate the light in the live lights */
1967 lightInfo = This->stateBlock->lights;
1968 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1970 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1971 if (lightInfo == NULL) {
1972 D3DLIGHT9 lightParms;
1973 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1974 wait until someone confirms it seems to work! */
1975 TRACE("Light enabled requested but light not defined, so defining one!\n");
1976 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1977 lightParms.Diffuse.r = 1.0;
1978 lightParms.Diffuse.g = 1.0;
1979 lightParms.Diffuse.b = 1.0;
1980 lightParms.Diffuse.a = 0.0;
1981 lightParms.Specular.r = 0.0;
1982 lightParms.Specular.g = 0.0;
1983 lightParms.Specular.b = 0.0;
1984 lightParms.Specular.a = 0.0;
1985 lightParms.Ambient.r = 0.0;
1986 lightParms.Ambient.g = 0.0;
1987 lightParms.Ambient.b = 0.0;
1988 lightParms.Ambient.a = 0.0;
1989 lightParms.Position.x = 0.0;
1990 lightParms.Position.y = 0.0;
1991 lightParms.Position.z = 0.0;
1992 lightParms.Direction.x = 0.0;
1993 lightParms.Direction.y = 0.0;
1994 lightParms.Direction.z = 1.0;
1995 lightParms.Range = 0.0;
1996 lightParms.Falloff = 0.0;
1997 lightParms.Attenuation0 = 0.0;
1998 lightParms.Attenuation1 = 0.0;
1999 lightParms.Attenuation2 = 0.0;
2000 lightParms.Theta = 0.0;
2001 lightParms.Phi = 0.0;
2002 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
2004 /* Search for it again! Should be fairly quick as near head of list */
2005 lightInfo = This->stateBlock->lights;
2006 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2007 if (lightInfo == NULL) {
2008 FIXME("Adding default lights has failed dismally\n");
2009 return D3DERR_INVALIDCALL;
2013 /* OK, we now have a light... */
2014 if (Enable == FALSE) {
2016 /* If we are disabling it, check it was enabled, and
2017 still only do something if it has assigned a glIndex (which it should have!) */
2018 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2019 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2020 ENTER_GL();
2021 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2022 checkGLcall("glDisable GL_LIGHT0+Index");
2023 LEAVE_GL();
2024 } else {
2025 TRACE("Nothing to do as light was not enabled\n");
2027 lightInfo->lightEnabled = FALSE;
2028 } else {
2030 /* We are enabling it. If it is enabled, it's really simple */
2031 if (lightInfo->lightEnabled) {
2032 /* nop */
2033 TRACE("Nothing to do as light was enabled\n");
2035 /* If it already has a glIndex, it's still simple */
2036 } else if (lightInfo->glIndex != -1) {
2037 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2038 lightInfo->lightEnabled = TRUE;
2039 ENTER_GL();
2040 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2041 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2042 LEAVE_GL();
2044 /* Otherwise got to find space - lights are ordered gl indexes first */
2045 } else {
2046 PLIGHTINFOEL *bsf = NULL;
2047 PLIGHTINFOEL *pos = This->stateBlock->lights;
2048 PLIGHTINFOEL *prev = NULL;
2049 int Index= 0;
2050 int glIndex = -1;
2052 /* Try to minimize changes as much as possible */
2053 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2055 /* Try to remember which index can be replaced if necessary */
2056 if (bsf==NULL && pos->lightEnabled == FALSE) {
2057 /* Found a light we can replace, save as best replacement */
2058 bsf = pos;
2061 /* Step to next space */
2062 prev = pos;
2063 pos = pos->next;
2064 Index ++;
2067 /* If we have too many active lights, fail the call */
2068 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2069 FIXME("Program requests too many concurrent lights\n");
2070 return D3DERR_INVALIDCALL;
2072 /* If we have allocated all lights, but not all are enabled,
2073 reuse one which is not enabled */
2074 } else if (Index == This->maxConcurrentLights) {
2075 /* use bsf - Simply swap the new light and the BSF one */
2076 PLIGHTINFOEL *bsfNext = bsf->next;
2077 PLIGHTINFOEL *bsfPrev = bsf->prev;
2079 /* Sort out ends */
2080 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2081 if (bsf->prev != NULL) {
2082 bsf->prev->next = lightInfo;
2083 } else {
2084 This->stateBlock->lights = lightInfo;
2087 /* If not side by side, lots of chains to update */
2088 if (bsf->next != lightInfo) {
2089 lightInfo->prev->next = bsf;
2090 bsf->next->prev = lightInfo;
2091 bsf->next = lightInfo->next;
2092 bsf->prev = lightInfo->prev;
2093 lightInfo->next = bsfNext;
2094 lightInfo->prev = bsfPrev;
2096 } else {
2097 /* Simple swaps */
2098 bsf->prev = lightInfo;
2099 bsf->next = lightInfo->next;
2100 lightInfo->next = bsf;
2101 lightInfo->prev = bsfPrev;
2105 /* Update states */
2106 glIndex = bsf->glIndex;
2107 bsf->glIndex = -1;
2108 lightInfo->glIndex = glIndex;
2109 lightInfo->lightEnabled = TRUE;
2111 /* Finally set up the light in gl itself */
2112 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2113 ENTER_GL();
2114 setup_light(iface, glIndex, lightInfo);
2115 glEnable(GL_LIGHT0 + glIndex);
2116 checkGLcall("glEnable GL_LIGHT0 new setup");
2117 LEAVE_GL();
2119 /* If we reached the end of the allocated lights, with space in the
2120 gl lights, setup a new light */
2121 } else if (pos->glIndex == -1) {
2123 /* We reached the end of the allocated gl lights, so already
2124 know the index of the next one! */
2125 glIndex = Index;
2126 lightInfo->glIndex = glIndex;
2127 lightInfo->lightEnabled = TRUE;
2129 /* In an ideal world, it's already in the right place */
2130 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2131 /* No need to move it */
2132 } else {
2133 /* Remove this light from the list */
2134 lightInfo->prev->next = lightInfo->next;
2135 if (lightInfo->next != NULL) {
2136 lightInfo->next->prev = lightInfo->prev;
2139 /* Add in at appropriate place (inbetween prev and pos) */
2140 lightInfo->prev = prev;
2141 lightInfo->next = pos;
2142 if (prev == NULL) {
2143 This->stateBlock->lights = lightInfo;
2144 } else {
2145 prev->next = lightInfo;
2147 if (pos != NULL) {
2148 pos->prev = lightInfo;
2152 /* Finally set up the light in gl itself */
2153 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2154 ENTER_GL();
2155 setup_light(iface, glIndex, lightInfo);
2156 glEnable(GL_LIGHT0 + glIndex);
2157 checkGLcall("glEnable GL_LIGHT0 new setup");
2158 LEAVE_GL();
2163 return D3D_OK;
2166 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2168 PLIGHTINFOEL *lightInfo = NULL;
2169 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2170 TRACE("(%p) : for idx(%ld)\n", This, Index);
2172 /* Locate the light in the live lights */
2173 lightInfo = This->stateBlock->lights;
2174 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2176 if (lightInfo == NULL) {
2177 TRACE("Light enabled state requested but light not defined\n");
2178 return D3DERR_INVALIDCALL;
2180 *pEnable = lightInfo->lightEnabled;
2181 return D3D_OK;
2184 /*****
2185 * Get / Set Clip Planes
2186 *****/
2187 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2188 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2189 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2191 /* Validate Index */
2192 if (Index >= GL_LIMITS(clipplanes)) {
2193 TRACE("Application has requested clipplane this device doesn't support\n");
2194 return D3DERR_INVALIDCALL;
2197 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2198 This->updateStateBlock->set.clipplane[Index] = TRUE;
2199 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2200 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2201 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2202 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2204 /* Handle recording of state blocks */
2205 if (This->isRecordingState) {
2206 TRACE("Recording... not performing anything\n");
2207 return D3D_OK;
2210 /* Apply it */
2212 ENTER_GL();
2214 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2215 glMatrixMode(GL_MODELVIEW);
2216 glPushMatrix();
2217 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2219 TRACE("Clipplane [%f,%f,%f,%f]\n",
2220 This->updateStateBlock->clipplane[Index][0],
2221 This->updateStateBlock->clipplane[Index][1],
2222 This->updateStateBlock->clipplane[Index][2],
2223 This->updateStateBlock->clipplane[Index][3]);
2224 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2225 checkGLcall("glClipPlane");
2227 glPopMatrix();
2228 LEAVE_GL();
2230 return D3D_OK;
2233 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2234 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2235 TRACE("(%p) : for idx %ld\n", This, Index);
2237 /* Validate Index */
2238 if (Index >= GL_LIMITS(clipplanes)) {
2239 TRACE("Application has requested clipplane this device doesn't support\n");
2240 return D3DERR_INVALIDCALL;
2243 pPlane[0] = This->stateBlock->clipplane[Index][0];
2244 pPlane[1] = This->stateBlock->clipplane[Index][1];
2245 pPlane[2] = This->stateBlock->clipplane[Index][2];
2246 pPlane[3] = This->stateBlock->clipplane[Index][3];
2247 return D3D_OK;
2250 /*****
2251 * Get / Set Clip Plane Status
2252 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2253 *****/
2254 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2255 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2256 FIXME("(%p) : stub\n", This);
2257 if (NULL == pClipStatus) {
2258 return D3DERR_INVALIDCALL;
2260 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2261 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2262 return D3D_OK;
2265 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2266 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2267 FIXME("(%p) : stub\n", This);
2268 if (NULL == pClipStatus) {
2269 return D3DERR_INVALIDCALL;
2271 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2272 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2273 return D3D_OK;
2276 /*****
2277 * Get / Set Material
2278 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2279 *****/
2280 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2281 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2283 This->updateStateBlock->changed.material = TRUE;
2284 This->updateStateBlock->set.material = TRUE;
2285 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2287 /* Handle recording of state blocks */
2288 if (This->isRecordingState) {
2289 TRACE("Recording... not performing anything\n");
2290 return D3D_OK;
2293 ENTER_GL();
2294 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2295 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2296 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2297 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2298 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2300 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2301 checkGLcall("glMaterialfv");
2302 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2303 checkGLcall("glMaterialfv");
2305 /* Only change material color if specular is enabled, otherwise it is set to black */
2306 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2307 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2308 checkGLcall("glMaterialfv");
2309 } else {
2310 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2311 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2312 checkGLcall("glMaterialfv");
2314 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2315 checkGLcall("glMaterialfv");
2316 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2317 checkGLcall("glMaterialf");
2319 LEAVE_GL();
2320 return D3D_OK;
2323 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2324 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2325 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2326 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2327 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2328 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2329 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2330 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2331 return D3D_OK;
2334 /*****
2335 * Get / Set Indices
2336 *****/
2337 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2338 UINT BaseVertexIndex) {
2339 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2340 IWineD3DIndexBuffer *oldIdxs;
2342 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2343 oldIdxs = This->updateStateBlock->pIndexData;
2345 This->updateStateBlock->changed.indices = TRUE;
2346 This->updateStateBlock->set.indices = TRUE;
2347 This->updateStateBlock->pIndexData = pIndexData;
2348 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2350 /* Handle recording of state blocks */
2351 if (This->isRecordingState) {
2352 TRACE("Recording... not performing anything\n");
2353 return D3D_OK;
2356 if (pIndexData) {
2357 IUnknown *indexBufferParent;
2358 /* Getting the parent causes a addRef... it gets released when the indicies are clear */
2359 IWineD3DIndexBuffer_GetParent(pIndexData, &indexBufferParent);
2361 if (oldIdxs) {
2362 IUnknown *indexBufferParent;
2363 IWineD3DIndexBuffer_GetParent(oldIdxs, &indexBufferParent);
2364 IUnknown_Release(indexBufferParent);
2365 IUnknown_Release(indexBufferParent);
2367 return D3D_OK;
2370 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2371 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2373 *ppIndexData = This->stateBlock->pIndexData;
2375 /* up ref count on ppindexdata */
2376 if (*ppIndexData) IWineD3DIndexBuffer_AddRef(*ppIndexData);
2377 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2379 return D3D_OK;
2382 /*****
2383 * Get / Set Viewports
2384 *****/
2385 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2386 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2388 TRACE("(%p)\n", This);
2389 This->updateStateBlock->changed.viewport = TRUE;
2390 This->updateStateBlock->set.viewport = TRUE;
2391 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2393 /* Handle recording of state blocks */
2394 if (This->isRecordingState) {
2395 TRACE("Recording... not performing anything\n");
2396 return D3D_OK;
2399 ENTER_GL();
2401 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2402 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2404 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2405 checkGLcall("glDepthRange");
2406 /* Note: GL requires lower left, DirectX supplies upper left */
2407 /* TODO: replace usage of renderTarget with context management */
2408 glViewport(pViewport->X,
2409 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2410 pViewport->Width, pViewport->Height);
2412 checkGLcall("glViewport");
2414 LEAVE_GL();
2416 return D3D_OK;
2420 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2421 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2422 TRACE("(%p)\n", This);
2423 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2424 return D3D_OK;
2427 /*****
2428 * Get / Set Render States
2429 * TODO: Verify against dx9 definitions
2430 *****/
2431 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2433 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2434 DWORD OldValue = This->stateBlock->renderState[State];
2436 /* Simple way of referring to either a DWORD or a 4 byte float */
2437 union {
2438 DWORD d;
2439 float f;
2440 } tmpvalue;
2442 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2443 This->updateStateBlock->changed.renderState[State] = TRUE;
2444 This->updateStateBlock->set.renderState[State] = TRUE;
2445 This->updateStateBlock->renderState[State] = Value;
2447 /* Handle recording of state blocks */
2448 if (This->isRecordingState) {
2449 TRACE("Recording... not performing anything\n");
2450 return D3D_OK;
2453 ENTER_GL();
2455 switch (State) {
2456 case WINED3DRS_FILLMODE :
2457 switch ((D3DFILLMODE) Value) {
2458 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2459 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2460 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2461 default:
2462 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
2464 checkGLcall("glPolygonMode (fillmode)");
2465 break;
2467 case WINED3DRS_LIGHTING :
2468 if (Value) {
2469 glEnable(GL_LIGHTING);
2470 checkGLcall("glEnable GL_LIGHTING");
2471 } else {
2472 glDisable(GL_LIGHTING);
2473 checkGLcall("glDisable GL_LIGHTING");
2475 break;
2477 case WINED3DRS_ZENABLE :
2478 switch ((D3DZBUFFERTYPE) Value) {
2479 case D3DZB_FALSE:
2480 glDisable(GL_DEPTH_TEST);
2481 checkGLcall("glDisable GL_DEPTH_TEST");
2482 break;
2483 case D3DZB_TRUE:
2484 glEnable(GL_DEPTH_TEST);
2485 checkGLcall("glEnable GL_DEPTH_TEST");
2486 break;
2487 case D3DZB_USEW:
2488 glEnable(GL_DEPTH_TEST);
2489 checkGLcall("glEnable GL_DEPTH_TEST");
2490 FIXME("W buffer is not well handled\n");
2491 break;
2492 default:
2493 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2495 break;
2497 case WINED3DRS_CULLMODE :
2499 /* If we are culling "back faces with clockwise vertices" then
2500 set front faces to be counter clockwise and enable culling
2501 of back faces */
2502 switch ((D3DCULL) Value) {
2503 case D3DCULL_NONE:
2504 glDisable(GL_CULL_FACE);
2505 checkGLcall("glDisable GL_CULL_FACE");
2506 break;
2507 case D3DCULL_CW:
2508 glEnable(GL_CULL_FACE);
2509 checkGLcall("glEnable GL_CULL_FACE");
2510 if (This->renderUpsideDown) {
2511 glFrontFace(GL_CW);
2512 checkGLcall("glFrontFace GL_CW");
2513 } else {
2514 glFrontFace(GL_CCW);
2515 checkGLcall("glFrontFace GL_CCW");
2517 glCullFace(GL_BACK);
2518 break;
2519 case D3DCULL_CCW:
2520 glEnable(GL_CULL_FACE);
2521 checkGLcall("glEnable GL_CULL_FACE");
2522 if (This->renderUpsideDown) {
2523 glFrontFace(GL_CCW);
2524 checkGLcall("glFrontFace GL_CCW");
2525 } else {
2526 glFrontFace(GL_CW);
2527 checkGLcall("glFrontFace GL_CW");
2529 glCullFace(GL_BACK);
2530 break;
2531 default:
2532 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2534 break;
2536 case WINED3DRS_SHADEMODE :
2537 switch ((D3DSHADEMODE) Value) {
2538 case D3DSHADE_FLAT:
2539 glShadeModel(GL_FLAT);
2540 checkGLcall("glShadeModel");
2541 break;
2542 case D3DSHADE_GOURAUD:
2543 glShadeModel(GL_SMOOTH);
2544 checkGLcall("glShadeModel");
2545 break;
2546 case D3DSHADE_PHONG:
2547 FIXME("D3DSHADE_PHONG isn't supported?\n");
2549 LEAVE_GL();
2550 return D3DERR_INVALIDCALL;
2551 default:
2552 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2554 break;
2556 case WINED3DRS_DITHERENABLE :
2557 if (Value) {
2558 glEnable(GL_DITHER);
2559 checkGLcall("glEnable GL_DITHER");
2560 } else {
2561 glDisable(GL_DITHER);
2562 checkGLcall("glDisable GL_DITHER");
2564 break;
2566 case WINED3DRS_ZWRITEENABLE :
2567 if (Value) {
2568 glDepthMask(1);
2569 checkGLcall("glDepthMask");
2570 } else {
2571 glDepthMask(0);
2572 checkGLcall("glDepthMask");
2574 break;
2576 case WINED3DRS_ZFUNC :
2578 int glParm = GL_LESS;
2580 switch ((D3DCMPFUNC) Value) {
2581 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2582 case D3DCMP_LESS: glParm=GL_LESS; break;
2583 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2584 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2585 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2586 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2587 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2588 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2589 default:
2590 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2592 glDepthFunc(glParm);
2593 checkGLcall("glDepthFunc");
2595 break;
2597 case WINED3DRS_AMBIENT :
2599 float col[4];
2600 D3DCOLORTOGLFLOAT4(Value, col);
2601 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2602 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2603 checkGLcall("glLightModel for MODEL_AMBIENT");
2606 break;
2608 case WINED3DRS_ALPHABLENDENABLE :
2609 if (Value) {
2610 glEnable(GL_BLEND);
2611 checkGLcall("glEnable GL_BLEND");
2612 } else {
2613 glDisable(GL_BLEND);
2614 checkGLcall("glDisable GL_BLEND");
2616 break;
2618 case WINED3DRS_SRCBLEND :
2619 case WINED3DRS_DESTBLEND :
2621 int newVal = GL_ZERO;
2622 switch (Value) {
2623 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2624 case D3DBLEND_ONE : newVal = GL_ONE; break;
2625 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2626 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2627 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2628 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2629 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2630 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2631 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2632 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2633 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2635 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2636 This->srcBlend = newVal;
2637 This->dstBlend = newVal;
2638 break;
2640 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2641 This->srcBlend = newVal;
2642 This->dstBlend = newVal;
2643 break;
2644 default:
2645 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2648 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2649 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2650 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2651 glBlendFunc(This->srcBlend, This->dstBlend);
2653 checkGLcall("glBlendFunc");
2655 break;
2657 case WINED3DRS_ALPHATESTENABLE :
2658 if (Value) {
2659 glEnable(GL_ALPHA_TEST);
2660 checkGLcall("glEnable GL_ALPHA_TEST");
2661 } else {
2662 glDisable(GL_ALPHA_TEST);
2663 checkGLcall("glDisable GL_ALPHA_TEST");
2665 break;
2667 case WINED3DRS_ALPHAFUNC :
2669 int glParm = GL_LESS;
2670 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2672 switch ((D3DCMPFUNC) Value) {
2673 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2674 case D3DCMP_LESS: glParm = GL_LESS; break;
2675 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2676 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2677 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2678 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2679 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2680 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2681 default:
2682 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2684 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2685 glAlphaFunc(glParm, ref);
2686 This->alphafunc = glParm;
2687 checkGLcall("glAlphaFunc");
2689 break;
2691 case WINED3DRS_ALPHAREF :
2693 int glParm = This->alphafunc;
2694 float ref = 1.0f;
2696 ref = ((float) Value) / 255.0f;
2697 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2698 glAlphaFunc(glParm, ref);
2699 checkGLcall("glAlphaFunc");
2701 break;
2703 case WINED3DRS_CLIPPLANEENABLE :
2704 case WINED3DRS_CLIPPING :
2706 /* Ensure we only do the changed clip planes */
2707 DWORD enable = 0xFFFFFFFF;
2708 DWORD disable = 0x00000000;
2710 /* If enabling / disabling all */
2711 if (State == WINED3DRS_CLIPPING) {
2712 if (Value) {
2713 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2714 disable = 0x00;
2715 } else {
2716 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2717 enable = 0x00;
2719 } else {
2720 enable = Value & ~OldValue;
2721 disable = ~Value & OldValue;
2724 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2725 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2726 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2727 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2728 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2729 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2731 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2732 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2733 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2734 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2735 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2736 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2738 /** update clipping status */
2739 if (enable) {
2740 This->stateBlock->clip_status.ClipUnion = 0;
2741 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
2742 } else {
2743 This->stateBlock->clip_status.ClipUnion = 0;
2744 This->stateBlock->clip_status.ClipIntersection = 0;
2747 break;
2749 case WINED3DRS_BLENDOP :
2751 int glParm = GL_FUNC_ADD;
2753 switch ((D3DBLENDOP) Value) {
2754 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2755 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2756 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2757 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2758 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2759 default:
2760 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2762 TRACE("glBlendEquation(%x)\n", glParm);
2763 glBlendEquation(glParm);
2764 checkGLcall("glBlendEquation");
2766 break;
2768 case WINED3DRS_TEXTUREFACTOR :
2770 unsigned int i;
2772 /* Note the texture color applies to all textures whereas
2773 GL_TEXTURE_ENV_COLOR applies to active only */
2774 float col[4];
2775 D3DCOLORTOGLFLOAT4(Value, col);
2776 /* Set the default alpha blend color */
2777 glBlendColor(col[0], col[1], col[2], col[3]);
2778 checkGLcall("glBlendColor");
2780 /* And now the default texture color as well */
2781 for (i = 0; i < GL_LIMITS(textures); i++) {
2783 /* Note the D3DRS value applies to all textures, but GL has one
2784 per texture, so apply it now ready to be used! */
2785 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2786 GLACTIVETEXTURE(i);
2787 } else if (i>0) {
2788 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2791 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2792 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2795 break;
2797 case WINED3DRS_SPECULARENABLE :
2799 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2800 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2801 specular color. This is wrong:
2802 Separate specular color means the specular colour is maintained separately, whereas
2803 single color means it is merged in. However in both cases they are being used to
2804 some extent.
2805 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2806 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2807 running 1.4 yet!
2809 if (Value) {
2810 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2811 checkGLcall("glMaterialfv");
2812 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2813 glEnable(GL_COLOR_SUM_EXT);
2814 } else {
2815 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2817 checkGLcall("glEnable(GL_COLOR_SUM)");
2818 } else {
2819 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2821 /* for the case of enabled lighting: */
2822 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2823 checkGLcall("glMaterialfv");
2825 /* for the case of disabled lighting: */
2826 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2827 glDisable(GL_COLOR_SUM_EXT);
2828 } else {
2829 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2831 checkGLcall("glDisable(GL_COLOR_SUM)");
2834 break;
2836 case WINED3DRS_STENCILENABLE :
2837 if (Value) {
2838 glEnable(GL_STENCIL_TEST);
2839 checkGLcall("glEnable GL_STENCIL_TEST");
2840 } else {
2841 glDisable(GL_STENCIL_TEST);
2842 checkGLcall("glDisable GL_STENCIL_TEST");
2844 break;
2846 case WINED3DRS_STENCILFUNC :
2848 int glParm = GL_ALWAYS;
2849 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2850 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2852 switch ((D3DCMPFUNC) Value) {
2853 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2854 case D3DCMP_LESS: glParm=GL_LESS; break;
2855 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2856 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2857 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2858 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2859 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2860 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2861 default:
2862 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2864 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2865 This->stencilfunc = glParm;
2866 glStencilFunc(glParm, ref, mask);
2867 checkGLcall("glStencilFunc");
2869 break;
2871 case WINED3DRS_STENCILREF :
2873 int glParm = This->stencilfunc;
2874 int ref = 0;
2875 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2877 ref = Value;
2878 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2879 glStencilFunc(glParm, ref, mask);
2880 checkGLcall("glStencilFunc");
2882 break;
2884 case WINED3DRS_STENCILMASK :
2886 int glParm = This->stencilfunc;
2887 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2888 GLuint mask = Value;
2890 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2891 glStencilFunc(glParm, ref, mask);
2892 checkGLcall("glStencilFunc");
2894 break;
2896 case WINED3DRS_STENCILFAIL :
2898 GLenum fail ;
2899 GLint zpass ;
2900 GLint zfail ;
2902 fail = StencilOp(Value);
2903 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2904 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2905 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2906 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2908 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2909 glStencilOp(fail, zfail, zpass);
2910 checkGLcall("glStencilOp(fail, zfail, zpass);");
2912 break;
2913 case WINED3DRS_STENCILZFAIL :
2915 GLint fail ;
2916 GLint zpass ;
2917 GLenum zfail ;
2919 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2920 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2921 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2922 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2923 zfail = StencilOp(Value);
2925 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2926 glStencilOp(fail, zfail, zpass);
2927 checkGLcall("glStencilOp(fail, zfail, zpass);");
2929 break;
2930 case WINED3DRS_STENCILPASS :
2932 GLint fail ;
2933 GLenum zpass ;
2934 GLint zfail ;
2936 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2937 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2938 zpass = StencilOp(Value);
2939 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2940 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2942 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2943 glStencilOp(fail, zfail, zpass);
2944 checkGLcall("glStencilOp(fail, zfail, zpass);");
2946 break;
2948 case WINED3DRS_STENCILWRITEMASK :
2950 glStencilMask(Value);
2951 TRACE("glStencilMask(%lu)\n", Value);
2952 checkGLcall("glStencilMask");
2954 break;
2956 case WINED3DRS_FOGENABLE :
2958 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2959 glEnable(GL_FOG);
2960 checkGLcall("glEnable GL_FOG");
2961 } else {
2962 glDisable(GL_FOG);
2963 checkGLcall("glDisable GL_FOG");
2966 break;
2968 case WINED3DRS_RANGEFOGENABLE :
2970 if (Value) {
2971 TRACE("Enabled RANGEFOG");
2972 } else {
2973 TRACE("Disabled RANGEFOG");
2976 break;
2978 case WINED3DRS_FOGCOLOR :
2980 float col[4];
2981 D3DCOLORTOGLFLOAT4(Value, col);
2982 /* Set the default alpha blend color */
2983 glFogfv(GL_FOG_COLOR, &col[0]);
2984 checkGLcall("glFog GL_FOG_COLOR");
2986 break;
2988 case WINED3DRS_FOGTABLEMODE :
2990 glHint(GL_FOG_HINT, GL_NICEST);
2991 switch (Value) {
2992 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2993 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2994 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2995 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2996 default:
2997 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
2999 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3000 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3003 break;
3005 case WINED3DRS_FOGVERTEXMODE :
3007 glHint(GL_FOG_HINT, GL_FASTEST);
3008 switch (Value) {
3009 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3010 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3011 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3012 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3013 default:
3014 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3016 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3017 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
3020 break;
3022 case WINED3DRS_FOGSTART :
3024 tmpvalue.d = Value;
3025 glFogfv(GL_FOG_START, &tmpvalue.f);
3026 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3027 TRACE("Fog Start == %f\n", tmpvalue.f);
3029 break;
3031 case WINED3DRS_FOGEND :
3033 tmpvalue.d = Value;
3034 glFogfv(GL_FOG_END, &tmpvalue.f);
3035 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3036 TRACE("Fog End == %f\n", tmpvalue.f);
3038 break;
3040 case WINED3DRS_FOGDENSITY :
3042 tmpvalue.d = Value;
3043 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3044 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3046 break;
3048 case WINED3DRS_VERTEXBLEND :
3050 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3051 TRACE("Vertex Blending state to %ld\n", Value);
3053 break;
3055 case WINED3DRS_TWEENFACTOR :
3057 tmpvalue.d = Value;
3058 This->updateStateBlock->tween_factor = tmpvalue.f;
3059 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3061 break;
3063 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
3065 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3067 break;
3069 case WINED3DRS_COLORVERTEX :
3070 case WINED3DRS_DIFFUSEMATERIALSOURCE :
3071 case WINED3DRS_SPECULARMATERIALSOURCE :
3072 case WINED3DRS_AMBIENTMATERIALSOURCE :
3073 case WINED3DRS_EMISSIVEMATERIALSOURCE :
3075 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3077 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3078 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3079 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3080 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3081 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3082 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3084 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3085 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3086 Parm = GL_AMBIENT_AND_DIFFUSE;
3087 } else {
3088 Parm = GL_DIFFUSE;
3090 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3091 Parm = GL_AMBIENT;
3092 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3093 Parm = GL_EMISSION;
3094 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3095 Parm = GL_SPECULAR;
3096 } else {
3097 Parm = -1;
3100 if (Parm == -1) {
3101 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3102 } else {
3103 This->tracking_color = NEEDS_TRACKING;
3104 This->tracking_parm = Parm;
3107 } else {
3108 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3111 break;
3113 case WINED3DRS_LINEPATTERN :
3115 union {
3116 DWORD d;
3117 D3DLINEPATTERN lp;
3118 } tmppattern;
3119 tmppattern.d = Value;
3121 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3123 if (tmppattern.lp.wRepeatFactor) {
3124 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3125 checkGLcall("glLineStipple(repeat, linepattern)");
3126 glEnable(GL_LINE_STIPPLE);
3127 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3128 } else {
3129 glDisable(GL_LINE_STIPPLE);
3130 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3133 break;
3135 case WINED3DRS_ZBIAS :
3137 if (Value) {
3138 tmpvalue.d = Value;
3139 TRACE("ZBias value %f\n", tmpvalue.f);
3140 glPolygonOffset(0, -tmpvalue.f);
3141 checkGLcall("glPolygonOffset(0, -Value)");
3142 glEnable(GL_POLYGON_OFFSET_FILL);
3143 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3144 glEnable(GL_POLYGON_OFFSET_LINE);
3145 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3146 glEnable(GL_POLYGON_OFFSET_POINT);
3147 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3148 } else {
3149 glDisable(GL_POLYGON_OFFSET_FILL);
3150 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3151 glDisable(GL_POLYGON_OFFSET_LINE);
3152 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3153 glDisable(GL_POLYGON_OFFSET_POINT);
3154 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3157 break;
3159 case WINED3DRS_NORMALIZENORMALS :
3160 if (Value) {
3161 glEnable(GL_NORMALIZE);
3162 checkGLcall("glEnable(GL_NORMALIZE);");
3163 } else {
3164 glDisable(GL_NORMALIZE);
3165 checkGLcall("glDisable(GL_NORMALIZE);");
3167 break;
3169 case WINED3DRS_POINTSIZE :
3170 tmpvalue.d = Value;
3171 TRACE("Set point size to %f\n", tmpvalue.f);
3172 glPointSize(tmpvalue.f);
3173 checkGLcall("glPointSize(...);");
3174 break;
3176 case WINED3DRS_POINTSIZE_MIN :
3177 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3178 tmpvalue.d = Value;
3179 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3180 checkGLcall("glPointParameterfEXT(...);");
3181 } else {
3182 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3184 break;
3186 case WINED3DRS_POINTSIZE_MAX :
3187 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3188 tmpvalue.d = Value;
3189 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3190 checkGLcall("glPointParameterfEXT(...);");
3191 } else {
3192 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3194 break;
3196 case WINED3DRS_POINTSCALE_A :
3197 case WINED3DRS_POINTSCALE_B :
3198 case WINED3DRS_POINTSCALE_C :
3199 case WINED3DRS_POINTSCALEENABLE :
3201 /* If enabled, supply the parameters, otherwise fall back to defaults */
3202 if (This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3203 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3204 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]);
3205 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]);
3206 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]);
3208 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3209 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3210 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3211 } else {
3212 TRACE("WINED3DRS_POINTSCALEENABLE not supported on this opengl\n");
3214 } else {
3215 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3216 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3217 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3218 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3219 } else {
3220 TRACE("WINED3DRS_POINTSCALEENABLE not supported, but not on either\n");
3223 break;
3226 case WINED3DRS_COLORWRITEENABLE :
3228 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3229 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3230 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3231 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3232 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3233 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3234 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3235 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3236 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3237 checkGLcall("glColorMask(...)");
3239 break;
3241 case WINED3DRS_LOCALVIEWER :
3243 GLint state = (Value) ? 1 : 0;
3244 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3245 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3247 break;
3249 case WINED3DRS_LASTPIXEL :
3251 if (Value) {
3252 TRACE("Last Pixel Drawing Enabled\n");
3253 } else {
3254 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3257 break;
3259 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3261 if (Value) {
3262 TRACE("Software Processing Enabled\n");
3263 } else {
3264 TRACE("Software Processing Disabled\n");
3267 break;
3269 /** not supported */
3270 case WINED3DRS_ZVISIBLE :
3272 LEAVE_GL();
3273 return D3DERR_INVALIDCALL;
3276 /* Unhandled yet...! */
3277 case WINED3DRS_EDGEANTIALIAS :
3278 case WINED3DRS_WRAP0 :
3279 case WINED3DRS_WRAP1 :
3280 case WINED3DRS_WRAP2 :
3281 case WINED3DRS_WRAP3 :
3282 case WINED3DRS_WRAP4 :
3283 case WINED3DRS_WRAP5 :
3284 case WINED3DRS_WRAP6 :
3285 case WINED3DRS_WRAP7 :
3286 case WINED3DRS_POINTSPRITEENABLE :
3287 case WINED3DRS_MULTISAMPLEANTIALIAS :
3288 case WINED3DRS_MULTISAMPLEMASK :
3289 case WINED3DRS_PATCHEDGESTYLE :
3290 case WINED3DRS_PATCHSEGMENTS :
3291 case WINED3DRS_DEBUGMONITORTOKEN :
3292 case WINED3DRS_POSITIONORDER :
3293 case WINED3DRS_NORMALORDER :
3294 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3295 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3296 break;
3297 default:
3298 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3301 LEAVE_GL();
3303 return D3D_OK;
3306 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3307 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3308 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3309 *pValue = This->stateBlock->renderState[State];
3310 return D3D_OK;
3313 /*****
3314 * Get / Set Sampler States
3315 * TODO: Verify against dx9 definitions
3316 *****/
3318 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3319 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3321 * SetSampler is designed to allow for more than the standard up to 8 textures
3322 * and Geforce has stopped supporting more than 6 standard textures in openGL.
3323 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3325 * http://developer.nvidia.com/object/General_FAQ.html#t6
3327 * There are two new settings for GForce
3328 * the sampler one:
3329 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3330 * and the texture one:
3331 * GL_MAX_TEXTURE_COORDS_ARB.
3332 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3333 ******************/
3334 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
3335 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
3337 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
3338 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE, Sampler, Type);
3339 return D3DERR_INVALIDCALL;
3341 TRACE("Setting sampler %ld %d to %ld \n", Sampler, Type, Value);
3342 This->updateStateBlock->samplerState[Sampler][Type] = Value;
3344 /* Handle recording of state blocks */
3345 if (This->isRecordingState) {
3346 TRACE("Recording... not performing anything\n");
3347 return D3D_OK;
3350 return D3D_OK;
3353 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3354 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3355 /** TODO: check that sampler is in range **/
3356 *Value = This->updateStateBlock->samplerState[Sampler][Type];
3357 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
3359 return D3D_OK;
3362 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3363 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3364 ENTER_GL();
3366 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3367 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3368 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3369 LEAVE_GL();
3371 return D3D_OK;
3374 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3375 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3376 GLint scissorBox[4];
3378 ENTER_GL();
3379 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3380 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
3381 pRect->left = scissorBox[1];
3382 pRect->top = scissorBox[2];
3383 pRect->right = scissorBox[1] + scissorBox[3];
3384 pRect->bottom = scissorBox[2] + scissorBox[4];
3385 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3386 LEAVE_GL();
3387 return D3D_OK;
3390 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3391 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3393 TRACE("(%p) : pDecl=%p\n", This, pDecl);
3395 /* TODO: what about recording stateblocks? */
3396 if (NULL != pDecl) {
3397 IWineD3DVertexDeclaration_AddRef(pDecl);
3399 if (NULL != This->updateStateBlock->vertexDecl) {
3400 IWineD3DVertexDeclaration_Release(This->updateStateBlock->vertexDecl);
3402 This->updateStateBlock->vertexDecl = pDecl;
3403 This->updateStateBlock->changed.vertexDecl = TRUE;
3404 This->updateStateBlock->set.vertexDecl = TRUE;
3405 return D3D_OK;
3408 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3409 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3411 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3413 *ppDecl = This->updateStateBlock->vertexDecl;
3414 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3415 return D3D_OK;
3418 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
3419 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3421 static BOOL showFixmes = TRUE;
3423 This->updateStateBlock->vertexShader = pShader;
3424 This->updateStateBlock->changed.vertexShader = TRUE;
3425 This->updateStateBlock->set.vertexShader = TRUE;
3427 if(pShader == NULL) {
3428 /* clear down the shader */
3429 TRACE("Clear down the shader\n");
3430 }else{
3431 if(showFixmes) {
3432 FIXME("(%p) : stub pShader(%p)\n", This, pShader);
3433 showFixmes = FALSE;
3437 return D3D_OK;
3439 /** FIXME: refernece counting? **/
3440 if (pShader == NULL) { /* only valid with non FVF shaders */
3441 TRACE_(d3d_shader)("(%p) : FVF Shader, pShader=%p\n", This, pShader);
3442 This->updateStateBlock->vertexShader = NULL;
3443 } else {
3444 TRACE_(d3d_shader)("(%p) : Created shader, pShader=%p\n", This, pShader);
3445 This->updateStateBlock->vertexShader = pShader;
3448 This->updateStateBlock->changed.vertexShader = TRUE;
3449 This->updateStateBlock->set.vertexShader = TRUE;
3451 /* Handle recording of state blocks */
3452 if (This->isRecordingState) {
3453 TRACE("Recording... not performing anything\n");
3454 return D3D_OK;
3457 * TODO: merge HAL shaders context switching from prototype
3459 return D3D_OK;
3462 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
3463 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3464 *ppShader = This->stateBlock->vertexShader;
3465 if(*ppShader != NULL)
3466 IWineD3DVertexShader_AddRef(*ppShader);
3467 TRACE("(%p) : returning %p\n", This, *ppShader);
3468 return D3D_OK;
3471 #define GET_SHADER_CONSTANT(_vertexshaderconstant, _count, _sizecount) \
3472 int count = min(_count, MAX_VSHADER_CONSTANTS - (StartRegister + 1)); \
3473 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3474 return D3DERR_INVALIDCALL; \
3475 memcpy(pConstantData, This->updateStateBlock->_vertexshaderconstant + (StartRegister * _sizecount), count * (sizeof(*pConstantData) * _sizecount));
3477 #define SET_SHADER_CONSTANT(_vertexshaderconstant, _count, _sizecount) \
3478 int count = min(_count, MAX_VSHADER_CONSTANTS - (StartRegister + 1)); \
3479 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3480 return D3DERR_INVALIDCALL; \
3481 memcpy(This->updateStateBlock->_vertexshaderconstant + (StartRegister * _sizecount), pConstantData, count * (sizeof(*pConstantData) * _sizecount)); \
3482 This->updateStateBlock->changed.vertexShader = TRUE; \
3483 This->updateStateBlock->set.vertexShader = TRUE;
3485 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
3486 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3487 static BOOL showFixmes = TRUE;
3488 SET_SHADER_CONSTANT(vertexShaderConstantB, BoolCount, 1);
3489 #if 0 /* TODO: a bitmasp to say which constant type we should load */
3490 memset(This->updateStateBlock->vsibfBitmap + StartRegister, WINESHADER_CONSTANTB, BoolCount);
3491 #endif
3492 /* clean out the other constants? */
3493 if(showFixmes || TRUE) {
3494 FIXME("(%p) : stub\n", This);
3495 showFixmes = FALSE;
3497 return D3D_OK;
3500 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
3501 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3502 static BOOL showFixmes = TRUE;
3503 #if 0 /* TODO: a bitmasp to say which constant type we should load */
3504 for (i = 0; i < BoolCount; i++ ) {
3505 if (This->updateStateBlock->vsibfBitmap[StartRegister + i] != WINESHADER_CONSTANTB) {
3506 /* the constant for this register isn't a boolean */
3507 return D3DERR_INVALIDCALL;
3510 #endif
3511 GET_SHADER_CONSTANT(vertexShaderConstantB, BoolCount, 1);
3512 if(showFixmes || TRUE) {
3513 FIXME("(%p) : stub\n", This);
3514 showFixmes = FALSE;
3516 return D3D_OK;
3519 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
3520 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3521 static BOOL showFixmes = TRUE;
3522 #if 0 /* TODO: a bitmasp to say which constant type we should load */
3523 memset(This->updateStateBlock->vsibfBitmap + StartRegister, WINESHADER_CONSTANTI, Vector4iCount);
3524 #endif
3525 SET_SHADER_CONSTANT(vertexShaderConstantI, Vector4iCount, 4);
3526 /* clean out the other constants? */
3527 if(showFixmes || TRUE) {
3528 FIXME("(%p) : stub\n", This);
3529 showFixmes = FALSE;
3531 return D3D_OK;
3534 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
3535 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3536 static BOOL showFixmes = TRUE;
3537 #if 0 /* TODO: a bitmap to say which constant type we should load */
3538 for (i = 0; i < Vector4iCount; i++ ) {
3539 if (This->updateStateBlock->vsibfBitmap[StartRegister + i] != WINESHADER_CONSTANTI) {
3540 /* the constant for this register isn't a boolean */
3541 return D3DERR_INVALIDCALL;
3544 #endif
3545 GET_SHADER_CONSTANT(vertexShaderConstantI, Vector4iCount, 4);
3546 if(showFixmes || TRUE) {
3547 FIXME("(%p) : stub\n", This);
3548 showFixmes = FALSE;
3550 return D3D_OK;
3553 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
3554 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3555 static BOOL showFixmes = TRUE;
3556 #if 0 /* TODO: a bitmasp to say which constant type we should load */
3557 memset(This->updateStateBlock->vsibfBitmap + StartRegister, WINESHADER_CONSTANTF, Vector4fCount);
3558 #endif
3559 SET_SHADER_CONSTANT(vertexShaderConstantF, Vector4fCount, 4);
3560 /* clean out the other constants? */
3561 if(showFixmes) {
3562 TRACE("(%p) : ConstantF isn't intergrated properly with the other constants.\n", This);
3563 showFixmes = FALSE;
3565 return D3D_OK;
3568 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
3569 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3570 static BOOL showFixmes = TRUE;
3571 #if 0 /* TODO: a bitmap to say which constant type we should load */
3572 for (i = 0; i < Vector4fCount; i++ ) {
3573 if (This->updateStateBlock->vsibfBitmap[StartRegister + i] != WINESHADER_CONSTANTF) {
3574 /* the constant for this register isn't a boolean */
3575 return D3DERR_INVALIDCALL;
3578 #endif
3579 GET_SHADER_CONSTANT(vertexShaderConstantF, Vector4fCount, 4);
3580 if(showFixmes) {
3581 TRACE("(%p) : ConstantF isn't intergrated properly with the other constants.\n", This);
3582 showFixmes = FALSE;
3584 return D3D_OK;
3587 #undef SET_SHADER_CONSTANT
3588 #undef GET_SHADER_CONSTANT
3591 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
3592 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3593 TRACE("(%p) : stub\n", This);
3594 return D3D_OK;
3597 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3598 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3599 TRACE("(%p) : stub\n", This);
3600 return D3D_OK;
3604 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
3605 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3606 TRACE("(%p) : stub\n", This);
3607 return D3D_OK;
3610 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
3611 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3612 TRACE("(%p) : stub\n", This);
3613 return D3D_OK;
3616 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
3617 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3618 TRACE("(%p) : stub\n", This);
3619 return D3D_OK;
3622 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
3623 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3624 TRACE("(%p) : stub\n", This);
3625 return D3D_OK;
3628 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
3629 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3630 TRACE("(%p) : stub\n", This);
3631 return D3D_OK;
3634 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
3635 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3636 TRACE("(%p) : stub\n", This);
3637 return D3D_OK;
3640 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
3641 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3642 FIXME("(%p) : stub\n", This);
3643 return D3D_OK;
3646 /*****
3647 * Apply / Get / Set Texture Stage States
3648 * TODO: Verify against dx9 definitions
3649 *****/
3651 /* NOTE: It's expected that this function is going to be called lots of times with the same stage active, so make it the callers responsibility to GLACTIVETEXTURE(Stage) for better state management. Set the correct Texture unit active before callnig ApplyTextureStageState */
3652 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
3653 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3654 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
3655 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3657 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3659 /* Check that the stage is within limits */
3660 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
3661 TRACE("Attempt to access invalid texture rejected\n");
3662 return;
3665 ENTER_GL();
3667 switch (Type) {
3668 case WINED3DTSS_ALPHAOP :
3669 case WINED3DTSS_COLOROP :
3672 if ((Value == D3DTOP_DISABLE) && (Type == WINED3DTSS_COLOROP)) {
3673 /* TODO: Disable by making this and all later levels disabled */
3674 glDisable(GL_TEXTURE_1D);
3675 checkGLcall("Disable GL_TEXTURE_1D");
3676 glDisable(GL_TEXTURE_2D);
3677 checkGLcall("Disable GL_TEXTURE_2D");
3678 glDisable(GL_TEXTURE_3D);
3679 checkGLcall("Disable GL_TEXTURE_3D");
3680 break; /* Don't bother setting the texture operations */
3681 } else {
3682 /* Enable only the appropriate texture dimension */
3683 if (Type == WINED3DTSS_COLOROP) {
3684 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3685 glEnable(GL_TEXTURE_1D);
3686 checkGLcall("Enable GL_TEXTURE_1D");
3687 } else {
3688 glDisable(GL_TEXTURE_1D);
3689 checkGLcall("Disable GL_TEXTURE_1D");
3691 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3692 if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
3693 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
3694 checkGLcall("Enable GL_TEXTURE_2D");
3695 } else {
3696 glEnable(GL_TEXTURE_2D);
3697 checkGLcall("Enable GL_TEXTURE_2D");
3699 } else {
3700 glDisable(GL_TEXTURE_2D);
3701 checkGLcall("Disable GL_TEXTURE_2D");
3703 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3704 glEnable(GL_TEXTURE_3D);
3705 checkGLcall("Enable GL_TEXTURE_3D");
3706 } else {
3707 glDisable(GL_TEXTURE_3D);
3708 checkGLcall("Disable GL_TEXTURE_3D");
3710 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3711 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3712 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3713 } else {
3714 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3715 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3719 /* Drop through... (Except disable case) */
3720 case WINED3DTSS_COLORARG0 :
3721 case WINED3DTSS_COLORARG1 :
3722 case WINED3DTSS_COLORARG2 :
3723 case WINED3DTSS_ALPHAARG0 :
3724 case WINED3DTSS_ALPHAARG1 :
3725 case WINED3DTSS_ALPHAARG2 :
3727 BOOL isAlphaArg = (Type == WINED3DTSS_ALPHAOP || Type == WINED3DTSS_ALPHAARG1 ||
3728 Type == WINED3DTSS_ALPHAARG2 || Type == WINED3DTSS_ALPHAARG0);
3729 if (isAlphaArg) {
3730 set_tex_op(iface, TRUE, Stage, This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAOP],
3731 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG1],
3732 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG2],
3733 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG0]);
3734 } else {
3735 set_tex_op(iface, FALSE, Stage, This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP],
3736 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG1],
3737 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG2],
3738 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG0]);
3741 break;
3744 case WINED3DTSS_ADDRESSW :
3746 GLint wrapParm = GL_REPEAT;
3748 switch (Value) {
3749 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3750 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3751 case D3DTADDRESS_BORDER:
3753 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3754 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3755 } else {
3756 /* FIXME: Not right, but better */
3757 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3758 wrapParm = GL_REPEAT;
3761 break;
3762 case D3DTADDRESS_MIRROR:
3764 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3765 wrapParm = GL_MIRRORED_REPEAT_ARB;
3766 } else {
3767 /* Unsupported in OpenGL pre-1.4 */
3768 FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3769 wrapParm = GL_REPEAT;
3772 break;
3773 case D3DTADDRESS_MIRRORONCE:
3775 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3776 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3777 } else {
3778 FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3779 wrapParm = GL_REPEAT;
3782 break;
3784 default:
3785 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3786 wrapParm = GL_REPEAT;
3789 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
3790 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3791 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3793 break;
3795 case WINED3DTSS_TEXCOORDINDEX :
3797 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3799 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
3800 one flag, you can still specify an index value, which the system uses to
3801 determine the texture wrapping mode.
3802 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3803 means use the vertex position (camera-space) as the input texture coordinates
3804 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
3805 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3806 to the TEXCOORDINDEX value */
3809 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3811 switch (Value & 0xFFFF0000) {
3812 case D3DTSS_TCI_PASSTHRU:
3813 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3814 glDisable(GL_TEXTURE_GEN_S);
3815 glDisable(GL_TEXTURE_GEN_T);
3816 glDisable(GL_TEXTURE_GEN_R);
3817 glDisable(GL_TEXTURE_GEN_Q);
3818 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3819 break;
3821 case D3DTSS_TCI_CAMERASPACEPOSITION:
3822 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3823 as the input texture coordinates for this stage's texture transformation. This
3824 equates roughly to EYE_LINEAR */
3826 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3827 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3828 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3829 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3830 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3832 glMatrixMode(GL_MODELVIEW);
3833 glPushMatrix();
3834 glLoadIdentity();
3835 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3836 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3837 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3838 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3839 glPopMatrix();
3841 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3842 glEnable(GL_TEXTURE_GEN_S);
3843 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3844 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3845 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3846 glEnable(GL_TEXTURE_GEN_T);
3847 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3848 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3849 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3850 glEnable(GL_TEXTURE_GEN_R);
3851 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3852 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3853 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3855 break;
3857 case D3DTSS_TCI_CAMERASPACENORMAL:
3859 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3860 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3861 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3862 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3863 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3864 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3866 glMatrixMode(GL_MODELVIEW);
3867 glPushMatrix();
3868 glLoadIdentity();
3869 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3870 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3871 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3872 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3873 glPopMatrix();
3875 glEnable(GL_TEXTURE_GEN_S);
3876 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3877 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3878 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3879 glEnable(GL_TEXTURE_GEN_T);
3880 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3881 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3882 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3883 glEnable(GL_TEXTURE_GEN_R);
3884 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3885 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3886 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3889 break;
3891 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3893 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3894 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3895 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3896 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3897 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3898 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3900 glMatrixMode(GL_MODELVIEW);
3901 glPushMatrix();
3902 glLoadIdentity();
3903 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3904 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3905 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3906 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3907 glPopMatrix();
3909 glEnable(GL_TEXTURE_GEN_S);
3910 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3911 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3912 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3913 glEnable(GL_TEXTURE_GEN_T);
3914 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3915 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3916 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3917 glEnable(GL_TEXTURE_GEN_R);
3918 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3919 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3920 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3923 break;
3925 /* Unhandled types: */
3926 default:
3927 /* Todo: */
3928 /* ? disable GL_TEXTURE_GEN_n ? */
3929 glDisable(GL_TEXTURE_GEN_S);
3930 glDisable(GL_TEXTURE_GEN_T);
3931 glDisable(GL_TEXTURE_GEN_R);
3932 glDisable(GL_TEXTURE_GEN_Q);
3933 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
3934 break;
3937 break;
3939 /* Unhandled */
3940 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
3941 set_texture_matrix((float *)&This->stateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value, (This->stateBlock->textureState[Stage][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU);
3942 break;
3944 case WINED3DTSS_BUMPENVMAT00 :
3945 case WINED3DTSS_BUMPENVMAT01 :
3946 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
3947 break;
3948 case WINED3DTSS_BUMPENVMAT10 :
3949 case WINED3DTSS_BUMPENVMAT11 :
3950 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
3951 break;
3953 case WINED3DTSS_BUMPENVLSCALE :
3954 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3955 break;
3957 case WINED3DTSS_BUMPENVLOFFSET :
3958 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3959 break;
3961 case WINED3DTSS_RESULTARG :
3962 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3963 break;
3965 default:
3966 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3967 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3970 LEAVE_GL();
3972 return;
3975 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3976 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3978 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3980 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3982 /* Reject invalid texture units */
3983 if (Stage >= GL_LIMITS(textures)) {
3984 TRACE("Attempt to access invalid texture rejected\n");
3985 return D3DERR_INVALIDCALL;
3988 This->updateStateBlock->textureState[Stage][Type] = Value;
3990 return D3D_OK;
3993 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
3994 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3995 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
3996 *pValue = This->updateStateBlock->textureState[Stage][Type];
3997 return D3D_OK;
4000 /*****
4001 * Get / Set Texture
4002 *****/
4003 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4005 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4006 IWineD3DBaseTexture *oldTexture;
4008 oldTexture = This->updateStateBlock->textures[Stage];
4009 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
4011 #if 0 /* TODO: check so vertex textures */
4012 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
4013 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
4014 return D3D_OK;
4016 #endif
4018 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4019 WARN("Attempt to access invalid texture rejected\n");
4020 return D3DERR_INVALIDCALL;
4023 oldTexture = This->updateStateBlock->textures[Stage];
4024 TRACE("GL_LIMITS %d\n",GL_LIMITS(textures));
4025 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
4027 This->updateStateBlock->set.textures[Stage] = TRUE;
4028 This->updateStateBlock->changed.textures[Stage] = TRUE;
4029 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
4030 This->updateStateBlock->textures[Stage] = pTexture;
4032 /* Handle recording of state blocks */
4033 if (This->isRecordingState) {
4034 TRACE("Recording... not performing anything\n");
4035 return D3D_OK;
4038 /** NOTE: MSDN says that setTexture increases the reference count,
4039 * and the the application nust set the texture back to null (or have a leaky application),
4040 * This means we should pass the refcount upto the parent
4041 *******************************/
4042 if (NULL != This->updateStateBlock->textures[Stage]) {
4043 IUnknown *textureParent;
4044 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[Stage], (IUnknown **)&textureParent);
4045 /** NOTE: GetParent will increase the ref count for me, I won't clean up until the texture is set to NULL **/
4048 if (NULL != oldTexture) {
4049 IUnknown *textureParent;
4050 IWineD3DBaseTexture_GetParent(oldTexture, (IUnknown **)&textureParent);
4051 IUnknown_Release(textureParent);
4052 IUnknown_Release(textureParent); /** NOTE: Twice because GetParent adds a ref **/
4053 oldTexture = NULL;
4056 return D3D_OK;
4059 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4060 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4061 TRACE("(%p) : returning %p for stage %ld\n", This, This->updateStateBlock->textures[Stage], Stage);
4062 *ppTexture = (IWineD3DBaseTexture *) This->updateStateBlock->textures[Stage];
4063 if (*ppTexture)
4064 IWineD3DBaseTexture_AddRef(*ppTexture);
4065 return D3D_OK;
4068 /*****
4069 * Get Back Buffer
4070 *****/
4071 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type,
4072 IWineD3DSurface** ppBackBuffer) {
4073 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4074 IWineD3DSwapChain *swapChain;
4075 HRESULT hr;
4077 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4079 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4080 if(hr == D3D_OK) {
4081 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4082 IWineD3DSwapChain_Release(swapChain);
4083 }else{
4084 *ppBackBuffer = NULL;
4086 return hr;
4089 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4090 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4091 WARN("(%p) : stub, calling idirect3d for now\n", This);
4092 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4095 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
4096 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4097 IWineD3DSwapChain *swapChain;
4098 HRESULT hr;
4100 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4101 if (hr == D3D_OK) {
4102 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4103 IWineD3DSwapChain_Release(swapChain);
4104 }else{
4105 FIXME("(%p) Error getting display mode\n", This);
4107 return hr;
4109 /*****
4110 * Stateblock related functions
4111 *****/
4113 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4114 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4115 IWineD3DStateBlockImpl *object;
4116 TRACE("(%p)", This);
4117 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4118 if(NULL == object ) {
4119 FIXME("(%p)Error allocating memory for stateblock\n", This);
4120 return E_OUTOFMEMORY;
4122 TRACE("(%p) creted object %p\n", This, object);
4123 object->wineD3DDevice= This;
4124 /** FIXME: object->parent = parent; **/
4125 object->parent = NULL;
4126 object->blockType = WINED3DSBT_ALL;
4127 object->ref = 1;
4128 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
4130 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4131 This->updateStateBlock = object;
4132 This->isRecordingState = TRUE;
4134 TRACE("(%p) recording stateblock %p\n",This , object);
4135 return D3D_OK;
4138 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4139 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4141 if (!This->isRecordingState) {
4142 FIXME("(%p) not recording! returning error\n", This);
4143 *ppStateBlock = NULL;
4144 return D3DERR_INVALIDCALL;
4147 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4148 This->isRecordingState = FALSE;
4149 This->updateStateBlock = This->stateBlock;
4150 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4151 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4152 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4153 return D3D_OK;
4156 /*****
4157 * Scene related functions
4158 *****/
4159 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4160 /* At the moment we have no need for any functionality at the beginning
4161 of a scene */
4162 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4163 TRACE("(%p) : stub\n", This);
4164 return D3D_OK;
4167 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4168 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4169 TRACE("(%p)\n", This);
4170 ENTER_GL();
4171 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4172 glFlush();
4173 checkGLcall("glFlush");
4175 TRACE("End Scene\n");
4176 if(This->renderTarget != NULL) {
4178 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4179 IUnknown *targetContainer = NULL;
4180 if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
4181 || D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
4182 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
4183 /** always dirtify for now. we must find a better way to see that surface have been modified
4184 (Modifications should will only occur via draw-primitive, but we do need better locking
4185 switching to render-to-texture should remove the overhead though.
4187 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4188 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
4189 IWineD3DSurface_PreLoad(This->renderTarget);
4190 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4191 IUnknown_Release(targetContainer);
4194 This->sceneEnded = TRUE;
4195 LEAVE_GL();
4196 return D3D_OK;
4199 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4200 CONST RECT* pSourceRect, CONST RECT* pDestRect,
4201 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4202 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4203 IWineD3DSwapChain *swapChain = NULL;
4204 int i;
4205 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4207 TRACE("(%p) Presenting the frame\n", This);
4209 for(i = 0 ; i < swapchains ; i ++) {
4211 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4212 TRACE("presentinng chain %d, %p\n", i, swapChain);
4213 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4214 IWineD3DSwapChain_Release(swapChain);
4217 return D3D_OK;
4220 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4221 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4222 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4224 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4225 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4226 when the depth-buffer format does not contain stencil buffer information, this method fails. */
4227 GLbitfield glMask = 0;
4228 GLboolean old_ztest;
4229 GLfloat old_z_clear_value;
4230 GLint old_stencil_clear_value;
4231 GLfloat old_color_clear_value[4];
4232 unsigned int i;
4233 CONST D3DRECT* curRect;
4235 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4236 Count, pRects, Flags, Z, Stencil);
4238 ENTER_GL();
4240 glEnable(GL_SCISSOR_TEST);
4241 checkGLcall("glEnable GL_SCISSOR_TEST");
4243 if (Count > 0 && pRects) {
4244 curRect = pRects;
4245 } else {
4246 curRect = NULL;
4249 /* Only set the values up once, as they are not changing */
4250 if (Flags & D3DCLEAR_STENCIL) {
4251 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4252 glClearStencil(Stencil);
4253 checkGLcall("glClearStencil");
4254 glMask = glMask | GL_STENCIL_BUFFER_BIT;
4255 glStencilMask(0xFFFFFFFF);
4258 if (Flags & D3DCLEAR_ZBUFFER) {
4259 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4260 glDepthMask(GL_TRUE);
4261 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4262 glClearDepth(Z);
4263 checkGLcall("glClearDepth");
4264 glMask = glMask | GL_DEPTH_BUFFER_BIT;
4267 if (Flags & D3DCLEAR_TARGET) {
4268 TRACE("Clearing screen with glClear to color %lx\n", Color);
4269 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4270 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
4271 ((Color >> 8) & 0xFF) / 255.0f,
4272 ((Color >> 0) & 0xFF) / 255.0f,
4273 ((Color >> 24) & 0xFF) / 255.0f);
4274 checkGLcall("glClearColor");
4276 /* Clear ALL colors! */
4277 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4278 glMask = glMask | GL_COLOR_BUFFER_BIT;
4281 /* Now process each rect in turn */
4282 for (i = 0; i < Count || i == 0; i++) {
4284 if (curRect) {
4285 /* Note gl uses lower left, width/height */
4286 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4287 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4288 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4289 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4290 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4291 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4292 checkGLcall("glScissor");
4293 } else {
4294 glScissor(This->stateBlock->viewport.X,
4295 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4296 This->stateBlock->viewport.Width,
4297 This->stateBlock->viewport.Height);
4298 checkGLcall("glScissor");
4301 /* Clear the selected rectangle (or full screen) */
4302 glClear(glMask);
4303 checkGLcall("glClear");
4305 /* Step to the next rectangle */
4306 if (curRect) curRect = curRect + sizeof(D3DRECT);
4309 /* Restore the old values (why..?) */
4310 if (Flags & D3DCLEAR_STENCIL) {
4311 glClearStencil(old_stencil_clear_value);
4312 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4314 if (Flags & D3DCLEAR_ZBUFFER) {
4315 glDepthMask(old_ztest);
4316 glClearDepth(old_z_clear_value);
4318 if (Flags & D3DCLEAR_TARGET) {
4319 glClearColor(old_color_clear_value[0],
4320 old_color_clear_value[1],
4321 old_color_clear_value[2],
4322 old_color_clear_value[3]);
4323 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4324 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4325 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4326 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4329 glDisable(GL_SCISSOR_TEST);
4330 checkGLcall("glDisable");
4331 LEAVE_GL();
4333 return D3D_OK;
4336 /*****
4337 * Drawing functions
4338 *****/
4339 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4340 UINT PrimitiveCount) {
4342 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4343 This->stateBlock->streamIsUP = FALSE;
4345 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4346 debug_d3dprimitivetype(PrimitiveType),
4347 StartVertex, PrimitiveCount);
4348 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
4350 return D3D_OK;
4353 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4354 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4355 D3DPRIMITIVETYPE PrimitiveType,
4356 INT baseVIndex, UINT minIndex,
4357 UINT NumVertices,UINT startIndex,UINT primCount) {
4359 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4360 UINT idxStride = 2;
4361 IWineD3DIndexBuffer *pIB;
4362 D3DINDEXBUFFER_DESC IdxBufDsc;
4364 pIB = This->stateBlock->pIndexData;
4365 This->stateBlock->streamIsUP = FALSE;
4367 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d \n", This,
4368 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4369 minIndex, NumVertices, startIndex, baseVIndex, primCount);
4371 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4372 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4373 idxStride = 2;
4374 } else {
4375 idxStride = 4;
4378 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex,
4379 startIndex, idxStride,
4380 ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory,
4381 minIndex);
4383 return D3D_OK;
4386 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4387 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4388 UINT VertexStreamZeroStride) {
4389 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4391 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4392 debug_d3dprimitivetype(PrimitiveType),
4393 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4395 if (This->stateBlock->streamSource[0] != NULL) {
4396 IUnknown *vertexBufferParent;
4397 IWineD3DVertexBuffer_GetParent(This->stateBlock->streamSource[0], &vertexBufferParent);
4398 IUnknown_Release(vertexBufferParent);
4399 IUnknown_Release(vertexBufferParent);
4402 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4403 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4404 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4405 This->stateBlock->streamIsUP = TRUE;
4406 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
4407 This->stateBlock->streamStride[0] = 0;
4408 This->stateBlock->streamSource[0] = NULL;
4410 /*stream zero settings set to null at end, as per the msdn */
4411 return D3D_OK;
4414 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4415 UINT MinVertexIndex,
4416 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
4417 WINED3DFORMAT IndexDataFormat, CONST void* pVertexStreamZeroData,
4418 UINT VertexStreamZeroStride) {
4419 int idxStride;
4420 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4422 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4423 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4424 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData,
4425 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4427 if (IndexDataFormat == WINED3DFMT_INDEX16) {
4428 idxStride = 2;
4429 } else {
4430 idxStride = 4;
4433 if (This->stateBlock->streamSource[0] != NULL) {
4434 IUnknown *vertexBufferParent;
4435 IWineD3DVertexBuffer_GetParent(This->stateBlock->streamSource[0], &vertexBufferParent);
4436 This->stateBlock->streamSource[0] = NULL;
4437 IUnknown_Release(vertexBufferParent);
4438 IUnknown_Release(vertexBufferParent);
4441 if (This->stateBlock->pIndexData) {
4442 IUnknown *indexBufferParent;
4443 IWineD3DIndexBuffer_GetParent(This->stateBlock->pIndexData, &indexBufferParent);
4444 This->stateBlock->pIndexData = NULL;
4445 IUnknown_Release(indexBufferParent);
4446 IUnknown_Release(indexBufferParent);
4449 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4450 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4451 This->stateBlock->streamIsUP = TRUE;
4452 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4454 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, idxStride, pIndexData, MinVertexIndex);
4456 /* stream zero settings set to null at end as per the msdn */
4457 This->stateBlock->streamSource[0] = NULL;
4458 This->stateBlock->streamStride[0] = 0;
4460 return D3D_OK;
4463 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4464 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
4465 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4466 D3DRESOURCETYPE sourceType;
4467 D3DRESOURCETYPE destinationType;
4468 IWineD3DTextureImpl *pDestTexture = (IWineD3DTextureImpl *)pDestinationTexture;
4469 IWineD3DTextureImpl *pSrcTexture = (IWineD3DTextureImpl *)pSourceTexture;
4470 int i;
4472 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
4473 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
4474 if(sourceType != D3DRTYPE_TEXTURE && destinationType != D3DRTYPE_TEXTURE){
4475 FIXME("(%p) Only D3DRTYPE_TEXTURE to D3DRTYPE_TEXTURE supported\n", This);
4476 return D3DERR_INVALIDCALL;
4478 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
4480 /** TODO: Get rid of the casts to IWineD3DBaseTextureImpl
4481 repalce surfaces[x] with GetSurfaceLevel, or GetCubeMapSurface etc..
4482 think about moving the code into texture, and adding a member to base texture to occomplish this **/
4484 /* Make sure that the destination texture is loaded */
4485 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
4486 TRACE("Loading source texture\n");
4488 if(pSrcTexture->surfaces[0] == NULL || pDestTexture->surfaces[0] == NULL){
4489 FIXME("(%p) Texture src %p or dest %p has not surface %p %p\n", This, pSrcTexture, pDestTexture,
4490 pSrcTexture->surfaces[0], pDestTexture->surfaces[0]);
4493 if(((IWineD3DSurfaceImpl *)pSrcTexture->surfaces[0])->resource.pool != D3DPOOL_SYSTEMMEM ||
4494 ((IWineD3DSurfaceImpl *)pDestTexture->surfaces[0])->resource.pool != D3DPOOL_DEFAULT){
4496 FIXME("(%p) source %p must be SYSTEMMEM and dest %p must be DEFAULT\n",This, pSrcTexture, pDestTexture);
4497 return D3DERR_INVALIDCALL;
4499 /** TODO: check that both textures have the same number of levels **/
4500 #if 0
4501 if(IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) !=IWineD3DBaseTexture_GetLevelCount(pSourceTexture))
4502 return D3DERR_INVALIDCALL;
4503 #endif
4504 /** TODO: move this code into baseTexture? device should never touch impl*'s **/
4505 for(i = 0 ; i < IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) ; i++){
4506 IWineD3DDevice_UpdateSurface(iface, pSrcTexture->surfaces[i], NULL, pDestTexture->surfaces[i], NULL);
4509 return D3D_OK;
4512 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
4513 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
4514 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
4515 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4517 TRACE("(%p) : stub\n", This);
4518 return D3D_OK;
4520 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
4521 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4523 TRACE("(%p) : stub\n", This);
4524 return D3D_OK;
4527 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
4528 IWineD3DSwapChain *swapChain;
4529 HRESULT hr;
4530 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4531 if(hr == D3D_OK) {
4532 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
4533 IWineD3DSwapChain_Release(swapChain);
4535 return hr;
4538 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4539 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4540 /* return a sensible default */
4541 *pNumPasses = 1;
4542 FIXME("(%p) : stub\n", This);
4543 return D3D_OK;
4546 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4547 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4548 int j;
4549 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4550 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4551 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4552 return D3DERR_INVALIDCALL;
4554 for (j = 0; j < 256; ++j) {
4555 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
4556 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
4557 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
4558 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
4560 TRACE("(%p) : returning\n", This);
4561 return D3D_OK;
4564 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4565 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4566 int j;
4567 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4568 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4569 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4570 return D3DERR_INVALIDCALL;
4572 for (j = 0; j < 256; ++j) {
4573 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
4574 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
4575 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
4576 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
4578 TRACE("(%p) : returning\n", This);
4579 return D3D_OK;
4582 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4583 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4584 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4585 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4586 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4587 return D3DERR_INVALIDCALL;
4589 /*TODO: stateblocks */
4590 This->currentPalette = PaletteNumber;
4591 TRACE("(%p) : returning\n", This);
4592 return D3D_OK;
4595 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4596 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4597 if (PaletteNumber == NULL) {
4598 WARN("(%p) : returning Invalid Call\n", This);
4599 return D3DERR_INVALIDCALL;
4601 /*TODO: stateblocks */
4602 *PaletteNumber = This->currentPalette;
4603 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
4604 return D3D_OK;
4607 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4608 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4609 static BOOL showFixmes = TRUE;
4610 if (showFixmes) {
4611 FIXME("(%p) : stub\n", This);
4612 showFixmes = FALSE;
4615 This->updateStateBlock->softwareVertexProcessing = bSoftware;
4616 return D3D_OK;
4620 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4621 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4622 static BOOL showFixmes = TRUE;
4623 if (showFixmes) {
4624 FIXME("(%p) : stub\n", This);
4625 showFixmes = FALSE;
4627 return This->updateStateBlock->softwareVertexProcessing;
4631 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
4632 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4634 pRasterStatus->InVBlank = TRUE;
4635 pRasterStatus->ScanLine = 0;
4636 FIXME("(%p) : stub\n", This);
4637 return D3D_OK;
4641 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4642 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4643 static BOOL showfixmes = TRUE;
4644 if(nSegments != 0.0f) {
4645 if( showfixmes) {
4646 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4647 showfixmes = FALSE;
4650 return D3D_OK;
4653 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4654 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4655 static BOOL showfixmes = TRUE;
4656 if( showfixmes) {
4657 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4658 showfixmes = FALSE;
4660 return 0.0f;
4664 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4665 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4666 /** TODO: remove casts to IWineD3DSurfaceImpl
4667 * NOTE: move code to surface to accomplish this
4668 ****************************************/
4669 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
4670 int srcWidth, srcHeight;
4671 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
4672 WINED3DFORMAT destFormat, srcFormat;
4673 UINT destSize;
4674 int destLeft, destTop;
4675 D3DPOOL srcPool, destPool;
4676 int offset = 0;
4677 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
4678 glDescriptor *glDescription = NULL;
4679 GLenum textureDimensions = GL_TEXTURE_2D;
4680 IWineD3DBaseTexture *baseTexture;
4682 WINED3DSURFACE_DESC winedesc;
4684 memset(&winedesc, 0, sizeof(winedesc));
4685 winedesc.Width = &srcSurfaceWidth;
4686 winedesc.Height = &srcSurfaceHeight;
4687 winedesc.Pool = &srcPool;
4688 winedesc.Format = &srcFormat;
4690 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
4692 winedesc.Width = &destSurfaceWidth;
4693 winedesc.Height = &destSurfaceHeight;
4694 winedesc.Pool = &destPool;
4695 winedesc.Format = &destFormat;
4696 winedesc.Size = &destSize;
4698 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
4700 if(srcPool != D3DPOOL_SYSTEMMEM || destPool != D3DPOOL_DEFAULT){
4701 FIXME("source %p must be SYSTEMMEM and dest %p must be DEFAULT\n", pSourceSurface, pDestinationSurface);
4702 return D3DERR_INVALIDCALL;
4704 /* TODO: change this to use bindTexture */
4705 /* Make sure the surface is loaded and upto date */
4706 IWineD3DSurface_PreLoad(pDestinationSurface);
4708 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
4710 ENTER_GL();
4712 /* this needs to be done in lines if the sourceRect != the sourceWidth */
4713 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
4714 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
4715 destLeft = pDestPoint ? pDestPoint->x : 0;
4716 destTop = pDestPoint ? pDestPoint->y : 0;
4719 /* This function doesn't support compressed textures
4720 the pitch is just bytesPerPixel * width */
4722 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
4723 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
4724 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
4725 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
4727 /* TODO DXT formats */
4729 if(pSourceRect != NULL && pSourceRect->top != 0){
4730 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
4732 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
4733 ,This
4734 ,glDescription->level
4735 ,destLeft
4736 ,destTop
4737 ,srcWidth
4738 ,srcHeight
4739 ,glDescription->glFormat
4740 ,glDescription->glType
4741 ,IWineD3DSurface_GetData(pSourceSurface)
4744 /* Sanity check */
4745 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
4746 /* need to lock the surface to get the data */
4747 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
4749 /* TODO: Cube and volume support */
4750 if(rowoffset != 0){
4751 /* not a whole row so we have to do it a line at a time */
4752 int j;
4753 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
4754 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
4756 for(j = destTop ; j < (srcHeight + destTop) ; j++){
4758 glTexSubImage2D(glDescription->target
4759 ,glDescription->level
4760 ,destLeft
4762 ,srcWidth
4764 ,glDescription->glFormat
4765 ,glDescription->glType
4766 ,data/* could be quicker using */
4768 data += rowoffset;
4771 } else { /* Full width, so just write out the whole texture */
4773 if (WINED3DFMT_DXT1 == destFormat ||
4774 WINED3DFMT_DXT3 == destFormat ||
4775 WINED3DFMT_DXT5 == destFormat) {
4776 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
4777 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
4778 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
4779 FIXME("Updating part of a compressed texture is not supported at the moment\n");
4780 } if (destFormat != srcFormat) {
4781 FIXME("Updating mixed format compressed texture is not curretly support\n");
4782 } else {
4783 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
4784 glDescription->level,
4785 glDescription->glFormatInternal,
4786 srcWidth,
4787 srcHeight,
4789 destSize,
4790 IWineD3DSurface_GetData(pSourceSurface));
4792 } else {
4793 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
4797 } else {
4798 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
4799 to repack the data from pow2Width/Height to expected Width,Height, this makes the
4800 data returned by GetData non-power2 width/height with hardware non-power2
4801 pow2Width/height are set to surface width height, repacking isn't needed so it
4802 doesn't matter which function gets called. */
4803 glTexSubImage2D(glDescription->target
4804 ,glDescription->level
4805 ,destLeft
4806 ,destTop
4807 ,srcWidth
4808 ,srcHeight
4809 ,glDescription->glFormat
4810 ,glDescription->glType
4811 ,IWineD3DSurface_GetData(pSourceSurface)
4816 checkGLcall("glTexSubImage2D");
4817 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
4818 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
4819 * surface bigger than it needs to be hmm.. */
4820 if (D3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
4821 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
4822 IWineD3DBaseTexture_Release(baseTexture);
4825 glDisable(textureDimensions); /* This needs to be managed better.... */
4826 LEAVE_GL();
4828 return D3D_OK;
4831 /* Implementation details at http://developer.nvidia.com/attach/6494
4833 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
4834 hmm.. no longer supported use
4835 OpenGL evaluators or tessellate surfaces within your application.
4838 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
4839 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4840 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4841 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p) \n", This, Handle, pNumSegs, pRectPatchInfo);
4842 FIXME("(%p) : Stub\n", This);
4843 return D3D_OK;
4847 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
4848 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4849 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4850 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p) \n", This, Handle, pNumSegs, pTriPatchInfo);
4851 FIXME("(%p) : Stub\n", This);
4852 return D3D_OK;
4855 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
4856 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4857 TRACE("(%p) Handle(%d)\n", This, Handle);
4858 FIXME("(%p) : Stub\n", This);
4859 return D3D_OK;
4862 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
4863 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
4864 fill a surface with a block of color! */
4865 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4866 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
4867 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
4868 IWineD3DSwapChainImpl *container = NULL;
4869 BOOL isRenderTarget = FALSE;
4870 unsigned int width, height;
4871 unsigned int top, left;
4872 unsigned int u, v;
4873 DWORD *data;
4874 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
4875 if (surface->resource.pool != D3DPOOL_DEFAULT) {
4876 FIXME("call to colorfill with non D3DPOOL_DEFAULT surface\n");
4877 return D3DERR_INVALIDCALL;
4880 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
4881 if (D3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
4882 if (D3DUSAGE_RENDERTARGET & surface->resource.usage) {
4883 /* TODO: make sure we set everything back to the way it was, and context management!
4884 glGetIntegerv(GL_READ_BUFFER, &prev_read);
4885 vcheckGLcall("glIntegerv");
4886 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
4887 vcheckGLcall("glIntegerv");
4889 TRACE("Color fill to render targets may cause some graphics issues\n");
4890 if (pSurface == container->frontBuffer) {
4891 glDrawBuffer(GL_FRONT);
4892 } else {
4893 glDrawBuffer(GL_BACK);
4895 } else {
4896 if (D3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
4897 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld \n", surface, surface->resource.usage);
4898 } else {
4899 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
4901 if (container != NULL) {
4902 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
4904 /* we can use GL_STENCIL_INDEX etc...*/
4905 return D3D_OK;
4907 if (container != NULL) {
4908 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
4910 isRenderTarget = TRUE;
4912 /* TODO: drawing to GL_FRONT and GL_BACK */
4913 /* TODO: see if things can be speeded up by using the correct
4914 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
4915 if (pRect == NULL) {
4916 top = 0;
4917 left = 0;
4918 width = surface->currentDesc.Width;
4919 height = surface->currentDesc.Height;
4920 } else {
4921 left = pRect->x1;
4922 top = pRect->y1;
4923 width = pRect->x2 - left;
4924 height = pRect->y2 - top;
4927 data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
4928 /* Create a 'line' of color color, in the correct format for the surface */
4929 for (u = 0 ; u < width ; u ++) {
4930 data[u] = color;
4933 ENTER_GL();
4934 if (isRenderTarget == FALSE) {
4935 glDescriptor *glDesc;
4936 IWineD3DSurface_PreLoad(pSurface);
4938 /* draw a block of the coloured line on the sufrace */
4939 IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
4940 for (v = 0 ; v< height;v++) {
4941 glTexSubImage2D(glDesc->target
4942 ,glDesc->level /* level */
4943 ,left
4944 ,top + v
4945 ,width
4946 ,1 /* height */
4947 ,GL_RGBA
4948 ,GL_UNSIGNED_BYTE
4949 ,data
4952 checkGLcall("glTexSubImage2D");
4953 /* clean up */
4954 glDisable(glDesc->target);
4955 } else {
4956 /** FIXME: Using GLClear may be faster **/
4957 glRasterPos2i(left, top);
4958 glPixelZoom((float)width ,(float)height);
4959 glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
4960 checkGLcall("glDrawPixels");
4962 HeapFree(GetProcessHeap(), 0, data);
4963 LEAVE_GL();
4964 return D3D_OK;
4968 /* rendertarget and deptth stencil functions */
4969 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
4970 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4972 /* FIXME: Implelent RenderTargetIndex >0 */
4973 if(RenderTargetIndex > 0)
4974 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
4976 *ppRenderTarget = This->renderTarget;
4977 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
4978 /* Note inc ref on returned surface */
4979 if(*ppRenderTarget != NULL)
4980 IWineD3DSurface_AddRef(*ppRenderTarget);
4981 return D3D_OK;
4984 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
4985 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4986 *ppZStencilSurface = This->depthStencilBuffer;
4987 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
4989 if(*ppZStencilSurface != NULL) {
4990 /* Note inc ref on returned surface */
4991 IWineD3DSurface_AddRef(*ppZStencilSurface);
4993 return D3D_OK;
4996 /* internal static helper functions */
4997 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
4998 IWineD3DSurface *RenderSurface);
5000 HRESULT WINAPI static IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain);
5002 HRESULT WINAPI static IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context);
5004 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5005 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5006 HRESULT hr = D3D_OK;
5007 WINED3DVIEWPORT viewport;
5009 TRACE("(%p) Swapping rendertarget\n",This);
5010 if (RenderTargetIndex > 0) {
5011 FIXME("(%p) Render targets other than the first are not supported\n",This);
5012 RenderTargetIndex = 0;
5015 /* MSDN says that null disables the render target
5016 but a device must always be associated with a render target
5017 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5019 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5020 for more details
5022 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5023 FIXME("Trying to set render target 0 to NULL\n");
5024 return D3DERR_INVALIDCALL;
5026 /* TODO: replace Impl* usage with interface usage */
5027 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & D3DUSAGE_RENDERTARGET) {
5028 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);
5029 return D3DERR_INVALIDCALL;
5031 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
5032 * builds, but I think wine counts as a 'debug' build for now.
5033 ******************************/
5034 /* If we are trying to set what we already have, don't bother */
5035 if (pRenderTarget == This->renderTarget) {
5036 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5037 } else {
5038 /* Otherwise, set the render target up */
5040 if (FALSE == This->sceneEnded) {
5041 IWineD3DDevice_EndScene(iface);
5043 TRACE("clearing renderer\n");
5044 /* IWineD3DDeviceImpl_CleanRender(iface); */
5045 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5046 depending on the renter target implementation being used.
5047 A shared context implementation will share all buffers between all rendertargets (including swapchains),
5048 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5049 stencil buffer and incure an extra memory overhead */
5050 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
5053 if (SUCCEEDED(hr)) {
5054 /* Finally, reset the viewport as the MSDN states. */
5055 /* TODO: Replace impl usage */
5056 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
5057 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
5058 viewport.X = 0;
5059 viewport.Y = 0;
5060 viewport.MaxZ = 1.0f;
5061 viewport.MinZ = 0.0f;
5062 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
5063 } else {
5064 FIXME("Unknown error setting the render target\n");
5066 This->sceneEnded = FALSE;
5067 return hr;
5070 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
5071 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5072 HRESULT hr = D3D_OK;
5073 IWineD3DSurface *tmp;
5075 TRACE("(%p) Swapping z-buffer\n",This);
5077 if (pNewZStencil == This->stencilBufferTarget) {
5078 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5079 } else {
5080 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5081 * depending on the renter target implementation being used.
5082 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5083 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5084 * stencil buffer and incure an extra memory overhead
5085 ******************************************************/
5088 tmp = This->stencilBufferTarget;
5089 This->stencilBufferTarget = pNewZStencil;
5090 /* should we be calling the parent or the wined3d surface? */
5091 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
5092 if (NULL != tmp) IWineD3DSurface_Release(tmp);
5093 hr = D3D_OK;
5094 /** TODO: glEnable/glDisable on depth/stencil depending on
5095 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
5096 **********************************************************/
5099 return hr;
5103 /* Internal functions not in DirectX */
5104 /** TODO: move this off to the opengl context manager
5105 *(the swapchain doesn't need to know anything about offscreen rendering!)
5106 ****************************************************/
5108 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
5110 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5112 TRACE("(%p), %p\n", This, swapchain);
5114 if (swapchain->win != swapchain->drawable) {
5115 /* Set everything back the way it ws */
5116 swapchain->render_ctx = swapchain->glCtx;
5117 swapchain->drawable = swapchain->win;
5119 return D3D_OK;
5121 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
5122 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
5123 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5124 int i;
5125 unsigned int width;
5126 unsigned int height;
5127 WINED3DFORMAT format;
5128 WINED3DSURFACE_DESC surfaceDesc;
5129 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5130 surfaceDesc.Width = &width;
5131 surfaceDesc.Height = &height;
5132 surfaceDesc.Format = &format;
5133 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5134 *context = NULL;
5135 /* I need a get width/height function (and should do something with the format) */
5136 for (i = 0; i < CONTEXT_CACHE; ++i) {
5137 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
5138 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
5139 the pSurface can be set to 0 allowing it to be reused from cache **/
5140 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
5141 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
5142 *context = &This->contextCache[i];
5143 break;
5145 if (This->contextCache[i].Width == 0) {
5146 This->contextCache[i].pSurface = pSurface;
5147 This->contextCache[i].Width = width;
5148 This->contextCache[i].Height = height;
5149 *context = &This->contextCache[i];
5150 break;
5153 if (i == CONTEXT_CACHE) {
5154 int minUsage = 0x7FFFFFFF; /* MAX_INT */
5155 glContext *dropContext = 0;
5156 for (i = 0; i < CONTEXT_CACHE; i++) {
5157 if (This->contextCache[i].usedcount < minUsage) {
5158 dropContext = &This->contextCache[i];
5159 minUsage = This->contextCache[i].usedcount;
5162 /* clean up the context (this doesn't work for ATI at the moment */
5163 #if 0
5164 glXDestroyContext(swapchain->display, dropContext->context);
5165 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
5166 #endif
5167 FIXME("Leak\n");
5168 dropContext->Width = 0;
5169 dropContext->pSurface = pSurface;
5170 *context = dropContext;
5171 } else {
5172 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
5173 for (i = 0; i < CONTEXT_CACHE; i++) {
5174 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
5178 if (*context != NULL)
5179 return D3D_OK;
5180 else
5181 return E_OUTOFMEMORY;
5184 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
5185 * the functionality needs splitting up so that we don't do more than we should do.
5186 * this only seems to impact performance a little.
5187 ******************************/
5188 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5189 IWineD3DSurface *RenderSurface) {
5190 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5192 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
5193 HRESULT ret = D3DERR_INVALIDCALL;
5194 IWineD3DSurface *tmp;
5196 * Currently only active for GLX >= 1.3
5197 * for others versions we'll have to use GLXPixmaps
5199 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
5200 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
5201 * so only check OpenGL version
5202 * ..........................
5203 * I don't believe that it is a problem with NVidia headers,
5204 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
5205 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
5206 * ATI Note:
5207 * Your application will report GLX version 1.2 on glXQueryVersion.
5208 * However, it is safe to call the GLX 1.3 functions as described below.
5210 #if defined(GL_VERSION_1_3)
5212 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
5213 GLXFBConfig* cfgs = NULL;
5214 int nCfgs = 0;
5215 int attribs[256];
5216 int nAttribs = 0;
5217 IWineD3DSwapChain *currentSwapchain;
5218 IWineD3DSwapChainImpl *swapchain;
5219 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
5220 * but switch them off if the StencilSurface is set to NULL
5221 ** *********************************************************/
5222 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
5223 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
5225 /**TODO:
5226 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
5227 it StencilSurface != NULL && zBufferTarget == NULL switch it on
5230 #define PUSH1(att) attribs[nAttribs++] = (att);
5231 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
5233 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
5235 /** TODO: remove the reff to Impl (context manager should fix this!) **/
5236 IWineD3DSwapChainImpl *impSwapChain;
5237 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
5238 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
5239 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
5242 ENTER_GL();
5244 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
5245 PUSH2(GLX_X_RENDERABLE, TRUE);
5246 PUSH2(GLX_DOUBLEBUFFER, TRUE);
5247 TRACE("calling makeglcfg\n");
5248 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
5249 PUSH1(None);
5251 TRACE("calling chooseFGConfig\n");
5252 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5253 attribs, &nCfgs);
5255 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
5256 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
5257 why we failed and only show this message once! */
5258 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"); /**/
5259 nAttribs = 0;
5260 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
5261 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
5262 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
5263 PUSH2(GLX_DOUBLEBUFFER, FALSE);
5264 TRACE("calling makeglcfg\n");
5265 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
5266 PUSH1(None);
5267 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5268 attribs, &nCfgs);
5271 if (NULL != cfgs) {
5272 #ifdef EXTRA_TRACES
5273 int i;
5274 for (i = 0; i < nCfgs; ++i) {
5275 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
5276 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
5277 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
5280 if (NULL != This->renderTarget) {
5281 glFlush();
5282 vcheckGLcall("glFlush");
5283 /** This is only useful if the old render target was a swapchain,
5284 * we need to supercede this with a function that displays
5285 * the current buffer on the screen. This is easy to do in glx1.3 but
5286 * we need to do copy-write pixels in glx 1.2.
5287 ************************************************/
5288 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
5290 printf("Hit Enter to get next frame ...\n");
5291 getchar();
5293 #endif
5296 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&currentSwapchain) != D3D_OK) {
5297 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
5298 IWineD3DDevice_GetSwapChain(iface, 0, &currentSwapchain);
5302 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
5303 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
5304 **********************************************************************/
5305 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == D3D_OK) {
5306 /* We also need to make sure that the lights &co are also in the context of the swapchains */
5307 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
5308 TRACE("making swapchain active\n");
5309 if (RenderSurface != This->renderTarget) {
5310 if (RenderSurface == swapchain->backBuffer) {
5311 } else {
5312 /* This could be flagged so that some operations work directly with the front buffer */
5313 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
5315 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
5316 == False) {
5317 TRACE("Error in setting current context: context %p drawable %ld !\n",
5318 impSwapChain->glCtx, impSwapChain->win);
5321 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5323 checkGLcall("glXMakeContextCurrent");
5325 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5327 else if (pbuffer_support == TRUE && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
5329 /** ********************************************************************
5330 * This is a quickly hacked out implementation of offscreen textures.
5331 * It will work in most cases but there may be problems if the client
5332 * modifies the texture directly, or expects the contents of the rendertarget
5333 * to be persistent.
5335 * There are some real speed vs compatibility issues here:
5336 * we should really use a new context for every texture, but that eats ram.
5337 * we should also be restoring the texture to the pbuffer but that eats CPU
5338 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
5339 * but if this means reusing the display backbuffer then we need to make sure that
5340 * states are correctly preserved.
5341 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
5342 * and gain a good performance increase at the cost of compatibility.
5343 * I would suggest that, when this is the case, a user configurable flag be made
5344 * available, allowing the user to choose the best emmulated experience for them.
5345 *********************************************************************/
5347 XVisualInfo *visinfo;
5348 glContext *newContext;
5350 /* Here were using a shared context model */
5351 if (D3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
5352 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5355 /* If the context doesn't exist then create a new one */
5356 /* TODO: This should really be part of findGlContext */
5357 if (NULL == newContext->context) {
5359 TRACE("making new buffer\n");
5360 nAttribs = 0;
5361 PUSH2(GLX_PBUFFER_WIDTH, newContext->Width);
5362 PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
5363 PUSH1(None);
5365 newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
5367 /** ****************************************
5368 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
5369 *they note:
5370 * In future releases, we may provide the calls glXCreateNewContext,
5371 * glXQueryDrawable and glXMakeContextCurrent.
5372 * so until then we have to use glXGetVisualFromFBConfig &co..
5373 ********************************************/
5376 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
5377 if (!visinfo) {
5378 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
5379 } else {
5380 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
5381 XFree(visinfo);
5384 if (NULL == newContext || NULL == newContext->context) {
5385 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5386 } else {
5387 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
5388 if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
5389 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
5392 /* Clean up the old context */
5393 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5394 /* Set the current context of the swapchain to the new context */
5395 impSwapChain->drawable = newContext->drawable;
5396 impSwapChain->render_ctx = newContext->context;
5400 #if 1 /* Apply the stateblock to the new context
5401 FIXME: This is a bit of a hack, each context should know it's own state,
5402 the directX current directX state should then be applied to the context */
5404 BOOL oldRecording;
5405 IWineD3DStateBlockImpl *oldUpdateStateBlock;
5406 oldUpdateStateBlock = This->updateStateBlock;
5407 oldRecording= This->isRecordingState;
5408 This->isRecordingState = FALSE;
5409 This->updateStateBlock = This->stateBlock;
5410 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
5412 This->isRecordingState = oldRecording;
5413 This->updateStateBlock = oldUpdateStateBlock;
5415 #endif
5418 /* clean up the current rendertargets swapchain (if it belonged to one) */
5419 if (currentSwapchain != NULL) {
5420 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
5423 /* Were done with the opengl context management, setup the rendertargets */
5425 tmp = This->renderTarget;
5426 This->renderTarget = RenderSurface;
5427 IWineD3DSurface_AddRef(This->renderTarget);
5428 IWineD3DSurface_Release(tmp);
5433 DWORD value;
5434 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
5435 /* Check that the container is not a swapchain member */
5437 IWineD3DSwapChain *tmpSwapChain;
5438 if (D3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
5439 This->renderUpsideDown = TRUE;
5440 }else{
5441 This->renderUpsideDown = FALSE;
5442 IWineD3DSwapChain_Release(tmpSwapChain);
5444 /* Force updating the cull mode */
5445 TRACE("setting render state\n");
5446 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
5447 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
5449 /* Force updating projection matrix */
5450 This->last_was_rhw = FALSE;
5451 This->proj_valid = FALSE;
5454 ret = D3D_OK;
5456 if (cfgs != NULL) {
5457 XFree(cfgs);
5458 } else {
5459 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
5460 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
5463 #undef PUSH1
5464 #undef PUSH2
5465 if ( NULL != impSwapChain) {
5466 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
5468 LEAVE_GL();
5470 #endif
5471 return ret;
5474 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
5475 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
5476 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5477 /* TODO: the use of Impl is deprecated. */
5478 /* some basic validation checks */
5479 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
5481 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
5483 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
5484 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
5485 return D3DERR_INVALIDCALL;
5487 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
5488 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
5489 return D3DERR_INVALIDCALL;
5491 /* TODO: make the cursor 'real' */
5493 This->xHotSpot = XHotSpot;
5494 This->yHotSpot = YHotSpot;
5496 return D3D_OK;
5499 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
5500 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5501 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
5503 This->xScreenSpace = XScreenSpace;
5504 This->yScreenSpace = YScreenSpace;
5506 return;
5510 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
5511 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5512 TRACE("(%p) : visible(%d)\n", This, bShow);
5514 This->bCursorVisible = bShow;
5516 return D3D_OK;
5519 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
5520 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5521 FIXME("(%p) : stub\n", This); /* No way of notifying yet! */
5522 return D3D_OK;
5526 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
5527 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5528 /** FIXME: Resource tracking needs to be done,
5529 * The closes we can do to this is set the priorities of all managed textures low
5530 * and then reset them.
5531 ***********************************************************/
5532 FIXME("(%p) : stub\n", This);
5533 return D3D_OK;
5536 HRESULT WINAPI IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
5537 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5538 /** FIXME: Resource trascking needs to be done.
5539 * in effect this pulls all non only default
5540 * textures out of video memory and deletes all glTextures (glDeleteTextures)
5541 * and should clear down the context and set it up according to pPresentationParameters
5542 ***********************************************************/
5543 FIXME("(%p) : stub\n", This);
5544 return D3D_OK;
5547 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
5548 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5549 /** FIXME: always true at the moment **/
5550 if(bEnableDialogs == FALSE) {
5551 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
5553 return D3D_OK;
5557 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
5558 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5560 FIXME("(%p) : stub\n", This);
5561 /* Setup some reasonable defaults */
5562 pParameters->AdapterOrdinal = 0; /* always for now */
5563 pParameters->DeviceType = D3DDEVTYPE_HAL; /* always for now */
5564 pParameters->hFocusWindow = 0;
5565 pParameters->BehaviorFlags =0;
5566 return D3D_OK;
5569 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
5570 IWineD3DSwapChain *swapchain;
5571 HRESULT hrc = D3D_OK;
5573 TRACE("Relaying to swapchain\n");
5575 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
5576 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (D3DGAMMARAMP *)pRamp);
5577 IWineD3DSwapChain_Release(swapchain);
5579 return;
5582 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
5583 IWineD3DSwapChain *swapchain;
5584 HRESULT hrc = D3D_OK;
5586 TRACE("Relaying to swapchain\n");
5588 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
5589 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
5590 IWineD3DSwapChain_Release(swapchain);
5592 return;
5596 /** ********************************************************
5597 * Notification functions
5598 ** ********************************************************/
5599 /** This function must be called in the release of a resource when ref == 0,
5600 * the contents of resource must still be correct,
5601 * any handels to other resource held by the caller must be closed
5602 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
5603 *****************************************************/
5604 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5605 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5606 ResourceList* resourceList;
5608 TRACE("(%p) : resource %p\n", This, resource);
5609 #if 0
5610 EnterCriticalSection(&resourceStoreCriticalSection);
5611 #endif
5612 /* add a new texture to the frot of the linked list */
5613 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
5614 resourceList->resource = resource;
5616 /* Get the old head */
5617 resourceList->next = This->resources;
5619 This->resources = resourceList;
5620 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
5622 #if 0
5623 LeaveCriticalSection(&resourceStoreCriticalSection);
5624 #endif
5625 return;
5628 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5629 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5630 ResourceList* resourceList = NULL;
5631 ResourceList* previousResourceList = NULL;
5633 TRACE("(%p) : resource %p\n", This, resource);
5635 #if 0
5636 EnterCriticalSection(&resourceStoreCriticalSection);
5637 #endif
5638 resourceList = This->resources;
5640 while (resourceList != NULL) {
5641 if(resourceList->resource == resource) break;
5642 previousResourceList = resourceList;
5643 resourceList = resourceList->next;
5646 if (resourceList == NULL) {
5647 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
5648 #if 0
5649 LeaveCriticalSection(&resourceStoreCriticalSection);
5650 #endif
5651 return;
5652 } else {
5653 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
5655 /* make sure we don't leave a hole in the list */
5656 if (previousResourceList != NULL) {
5657 previousResourceList->next = resourceList->next;
5658 } else {
5659 This->resources = resourceList->next;
5662 #if 0
5663 LeaveCriticalSection(&resourceStoreCriticalSection);
5664 #endif
5665 return;
5669 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
5670 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5671 int counter;
5673 TRACE("(%p) : resource %p\n", This, resource);
5674 switch(IWineD3DResource_GetType(resource)){
5675 case D3DRTYPE_SURFACE:
5676 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
5677 break;
5678 case D3DRTYPE_TEXTURE:
5679 case D3DRTYPE_CUBETEXTURE:
5680 case D3DRTYPE_VOLUMETEXTURE:
5681 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
5682 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5683 IUnknown *textureParent;
5684 IWineD3DBaseTexture_GetParent(This->stateBlock->textures[counter], &textureParent);
5685 /* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
5686 FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter, resource, textureParent);
5687 IUnknown_Release(textureParent);
5688 This->stateBlock->textures[counter] = NULL;
5690 if (This->updateStateBlock != This->stateBlock ){
5691 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5692 IUnknown *textureParent;
5693 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[counter], &textureParent);
5694 /* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
5695 FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter, resource, textureParent);
5696 IUnknown_Release(textureParent);
5697 This->updateStateBlock->textures[counter] = NULL;
5701 break;
5702 case D3DRTYPE_VOLUME:
5703 /* TODO: nothing really? */
5704 break;
5705 case D3DRTYPE_VERTEXBUFFER:
5706 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
5708 int streamNumber;
5709 TRACE("Cleaning up stream pointers\n");
5711 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
5712 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
5713 FINDOUT: should changes.streamSource[StreamNumber] be set ?
5715 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5716 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
5717 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
5718 This->updateStateBlock->streamSource[streamNumber] = 0;
5719 /* Set changed flag? */
5722 if (This->stateBlock != NULL ) { /* only happens if their is an error in the application, or on reset/release (because we don't manage internal tracknig properly) */
5723 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
5724 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
5725 This->stateBlock->streamSource[streamNumber] = 0;
5728 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
5729 else { /* This shouldn't happen */
5730 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
5732 #endif
5736 break;
5737 case D3DRTYPE_INDEXBUFFER:
5738 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
5739 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5740 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5741 This->updateStateBlock->pIndexData = NULL;
5744 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
5745 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5746 This->stateBlock->pIndexData = NULL;
5750 break;
5751 default:
5752 FIXME("(%p) unknown resource type %p %u \n", This, resource, IWineD3DResource_GetType(resource));
5753 break;
5757 /* Remove the resoruce from the resourceStore */
5758 IWineD3DDeviceImpl_RemoveResource(iface, resource);
5760 TRACE("Resource released\n");
5765 /** This function is to be called by the swapchain when it is released and it's ref = 0
5766 *****************************************************/
5767 void WINAPI IWineD3DDeviceImpl_SwapChainReleased(IWineD3DDevice *iface, IWineD3DSwapChain *swapChain){
5768 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5769 SwapChainList **nextSwapchain;
5770 nextSwapchain = &This->swapchains;
5772 /* Check to see if the swapchian is being used as the render target */
5773 if (This->renderTarget != NULL) {
5774 IWineD3DSurface *swapchainBackBuffer;
5776 IWineD3DSwapChain_GetBackBuffer(swapChain, 0 ,( D3DBACKBUFFER_TYPE) 0, &swapchainBackBuffer);
5777 if (This->renderTarget == swapchainBackBuffer) {
5778 /* Don't know what to do, so warn and carry on as usual (which in this case leaves the renderterget in limbo) */
5779 FIXME("Atempting to release a swapchain that is currently beuing used as a render target, behaviour is undefined\n");
5783 /* Go through the swapchain list and try to find the swapchain being released */
5784 while(*nextSwapchain != NULL && (*nextSwapchain)->swapchain != swapChain) {
5785 nextSwapchain = &(*nextSwapchain)->next;
5788 /* Check to see if we found the swapchain */
5789 if (NULL != *nextSwapchain) {
5790 /* We found the swapchain so remove it from the list */
5791 TRACE("(%p) releasing swapchain(%p)\n", iface, swapChain);
5792 HeapFree(GetProcessHeap(), 0 , *nextSwapchain);
5793 *nextSwapchain = (*nextSwapchain)->next;
5794 } else {
5795 /* We didn't find the swapchain on the list, this can only heppen because of a programming error in wined3d */
5796 FIXME("(%p) Attempting to release a swapchain (%p) that hasn't been stored\n", iface, swapChain);
5799 TRACE("swapchain (%p) released\n", swapChain);
5800 return;
5803 /**********************************************************
5804 * IWineD3DDevice VTbl follows
5805 **********************************************************/
5807 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
5809 /*** IUnknown methods ***/
5810 IWineD3DDeviceImpl_QueryInterface,
5811 IWineD3DDeviceImpl_AddRef,
5812 IWineD3DDeviceImpl_Release,
5813 /*** IWineD3DDevice methods ***/
5814 IWineD3DDeviceImpl_GetParent,
5815 /*** Creation methods**/
5816 IWineD3DDeviceImpl_CreateVertexBuffer,
5817 IWineD3DDeviceImpl_CreateIndexBuffer,
5818 IWineD3DDeviceImpl_CreateStateBlock,
5819 IWineD3DDeviceImpl_CreateSurface,
5820 IWineD3DDeviceImpl_CreateTexture,
5821 IWineD3DDeviceImpl_CreateVolumeTexture,
5822 IWineD3DDeviceImpl_CreateVolume,
5823 IWineD3DDeviceImpl_CreateCubeTexture,
5824 IWineD3DDeviceImpl_CreateQuery,
5825 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
5826 IWineD3DDeviceImpl_CreateVertexDeclaration,
5827 IWineD3DDeviceImpl_CreateVertexShader,
5828 IWineD3DDeviceImpl_CreatePixelShader,
5830 /*** Odd functions **/
5831 IWineD3DDeviceImpl_EvictManagedResources,
5832 IWineD3DDeviceImpl_GetAvailableTextureMem,
5833 IWineD3DDeviceImpl_GetBackBuffer,
5834 IWineD3DDeviceImpl_GetCreationParameters,
5835 IWineD3DDeviceImpl_GetDeviceCaps,
5836 IWineD3DDeviceImpl_GetDirect3D,
5837 IWineD3DDeviceImpl_GetDisplayMode,
5838 IWineD3DDeviceImpl_GetNumberOfSwapChains,
5839 IWineD3DDeviceImpl_GetRasterStatus,
5840 IWineD3DDeviceImpl_GetSwapChain,
5841 IWineD3DDeviceImpl_Reset,
5842 IWineD3DDeviceImpl_SetDialogBoxMode,
5843 IWineD3DDeviceImpl_SetCursorProperties,
5844 IWineD3DDeviceImpl_SetCursorPosition,
5845 IWineD3DDeviceImpl_ShowCursor,
5846 IWineD3DDeviceImpl_TestCooperativeLevel,
5847 /*** Getters and setters **/
5848 IWineD3DDeviceImpl_SetClipPlane,
5849 IWineD3DDeviceImpl_GetClipPlane,
5850 IWineD3DDeviceImpl_SetClipStatus,
5851 IWineD3DDeviceImpl_GetClipStatus,
5852 IWineD3DDeviceImpl_SetCurrentTexturePalette,
5853 IWineD3DDeviceImpl_GetCurrentTexturePalette,
5854 IWineD3DDeviceImpl_SetDepthStencilSurface,
5855 IWineD3DDeviceImpl_GetDepthStencilSurface,
5856 IWineD3DDeviceImpl_SetFVF,
5857 IWineD3DDeviceImpl_GetFVF,
5858 IWineD3DDeviceImpl_SetGammaRamp,
5859 IWineD3DDeviceImpl_GetGammaRamp,
5860 IWineD3DDeviceImpl_SetIndices,
5861 IWineD3DDeviceImpl_GetIndices,
5862 IWineD3DDeviceImpl_SetLight,
5863 IWineD3DDeviceImpl_GetLight,
5864 IWineD3DDeviceImpl_SetLightEnable,
5865 IWineD3DDeviceImpl_GetLightEnable,
5866 IWineD3DDeviceImpl_SetMaterial,
5867 IWineD3DDeviceImpl_GetMaterial,
5868 IWineD3DDeviceImpl_SetNPatchMode,
5869 IWineD3DDeviceImpl_GetNPatchMode,
5870 IWineD3DDeviceImpl_SetPaletteEntries,
5871 IWineD3DDeviceImpl_GetPaletteEntries,
5872 IWineD3DDeviceImpl_SetPixelShader,
5873 IWineD3DDeviceImpl_GetPixelShader,
5874 IWineD3DDeviceImpl_SetPixelShaderConstantB,
5875 IWineD3DDeviceImpl_GetPixelShaderConstantB,
5876 IWineD3DDeviceImpl_SetPixelShaderConstantI,
5877 IWineD3DDeviceImpl_GetPixelShaderConstantI,
5878 IWineD3DDeviceImpl_SetPixelShaderConstantF,
5879 IWineD3DDeviceImpl_GetPixelShaderConstantF,
5880 IWineD3DDeviceImpl_SetRenderState,
5881 IWineD3DDeviceImpl_GetRenderState,
5882 IWineD3DDeviceImpl_SetRenderTarget,
5883 IWineD3DDeviceImpl_GetRenderTarget,
5884 IWineD3DDeviceImpl_SetSamplerState,
5885 IWineD3DDeviceImpl_GetSamplerState,
5886 IWineD3DDeviceImpl_SetScissorRect,
5887 IWineD3DDeviceImpl_GetScissorRect,
5888 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
5889 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
5890 IWineD3DDeviceImpl_SetStreamSource,
5891 IWineD3DDeviceImpl_GetStreamSource,
5892 IWineD3DDeviceImpl_SetStreamSourceFreq,
5893 IWineD3DDeviceImpl_GetStreamSourceFreq,
5894 IWineD3DDeviceImpl_SetTexture,
5895 IWineD3DDeviceImpl_GetTexture,
5896 IWineD3DDeviceImpl_SetTextureStageState,
5897 IWineD3DDeviceImpl_GetTextureStageState,
5898 IWineD3DDeviceImpl_SetTransform,
5899 IWineD3DDeviceImpl_GetTransform,
5900 IWineD3DDeviceImpl_SetVertexDeclaration,
5901 IWineD3DDeviceImpl_GetVertexDeclaration,
5902 IWineD3DDeviceImpl_SetVertexShader,
5903 IWineD3DDeviceImpl_GetVertexShader,
5904 IWineD3DDeviceImpl_SetVertexShaderConstantB,
5905 IWineD3DDeviceImpl_GetVertexShaderConstantB,
5906 IWineD3DDeviceImpl_SetVertexShaderConstantI,
5907 IWineD3DDeviceImpl_GetVertexShaderConstantI,
5908 IWineD3DDeviceImpl_SetVertexShaderConstantF,
5909 IWineD3DDeviceImpl_GetVertexShaderConstantF,
5910 IWineD3DDeviceImpl_SetViewport,
5911 IWineD3DDeviceImpl_GetViewport,
5912 IWineD3DDeviceImpl_MultiplyTransform,
5913 IWineD3DDeviceImpl_ValidateDevice,
5914 IWineD3DDeviceImpl_ProcessVertices,
5915 /*** State block ***/
5916 IWineD3DDeviceImpl_BeginStateBlock,
5917 IWineD3DDeviceImpl_EndStateBlock,
5918 /*** Scene management ***/
5919 IWineD3DDeviceImpl_BeginScene,
5920 IWineD3DDeviceImpl_EndScene,
5921 IWineD3DDeviceImpl_Present,
5922 IWineD3DDeviceImpl_Clear,
5923 /*** Drawing ***/
5924 IWineD3DDeviceImpl_DrawPrimitive,
5925 IWineD3DDeviceImpl_DrawIndexedPrimitive,
5926 IWineD3DDeviceImpl_DrawPrimitiveUP,
5927 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
5928 IWineD3DDeviceImpl_DrawRectPatch,
5929 IWineD3DDeviceImpl_DrawTriPatch,
5930 IWineD3DDeviceImpl_DeletePatch,
5931 IWineD3DDeviceImpl_ColorFill,
5932 IWineD3DDeviceImpl_UpdateTexture,
5933 IWineD3DDeviceImpl_UpdateSurface,
5934 IWineD3DDeviceImpl_StretchRect,
5935 IWineD3DDeviceImpl_GetRenderTargetData,
5936 IWineD3DDeviceImpl_GetFrontBufferData,
5937 /*** Internal use IWineD3DDevice methods ***/
5938 IWineD3DDeviceImpl_SetupTextureStates,
5939 IWineD3DDeviceImpl_SwapChainReleased,
5940 /*** object tracking ***/
5941 IWineD3DDeviceImpl_ResourceReleased
5945 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
5946 WINED3DRS_ALPHABLENDENABLE ,
5947 WINED3DRS_ALPHAFUNC ,
5948 WINED3DRS_ALPHAREF ,
5949 WINED3DRS_ALPHATESTENABLE ,
5950 WINED3DRS_BLENDOP ,
5951 WINED3DRS_COLORWRITEENABLE ,
5952 WINED3DRS_DESTBLEND ,
5953 WINED3DRS_DITHERENABLE ,
5954 WINED3DRS_FILLMODE ,
5955 WINED3DRS_FOGDENSITY ,
5956 WINED3DRS_FOGEND ,
5957 WINED3DRS_FOGSTART ,
5958 WINED3DRS_LASTPIXEL ,
5959 WINED3DRS_SHADEMODE ,
5960 WINED3DRS_SRCBLEND ,
5961 WINED3DRS_STENCILENABLE ,
5962 WINED3DRS_STENCILFAIL ,
5963 WINED3DRS_STENCILFUNC ,
5964 WINED3DRS_STENCILMASK ,
5965 WINED3DRS_STENCILPASS ,
5966 WINED3DRS_STENCILREF ,
5967 WINED3DRS_STENCILWRITEMASK ,
5968 WINED3DRS_STENCILZFAIL ,
5969 WINED3DRS_TEXTUREFACTOR ,
5970 WINED3DRS_WRAP0 ,
5971 WINED3DRS_WRAP1 ,
5972 WINED3DRS_WRAP2 ,
5973 WINED3DRS_WRAP3 ,
5974 WINED3DRS_WRAP4 ,
5975 WINED3DRS_WRAP5 ,
5976 WINED3DRS_WRAP6 ,
5977 WINED3DRS_WRAP7 ,
5978 WINED3DRS_ZENABLE ,
5979 WINED3DRS_ZFUNC ,
5980 WINED3DRS_ZWRITEENABLE
5983 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
5984 WINED3DTSS_ADDRESSW ,
5985 WINED3DTSS_ALPHAARG0 ,
5986 WINED3DTSS_ALPHAARG1 ,
5987 WINED3DTSS_ALPHAARG2 ,
5988 WINED3DTSS_ALPHAOP ,
5989 WINED3DTSS_BUMPENVLOFFSET ,
5990 WINED3DTSS_BUMPENVLSCALE ,
5991 WINED3DTSS_BUMPENVMAT00 ,
5992 WINED3DTSS_BUMPENVMAT01 ,
5993 WINED3DTSS_BUMPENVMAT10 ,
5994 WINED3DTSS_BUMPENVMAT11 ,
5995 WINED3DTSS_COLORARG0 ,
5996 WINED3DTSS_COLORARG1 ,
5997 WINED3DTSS_COLORARG2 ,
5998 WINED3DTSS_COLOROP ,
5999 WINED3DTSS_RESULTARG ,
6000 WINED3DTSS_TEXCOORDINDEX ,
6001 WINED3DTSS_TEXTURETRANSFORMFLAGS
6004 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
6005 WINED3DSAMP_ADDRESSU ,
6006 WINED3DSAMP_ADDRESSV ,
6007 WINED3DSAMP_ADDRESSW ,
6008 WINED3DSAMP_BORDERCOLOR ,
6009 WINED3DSAMP_MAGFILTER ,
6010 WINED3DSAMP_MINFILTER ,
6011 WINED3DSAMP_MIPFILTER ,
6012 WINED3DSAMP_MIPMAPLODBIAS ,
6013 WINED3DSAMP_MAXMIPLEVEL ,
6014 WINED3DSAMP_MAXANISOTROPY ,
6015 WINED3DSAMP_SRGBTEXTURE ,
6016 WINED3DSAMP_ELEMENTINDEX
6019 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
6020 WINED3DRS_AMBIENT ,
6021 WINED3DRS_AMBIENTMATERIALSOURCE ,
6022 WINED3DRS_CLIPPING ,
6023 WINED3DRS_CLIPPLANEENABLE ,
6024 WINED3DRS_COLORVERTEX ,
6025 WINED3DRS_DIFFUSEMATERIALSOURCE ,
6026 WINED3DRS_EMISSIVEMATERIALSOURCE ,
6027 WINED3DRS_FOGDENSITY ,
6028 WINED3DRS_FOGEND ,
6029 WINED3DRS_FOGSTART ,
6030 WINED3DRS_FOGTABLEMODE ,
6031 WINED3DRS_FOGVERTEXMODE ,
6032 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
6033 WINED3DRS_LIGHTING ,
6034 WINED3DRS_LOCALVIEWER ,
6035 WINED3DRS_MULTISAMPLEANTIALIAS ,
6036 WINED3DRS_MULTISAMPLEMASK ,
6037 WINED3DRS_NORMALIZENORMALS ,
6038 WINED3DRS_PATCHEDGESTYLE ,
6039 WINED3DRS_POINTSCALE_A ,
6040 WINED3DRS_POINTSCALE_B ,
6041 WINED3DRS_POINTSCALE_C ,
6042 WINED3DRS_POINTSCALEENABLE ,
6043 WINED3DRS_POINTSIZE ,
6044 WINED3DRS_POINTSIZE_MAX ,
6045 WINED3DRS_POINTSIZE_MIN ,
6046 WINED3DRS_POINTSPRITEENABLE ,
6047 WINED3DRS_RANGEFOGENABLE ,
6048 WINED3DRS_SPECULARMATERIALSOURCE ,
6049 WINED3DRS_TWEENFACTOR ,
6050 WINED3DRS_VERTEXBLEND
6053 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
6054 WINED3DTSS_TEXCOORDINDEX ,
6055 WINED3DTSS_TEXTURETRANSFORMFLAGS
6058 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
6059 WINED3DSAMP_DMAPOFFSET