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
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 )
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;
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);
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; \
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); \
98 return D3DERR_OUTOFVIDEOMEMORY; \
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); \
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) {
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);
139 glLoadMatrixf((float *)&This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
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");
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");
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);
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) {
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");
193 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
194 checkGLcall("glLightfv");
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");
205 case D3DLIGHT_DIRECTIONAL:
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");
216 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
219 /* Restore the modelview matrix */
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;
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));
241 VTRACE(("Activating appropriate texture state %ld\n", Sampler));
242 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
244 GLACTIVETEXTURE(Sampler);
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");
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);
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);
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,
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);
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);
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);
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;
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);
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);
394 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
395 DWORD FVF, D3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
397 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
398 IWineD3DVertexBufferImpl *object;
399 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
400 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, D3DRTYPE_VERTEXBUFFER, Size)
403 if (Pool == D3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
404 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
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;
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)
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;
436 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
438 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
439 IWineD3DStateBlockImpl *object;
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 */
453 /* Otherwise, might as well set the whole state block to the appropriate values */
454 if ( This->stateBlock != NULL) {
455 memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
457 memset(object->streamFreq, 1, sizeof(object->streamFreq));
460 /* Reset the ref and type after kludging it */
461 object->wineD3DDevice = This;
463 object->blockType = Type;
465 TRACE("Updating changed flags appropriate for type %d\n", Type);
467 if (Type == WINED3DSBT_ALL) {
469 TRACE("ALL => Pretend everything has changed\n");
470 memset(&object->changed, TRUE, sizeof(This->stateBlock->changed));
471 } else if (Type == WINED3DSBT_PIXELSTATE) {
473 TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
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 TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
484 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
485 /* TODO: Vertex Shader Constants */
486 object->changed.vertexShader = TRUE;
487 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
488 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
491 /* Duplicate light chain */
493 PLIGHTINFOEL *src = NULL;
494 PLIGHTINFOEL *dst = NULL;
495 PLIGHTINFOEL *newEl = NULL;
496 src = This->stateBlock->lights;
497 object->lights = NULL;
501 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
502 if (newEl == NULL) return D3DERR_OUTOFVIDEOMEMORY;
503 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
505 newEl->changed = TRUE;
506 newEl->enabledChanged = TRUE;
508 object->lights = newEl;
519 FIXME("Unrecognized state block type %d\n", Type);
522 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
527 /* ************************************
529 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
532 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
534 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.
536 ******************************** */
538 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) {
539 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
540 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
541 unsigned int pow2Width, pow2Height;
542 unsigned int Size = 1;
543 TRACE("(%p) Create surface\n",This);
545 /** FIXME: Check ranges on the inputs are valid
548 * [in] Quality level. The valid range is between zero and one less than the level
549 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
550 * Passing a larger value returns the error D3DERR_INVALIDCALL. The MultisampleQuality
551 * values of paired render targets, depth stencil surfaces, and the MultiSample type
553 *******************************/
558 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
560 * If this flag is set, the contents of the depth stencil buffer will be
561 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
562 * with a different depth surface.
564 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
565 ***************************/
567 if(MultisampleQuality < 0) {
568 FIXME("Invalid multisample level %ld \n", MultisampleQuality);
569 return D3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
572 if(MultisampleQuality > 0) {
573 FIXME("MultisampleQuality set to %ld, substituting 0 \n" , MultisampleQuality);
574 MultisampleQuality=0;
577 /** FIXME: Check that the format is supported
579 *******************************/
580 /* TODO: add support for dxt2 and dxt4 formats */
581 if (Format == D3DFMT_DXT2 || Format == D3DFMT_DXT4) return D3DERR_NOTAVAILABLE;
583 /* Non-power2 support */
585 /* Find the nearest pow2 match */
586 pow2Width = pow2Height = 1;
587 while (pow2Width < Width) pow2Width <<= 1;
588 while (pow2Height < Height) pow2Height <<= 1;
590 if (pow2Width > Width || pow2Height > Height) {
591 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
592 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
593 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
594 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d) \n",
595 This, Width, Height);
596 return D3DERR_NOTAVAILABLE;
600 /** Check against the maximum texture sizes supported by the video card **/
601 if (pow2Width > GL_LIMITS(texture_size) || pow2Height > GL_LIMITS(texture_size)) {
602 /* one of three options
603 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)
604 2: Set the texture to the maxium size (bad idea)
605 3: WARN and return D3DERR_NOTAVAILABLE;
607 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));
608 return D3DERR_NOTAVAILABLE;
613 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
614 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
616 *********************************/
617 if (Format == WINED3DFMT_DXT1) {
618 /* DXT1 is half byte per pixel */
619 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4)) >> 1;
621 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
622 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
623 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4));
625 Size = (pow2Width * D3DFmtGetBpp(This, Format)) * pow2Height;
628 /** Create the and initilise surface resource **/
629 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,D3DRTYPE_SURFACE, Size)
630 object->container = (IUnknown*) This;
632 object->currentDesc.Width = Width;
633 object->currentDesc.Height = Height;
634 object->currentDesc.MultiSampleType = MultiSample;
635 object->currentDesc.MultiSampleQuality = MultisampleQuality;
637 /* Setup some glformat defaults */
638 object->glDescription.glFormat = D3DFmt2GLFmt(This, object->resource.format);
639 object->glDescription.glFormatInternal = D3DFmt2GLIntFmt(This, object->resource.format);
640 object->glDescription.glType = D3DFmt2GLType(This, object->resource.format);
641 object->glDescription.textureName = 0;
642 object->glDescription.level = Level;
643 object->glDescription.target = GL_TEXTURE_2D;
646 object->pow2Width = pow2Width;
647 object->pow2Height = pow2Height;
648 object->nonpow2 = (pow2Width != Width || pow2Height != Height) ? TRUE : FALSE;
649 object->discard = Discard;
650 object->activeLock = FALSE;
651 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
652 object->pow2Size = (pow2Width * object->bytesPerPixel) * pow2Height;
654 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
656 TRACE("Pool %d %d %d %d",Pool, D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM);
658 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
659 * this function is too deap to need to care about things like this.
660 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
661 * ****************************************/
663 case D3DPOOL_SCRATCH:
664 if(Lockable == FALSE)
665 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
666 which are mutually exclusive, setting lockable to true\n");
669 case D3DPOOL_SYSTEMMEM:
670 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
671 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
672 case D3DPOOL_MANAGED:
673 if(Usage == D3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
674 Usage of DYNAMIC which are mutually exclusive, not doing \
675 anything just telling you.\n");
677 case D3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
678 if(!(Usage & D3DUSAGE_DYNAMIC) && !(Usage & D3DUSAGE_RENDERTARGET)
679 && !(Usage && D3DUSAGE_DEPTHSTENCIL ) && Lockable == TRUE)
680 FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
683 FIXME("(%p) Unknown pool %d\n", This, Pool);
687 if (Usage & D3DUSAGE_RENDERTARGET && Pool != D3DPOOL_DEFAULT) {
688 FIXME("Trying to create a render target that isn't in the default pool\n");
692 object->locked = FALSE;
693 object->lockable = (WINED3DFMT_D16_LOCKABLE == Format) ? TRUE : Lockable;
695 /* mark the texture as dirty so that it get's loaded first time around*/
696 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
697 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
698 This, Width, Height, Format, debug_d3dformat(Format),
699 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
704 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
705 DWORD Usage, WINED3DFORMAT Format, D3DPOOL Pool,
706 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
707 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
709 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
710 IWineD3DTextureImpl *object;
715 unsigned int pow2Width = Width;
716 unsigned int pow2Height = Height;
719 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) .... \n", This, Width, Height, Levels, Usage);
721 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, D3DRTYPE_TEXTURE, 0);
722 D3DINITILIZEBASETEXTURE(object->baseTexture);
723 object->width = Width;
724 object->height = Height;
726 /** Non-power2 support **/
727 /* Find the nearest pow2 match */
728 pow2Width = pow2Height = 1;
729 while (pow2Width < Width) pow2Width <<= 1;
730 while (pow2Height < Height) pow2Height <<= 1;
732 /** FIXME: add support for real non-power-two if it's provided by the video card **/
733 /* Precalculated scaling for 'faked' non power of two texture coords */
734 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
735 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
736 TRACE(" xf(%f) yf(%f) \n", object->pow2scalingFactorX, object->pow2scalingFactorY);
738 /* Calculate levels for mip mapping */
740 TRACE("calculating levels %d\n", object->baseTexture.levels);
741 object->baseTexture.levels++;
744 while (tmpW > 1 && tmpH > 1) {
745 tmpW = max(1, tmpW >> 1);
746 tmpH = max(1, tmpH >> 1);
747 object->baseTexture.levels++;
749 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
752 /* Generate all the surfaces */
755 for (i = 0; i < object->baseTexture.levels; i++)
757 /* use the callback to create the texture surface */
758 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
761 FIXME("Failed to create surface %p \n",object);
763 for (j = 0 ; j < i ; j++) {
764 IWineD3DSurface_Release(object->surfaces[j]);
766 /* heap free object */
767 HeapFree(GetProcessHeap(), 0, object);
773 IWineD3DSurface_SetContainer(object->surfaces[i], (IUnknown *)object);
774 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
775 /* calculate the next mipmap level */
776 tmpW = max(1, tmpW >> 1);
777 tmpH = max(1, tmpH >> 1);
780 TRACE("(%p) : Created texture %p\n", This, object);
784 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
785 UINT Width, UINT Height, UINT Depth,
786 UINT Levels, DWORD Usage,
787 WINED3DFORMAT Format, D3DPOOL Pool,
788 IWineD3DVolumeTexture **ppVolumeTexture,
789 HANDLE *pSharedHandle, IUnknown *parent,
790 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
792 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
793 IWineD3DVolumeTextureImpl *object;
799 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, D3DRTYPE_VOLUMETEXTURE, 0);
800 D3DINITILIZEBASETEXTURE(object->baseTexture);
802 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
803 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
805 object->width = Width;
806 object->height = Height;
807 object->depth = Depth;
809 /* Calculate levels for mip mapping */
811 object->baseTexture.levels++;
815 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
816 tmpW = max(1, tmpW >> 1);
817 tmpH = max(1, tmpH >> 1);
818 tmpD = max(1, tmpD >> 1);
819 object->baseTexture.levels++;
821 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
824 /* Generate all the surfaces */
829 for (i = 0; i < object->baseTexture.levels; i++)
831 /* Create the volume */
832 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
833 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
835 /* Set it's container to this object */
836 IWineD3DVolume_SetContainer(object->volumes[i], (IUnknown *)object);
838 /* calcualte the next mipmap level */
839 tmpW = max(1, tmpW >> 1);
840 tmpH = max(1, tmpH >> 1);
841 tmpD = max(1, tmpD >> 1);
844 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
845 TRACE("(%p) : Created volume texture %p\n", This, object);
849 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
850 UINT Width, UINT Height, UINT Depth,
852 WINED3DFORMAT Format, D3DPOOL Pool,
853 IWineD3DVolume** ppVolume,
854 HANDLE* pSharedHandle, IUnknown *parent) {
856 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
857 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
859 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, D3DRTYPE_VOLUME, ((Width * D3DFmtGetBpp(This, Format)) * Height * Depth))
861 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
862 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
864 object->currentDesc.Width = Width;
865 object->currentDesc.Height = Height;
866 object->currentDesc.Depth = Depth;
867 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
869 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
870 object->lockable = TRUE;
871 object->locked = FALSE;
872 memset(&object->lockedBox, 0, sizeof(D3DBOX));
873 object->dirty = TRUE;
875 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
878 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
879 UINT Levels, DWORD Usage,
880 WINED3DFORMAT Format, D3DPOOL Pool,
881 IWineD3DCubeTexture **ppCubeTexture,
882 HANDLE *pSharedHandle, IUnknown *parent,
883 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
885 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
886 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
890 unsigned int pow2EdgeLength = EdgeLength;
892 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, D3DRTYPE_CUBETEXTURE, 0);
893 D3DINITILIZEBASETEXTURE(object->baseTexture);
895 TRACE("(%p) Create Cube Texture \n", This);
897 /** Non-power2 support **/
899 /* Find the nearest pow2 match */
901 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
903 object->edgeLength = EdgeLength;
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 */
910 object->baseTexture.levels++;
913 tmpW = max(1, tmpW >> 1);
914 object->baseTexture.levels++;
916 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
919 /* Generate all the surfaces */
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);
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;
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;
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) */
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:
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);
990 D3DCREATEOBJECTINSTANCE(object, Query)
992 object->extendedData = 0;
993 TRACE("(%p) : Created Query %p\n", This, object);
997 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
998 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1000 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1001 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1002 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1005 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
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 **/
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");
1070 return D3DERR_NOTAVAILABLE;
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 **/
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);
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);
1130 XFree(object->visInfo);
1131 object->visInfo = NULL;
1133 if (NULL == object->glCtx) {
1134 ERR("cannot create glxContext\n");
1136 return D3DERR_NOTAVAILABLE;
1140 if (object->glCtx == NULL) {
1141 ERR("Error in context creation !\n");
1142 return D3DERR_INVALIDCALL;
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)) {
1164 /* Get info on the current display setup */
1165 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1166 bpp = GetDeviceCaps(hdc, BITSPIXEL);
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))) {
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;
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;
1295 /*********************
1296 * Setup some defaults and clear down the buffers
1297 *******************/
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");
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 (if there was one)*/
1336 if (This->swapchains != NULL) {
1337 /** TODO: restore the context and drawable **/
1338 glXMakeCurrent(object->display, oldDrawable, oldContext);
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);
1385 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1386 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1387 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1388 unsigned int numberOfSwapChains = 0;
1389 SwapChainList *swapchain;
1391 swapchain = This->swapchains;
1392 /* itterate through the list to get a count */
1393 while (swapchain != NULL) {
1394 swapchain = swapchain->next;
1395 numberOfSwapChains++;
1398 TRACE("(%p) returning %d\n", This, numberOfSwapChains);
1399 return numberOfSwapChains;
1402 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1403 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1404 SwapChainList *swapchain;
1405 HRESULT hr = D3DERR_INVALIDCALL;
1406 swapchain = This->swapchains;
1407 TRACE("(%p) : swapchain %d \n", This, iSwapChain);
1410 TRACE("(%p) Finding swapchain %d\n", This, iSwapChain);
1411 while (iSwapChain > 0 && swapchain != NULL) {
1412 swapchain = swapchain->next;
1416 if (iSwapChain > 0 || swapchain == NULL) {
1417 FIXME("(%p) Unable to find swapchain %d\n", This, iSwapChain);
1420 /** TODO: move off to a linkesList implementation **/
1421 *pSwapChain = swapchain->swapchain;
1422 IWineD3DSwapChain_AddRef(*pSwapChain);
1426 TRACE("(%p) returning %p\n", This, *pSwapChain);
1430 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
1431 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1433 FIXME("(%p) : Stub\n",This);
1439 * Vertex Declaration
1441 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1442 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1443 IWineD3DVertexDeclarationImpl *object = NULL;
1444 HRESULT hr = D3D_OK;
1445 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1446 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1449 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1454 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1455 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DVertexShader** ppVertexShader, IUnknown *parent) {
1456 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1457 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1458 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1460 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1461 IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1466 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DPixelShader** ppPixelShader, IUnknown *parent) {
1467 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1468 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1470 D3DCREATEOBJECTINSTANCE(object, PixelShader)
1472 object->function = pFunction;
1473 #else /* TODO: pixel shader set function */
1474 IWineD3DPixelShaderImpl_SetFuction(*ppPixelShader, pFunction);
1476 FIXME("(%p) : STUB: Created Pixel shader %p\n", This, ppPixelShader);
1482 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice* iface, IWineD3D** ppD3D) {
1483 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1484 *ppD3D= This->wineD3D;
1485 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1486 IWineD3D_AddRef(*ppD3D);
1490 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1491 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1492 * Into the video ram as possible and seeing how many fit
1493 * you can also get the correct initial value from via X and ATI's driver
1494 *******************/
1495 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1496 static BOOL showfixmes = TRUE;
1498 FIXME("(%p) : stub, emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1499 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1502 TRACE("(%p) : emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1503 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1504 /* videomemory is simulated videomemory + AGP memory left */
1505 return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1513 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1514 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1516 /* Update the current state block */
1517 This->updateStateBlock->fvf = fvf;
1518 This->updateStateBlock->changed.fvf = TRUE;
1519 This->updateStateBlock->set.fvf = TRUE;
1521 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1522 /* clear down the vertex declaration
1523 NOTE: Axis and Allies doesn't work properly otherwise
1524 (may be a stateblock problem though!)
1526 /* No difference if recording or not */
1527 return IWineD3DDevice_SetVertexDeclaration(iface, NULL);
1532 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1533 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1534 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1535 *pfvf = This->stateBlock->fvf;
1540 * Get / Set Stream Source
1542 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1543 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1544 IWineD3DVertexBuffer *oldSrc;
1546 oldSrc = This->stateBlock->streamSource[StreamNumber];
1547 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1549 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
1550 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
1551 This->updateStateBlock->streamStride[StreamNumber] = Stride;
1552 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
1553 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
1555 /* Handle recording of state blocks */
1556 if (This->isRecordingState) {
1557 TRACE("Recording... not performing anything\n");
1561 /* Not recording... */
1562 if (pStreamData != NULL) {
1563 IUnknown *newVertexBufferParent;
1564 /* GetParent will add a ref, so leave it hanging until the vertex buffer is cleared */
1565 IWineD3DVertexBuffer_GetParent(pStreamData, &newVertexBufferParent);
1567 if (oldSrc != NULL) {
1568 IUnknown *oldVertexBufferParent;
1569 IWineD3DVertexBuffer_GetParent(oldSrc, &oldVertexBufferParent);
1570 IUnknown_Release(oldVertexBufferParent);
1571 IUnknown_Release(oldVertexBufferParent);
1577 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
1578 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1580 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
1581 *pStream = This->stateBlock->streamSource[StreamNumber];
1582 *pStride = This->stateBlock->streamStride[StreamNumber];
1583 *pOffset = This->stateBlock->streamOffset[StreamNumber];
1584 if (*pStream != NULL) IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
1588 /*Should be quite easy, just an extension of vertexdata
1590 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1592 The divider is a bit odd though
1594 VertexOffset = StartVertex / Divider * StreamStride +
1595 VertexIndex / Divider * StreamStride + StreamOffset
1598 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
1599 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1601 FIXME("(%p) : stub\n", This);
1605 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
1606 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1608 FIXME("(%p) : stub\n", This);
1613 * Get / Set & Multiply Transform
1615 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1616 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1618 /* Most of this routine, comments included copied from ddraw tree initially: */
1619 TRACE("(%p) : Transform State=%d\n", This, d3dts);
1621 /* Handle recording of state blocks */
1622 if (This->isRecordingState) {
1623 TRACE("Recording... not performing anything\n");
1624 This->updateStateBlock->changed.transform[d3dts] = TRUE;
1625 This->updateStateBlock->set.transform[d3dts] = TRUE;
1626 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1631 * If the new matrix is the same as the current one,
1632 * we cut off any further processing. this seems to be a reasonable
1633 * optimization because as was noticed, some apps (warcraft3 for example)
1634 * tend towards setting the same matrix repeatedly for some reason.
1636 * From here on we assume that the new matrix is different, wherever it matters.
1638 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1639 TRACE("The app is setting the same matrix over again\n");
1642 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1646 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1647 where ViewMat = Camera space, WorldMat = world space.
1649 In OpenGL, camera and world space is combined into GL_MODELVIEW
1650 matrix. The Projection matrix stay projection matrix.
1653 /* Capture the times we can just ignore the change for now */
1654 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1655 This->modelview_valid = FALSE;
1658 } else if (d3dts == D3DTS_PROJECTION) {
1659 This->proj_valid = FALSE;
1662 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1663 /* Indexed Vertex Blending Matrices 256 -> 511 */
1664 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1665 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1669 /* Now we really are going to have to change a matrix */
1672 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1673 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
1674 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1677 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1678 * NOTE: We have to reset the positions even if the light/plane is not currently
1679 * enabled, since the call to enable it will not reset the position.
1680 * NOTE2: Apparently texture transforms do NOT need reapplying
1683 PLIGHTINFOEL *lightChain = NULL;
1684 This->modelview_valid = FALSE;
1685 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
1687 glMatrixMode(GL_MODELVIEW);
1688 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1690 glLoadMatrixf((float *)lpmatrix);
1691 checkGLcall("glLoadMatrixf(...)");
1694 lightChain = This->stateBlock->lights;
1695 while (lightChain && lightChain->glIndex != -1) {
1696 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1697 checkGLcall("glLightfv posn");
1698 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1699 checkGLcall("glLightfv dirn");
1700 lightChain = lightChain->next;
1703 /* Reset Clipping Planes if clipping is enabled */
1704 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1705 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1706 checkGLcall("glClipPlane");
1710 } else { /* What was requested!?? */
1711 WARN("invalid matrix specified: %i\n", d3dts);
1714 /* Release lock, all done */
1719 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1720 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1721 TRACE("(%p) : for Transform State %d\n", This, State);
1722 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1726 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1727 D3DMATRIX *mat = NULL;
1730 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1731 * below means it will be recorded in a state block change, but it
1732 * works regardless where it is recorded.
1733 * If this is found to be wrong, change to StateBlock.
1735 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1736 TRACE("(%p) : For state %u\n", This, State);
1738 if (State < HIGHEST_TRANSFORMSTATE)
1740 mat = &This->updateStateBlock->transforms[State];
1742 FIXME("Unhandled transform state!!\n");
1745 /* Copied from ddraw code: */
1746 temp.u.s._11 = (mat->u.s._11 * pMatrix->u.s._11) + (mat->u.s._21 * pMatrix->u.s._12) +
1747 (mat->u.s._31 * pMatrix->u.s._13) + (mat->u.s._41 * pMatrix->u.s._14);
1748 temp.u.s._21 = (mat->u.s._11 * pMatrix->u.s._21) + (mat->u.s._21 * pMatrix->u.s._22) +
1749 (mat->u.s._31 * pMatrix->u.s._23) + (mat->u.s._41 * pMatrix->u.s._24);
1750 temp.u.s._31 = (mat->u.s._11 * pMatrix->u.s._31) + (mat->u.s._21 * pMatrix->u.s._32) +
1751 (mat->u.s._31 * pMatrix->u.s._33) + (mat->u.s._41 * pMatrix->u.s._34);
1752 temp.u.s._41 = (mat->u.s._11 * pMatrix->u.s._41) + (mat->u.s._21 * pMatrix->u.s._42) +
1753 (mat->u.s._31 * pMatrix->u.s._43) + (mat->u.s._41 * pMatrix->u.s._44);
1755 temp.u.s._12 = (mat->u.s._12 * pMatrix->u.s._11) + (mat->u.s._22 * pMatrix->u.s._12) +
1756 (mat->u.s._32 * pMatrix->u.s._13) + (mat->u.s._42 * pMatrix->u.s._14);
1757 temp.u.s._22 = (mat->u.s._12 * pMatrix->u.s._21) + (mat->u.s._22 * pMatrix->u.s._22) +
1758 (mat->u.s._32 * pMatrix->u.s._23) + (mat->u.s._42 * pMatrix->u.s._24);
1759 temp.u.s._32 = (mat->u.s._12 * pMatrix->u.s._31) + (mat->u.s._22 * pMatrix->u.s._32) +
1760 (mat->u.s._32 * pMatrix->u.s._33) + (mat->u.s._42 * pMatrix->u.s._34);
1761 temp.u.s._42 = (mat->u.s._12 * pMatrix->u.s._41) + (mat->u.s._22 * pMatrix->u.s._42) +
1762 (mat->u.s._32 * pMatrix->u.s._43) + (mat->u.s._42 * pMatrix->u.s._44);
1764 temp.u.s._13 = (mat->u.s._13 * pMatrix->u.s._11) + (mat->u.s._23 * pMatrix->u.s._12) +
1765 (mat->u.s._33 * pMatrix->u.s._13) + (mat->u.s._43 * pMatrix->u.s._14);
1766 temp.u.s._23 = (mat->u.s._13 * pMatrix->u.s._21) + (mat->u.s._23 * pMatrix->u.s._22) +
1767 (mat->u.s._33 * pMatrix->u.s._23) + (mat->u.s._43 * pMatrix->u.s._24);
1768 temp.u.s._33 = (mat->u.s._13 * pMatrix->u.s._31) + (mat->u.s._23 * pMatrix->u.s._32) +
1769 (mat->u.s._33 * pMatrix->u.s._33) + (mat->u.s._43 * pMatrix->u.s._34);
1770 temp.u.s._43 = (mat->u.s._13 * pMatrix->u.s._41) + (mat->u.s._23 * pMatrix->u.s._42) +
1771 (mat->u.s._33 * pMatrix->u.s._43) + (mat->u.s._43 * pMatrix->u.s._44);
1773 temp.u.s._14 = (mat->u.s._14 * pMatrix->u.s._11) + (mat->u.s._24 * pMatrix->u.s._12) +
1774 (mat->u.s._34 * pMatrix->u.s._13) + (mat->u.s._44 * pMatrix->u.s._14);
1775 temp.u.s._24 = (mat->u.s._14 * pMatrix->u.s._21) + (mat->u.s._24 * pMatrix->u.s._22) +
1776 (mat->u.s._34 * pMatrix->u.s._23) + (mat->u.s._44 * pMatrix->u.s._24);
1777 temp.u.s._34 = (mat->u.s._14 * pMatrix->u.s._31) + (mat->u.s._24 * pMatrix->u.s._32) +
1778 (mat->u.s._34 * pMatrix->u.s._33) + (mat->u.s._44 * pMatrix->u.s._34);
1779 temp.u.s._44 = (mat->u.s._14 * pMatrix->u.s._41) + (mat->u.s._24 * pMatrix->u.s._42) +
1780 (mat->u.s._34 * pMatrix->u.s._43) + (mat->u.s._44 * pMatrix->u.s._44);
1782 /* Apply change via set transform - will reapply to eg. lights this way */
1783 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
1788 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
1790 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1791 you can reference any indexes you want as long as that number max are enabled at any
1792 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1793 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1794 but when recording, just build a chain pretty much of commands to be replayed. */
1796 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
1798 PLIGHTINFOEL *object, *temp;
1800 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1801 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1803 /* If recording state block, just add to end of lights chain */
1804 if (This->isRecordingState) {
1805 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1806 if (NULL == object) {
1807 return D3DERR_OUTOFVIDEOMEMORY;
1809 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1810 object->OriginalIndex = Index;
1811 object->glIndex = -1;
1812 object->changed = TRUE;
1814 /* Add to the END of the chain of lights changes to be replayed */
1815 if (This->updateStateBlock->lights == NULL) {
1816 This->updateStateBlock->lights = object;
1818 temp = This->updateStateBlock->lights;
1819 while (temp->next != NULL) temp=temp->next;
1820 temp->next = object;
1822 TRACE("Recording... not performing anything more\n");
1826 /* Ok, not recording any longer so do real work */
1827 object = This->stateBlock->lights;
1828 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1830 /* If we didn't find it in the list of lights, time to add it */
1831 if (object == NULL) {
1832 PLIGHTINFOEL *insertAt,*prevPos;
1834 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1835 if (NULL == object) {
1836 return D3DERR_OUTOFVIDEOMEMORY;
1838 object->OriginalIndex = Index;
1839 object->glIndex = -1;
1841 /* Add it to the front of list with the idea that lights will be changed as needed
1842 BUT after any lights currently assigned GL indexes */
1843 insertAt = This->stateBlock->lights;
1845 while (insertAt != NULL && insertAt->glIndex != -1) {
1847 insertAt = insertAt->next;
1850 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1851 This->stateBlock->lights = object;
1852 } else if (insertAt == NULL) { /* End of list */
1853 prevPos->next = object;
1854 object->prev = prevPos;
1855 } else { /* Middle of chain */
1856 if (prevPos == NULL) {
1857 This->stateBlock->lights = object;
1859 prevPos->next = object;
1861 object->prev = prevPos;
1862 object->next = insertAt;
1863 insertAt->prev = object;
1867 /* Initialze the object */
1868 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,
1869 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1870 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1871 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1872 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1873 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1874 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1876 /* Save away the information */
1877 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1879 switch (pLight->Type) {
1880 case D3DLIGHT_POINT:
1882 object->lightPosn[0] = pLight->Position.x;
1883 object->lightPosn[1] = pLight->Position.y;
1884 object->lightPosn[2] = pLight->Position.z;
1885 object->lightPosn[3] = 1.0f;
1886 object->cutoff = 180.0f;
1890 case D3DLIGHT_DIRECTIONAL:
1892 object->lightPosn[0] = -pLight->Direction.x;
1893 object->lightPosn[1] = -pLight->Direction.y;
1894 object->lightPosn[2] = -pLight->Direction.z;
1895 object->lightPosn[3] = 0.0;
1896 object->exponent = 0.0f;
1897 object->cutoff = 180.0f;
1902 object->lightPosn[0] = pLight->Position.x;
1903 object->lightPosn[1] = pLight->Position.y;
1904 object->lightPosn[2] = pLight->Position.z;
1905 object->lightPosn[3] = 1.0;
1908 object->lightDirn[0] = pLight->Direction.x;
1909 object->lightDirn[1] = pLight->Direction.y;
1910 object->lightDirn[2] = pLight->Direction.z;
1911 object->lightDirn[3] = 1.0;
1914 * opengl-ish and d3d-ish spot lights use too different models for the
1915 * light "intensity" as a function of the angle towards the main light direction,
1916 * so we only can approximate very roughly.
1917 * however spot lights are rather rarely used in games (if ever used at all).
1918 * furthermore if still used, probably nobody pays attention to such details.
1920 if (pLight->Falloff == 0) {
1923 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1925 if (rho < 0.0001) rho = 0.0001f;
1926 object->exponent = -0.3/log(cos(rho/2));
1927 object->cutoff = pLight->Phi*90/M_PI;
1933 FIXME("Unrecognized light type %d\n", pLight->Type);
1936 /* Update the live definitions if the light is currently assigned a glIndex */
1937 if (object->glIndex != -1) {
1938 setup_light(iface, object->glIndex, object);
1943 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
1944 PLIGHTINFOEL *lightInfo = NULL;
1945 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1946 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1948 /* Locate the light in the live lights */
1949 lightInfo = This->stateBlock->lights;
1950 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1952 if (lightInfo == NULL) {
1953 TRACE("Light information requested but light not defined\n");
1954 return D3DERR_INVALIDCALL;
1957 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
1962 * Get / Set Light Enable
1963 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
1965 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
1966 PLIGHTINFOEL *lightInfo = NULL;
1967 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1968 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1970 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1971 if (This->isRecordingState) {
1972 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1973 if (NULL == lightInfo) {
1974 return D3DERR_OUTOFVIDEOMEMORY;
1976 lightInfo->OriginalIndex = Index;
1977 lightInfo->glIndex = -1;
1978 lightInfo->enabledChanged = TRUE;
1980 /* Add to the END of the chain of lights changes to be replayed */
1981 if (This->updateStateBlock->lights == NULL) {
1982 This->updateStateBlock->lights = lightInfo;
1984 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
1985 while (temp->next != NULL) temp=temp->next;
1986 temp->next = lightInfo;
1988 TRACE("Recording... not performing anything more\n");
1992 /* Not recording... So, locate the light in the live lights */
1993 lightInfo = This->stateBlock->lights;
1994 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1996 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1997 if (lightInfo == NULL) {
1998 D3DLIGHT9 lightParms;
1999 /* Warning - untested code :-) Prob safe to change fixme to a trace but
2000 wait until someone confirms it seems to work! */
2001 TRACE("Light enabled requested but light not defined, so defining one!\n");
2002 lightParms.Type = D3DLIGHT_DIRECTIONAL;
2003 lightParms.Diffuse.r = 1.0;
2004 lightParms.Diffuse.g = 1.0;
2005 lightParms.Diffuse.b = 1.0;
2006 lightParms.Diffuse.a = 0.0;
2007 lightParms.Specular.r = 0.0;
2008 lightParms.Specular.g = 0.0;
2009 lightParms.Specular.b = 0.0;
2010 lightParms.Specular.a = 0.0;
2011 lightParms.Ambient.r = 0.0;
2012 lightParms.Ambient.g = 0.0;
2013 lightParms.Ambient.b = 0.0;
2014 lightParms.Ambient.a = 0.0;
2015 lightParms.Position.x = 0.0;
2016 lightParms.Position.y = 0.0;
2017 lightParms.Position.z = 0.0;
2018 lightParms.Direction.x = 0.0;
2019 lightParms.Direction.y = 0.0;
2020 lightParms.Direction.z = 1.0;
2021 lightParms.Range = 0.0;
2022 lightParms.Falloff = 0.0;
2023 lightParms.Attenuation0 = 0.0;
2024 lightParms.Attenuation1 = 0.0;
2025 lightParms.Attenuation2 = 0.0;
2026 lightParms.Theta = 0.0;
2027 lightParms.Phi = 0.0;
2028 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
2030 /* Search for it again! Should be fairly quick as near head of list */
2031 lightInfo = This->stateBlock->lights;
2032 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2033 if (lightInfo == NULL) {
2034 FIXME("Adding default lights has failed dismally\n");
2035 return D3DERR_INVALIDCALL;
2039 /* OK, we now have a light... */
2040 if (Enable == FALSE) {
2042 /* If we are disabling it, check it was enabled, and
2043 still only do something if it has assigned a glIndex (which it should have!) */
2044 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2045 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2047 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2048 checkGLcall("glDisable GL_LIGHT0+Index");
2051 TRACE("Nothing to do as light was not enabled\n");
2053 lightInfo->lightEnabled = FALSE;
2056 /* We are enabling it. If it is enabled, it's really simple */
2057 if (lightInfo->lightEnabled) {
2059 TRACE("Nothing to do as light was enabled\n");
2061 /* If it already has a glIndex, it's still simple */
2062 } else if (lightInfo->glIndex != -1) {
2063 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2064 lightInfo->lightEnabled = TRUE;
2066 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2067 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2070 /* Otherwise got to find space - lights are ordered gl indexes first */
2072 PLIGHTINFOEL *bsf = NULL;
2073 PLIGHTINFOEL *pos = This->stateBlock->lights;
2074 PLIGHTINFOEL *prev = NULL;
2078 /* Try to minimize changes as much as possible */
2079 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2081 /* Try to remember which index can be replaced if necessary */
2082 if (bsf==NULL && pos->lightEnabled == FALSE) {
2083 /* Found a light we can replace, save as best replacement */
2087 /* Step to next space */
2093 /* If we have too many active lights, fail the call */
2094 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2095 FIXME("Program requests too many concurrent lights\n");
2096 return D3DERR_INVALIDCALL;
2098 /* If we have allocated all lights, but not all are enabled,
2099 reuse one which is not enabled */
2100 } else if (Index == This->maxConcurrentLights) {
2101 /* use bsf - Simply swap the new light and the BSF one */
2102 PLIGHTINFOEL *bsfNext = bsf->next;
2103 PLIGHTINFOEL *bsfPrev = bsf->prev;
2106 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2107 if (bsf->prev != NULL) {
2108 bsf->prev->next = lightInfo;
2110 This->stateBlock->lights = lightInfo;
2113 /* If not side by side, lots of chains to update */
2114 if (bsf->next != lightInfo) {
2115 lightInfo->prev->next = bsf;
2116 bsf->next->prev = lightInfo;
2117 bsf->next = lightInfo->next;
2118 bsf->prev = lightInfo->prev;
2119 lightInfo->next = bsfNext;
2120 lightInfo->prev = bsfPrev;
2124 bsf->prev = lightInfo;
2125 bsf->next = lightInfo->next;
2126 lightInfo->next = bsf;
2127 lightInfo->prev = bsfPrev;
2132 glIndex = bsf->glIndex;
2134 lightInfo->glIndex = glIndex;
2135 lightInfo->lightEnabled = TRUE;
2137 /* Finally set up the light in gl itself */
2138 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2140 setup_light(iface, glIndex, lightInfo);
2141 glEnable(GL_LIGHT0 + glIndex);
2142 checkGLcall("glEnable GL_LIGHT0 new setup");
2145 /* If we reached the end of the allocated lights, with space in the
2146 gl lights, setup a new light */
2147 } else if (pos->glIndex == -1) {
2149 /* We reached the end of the allocated gl lights, so already
2150 know the index of the next one! */
2152 lightInfo->glIndex = glIndex;
2153 lightInfo->lightEnabled = TRUE;
2155 /* In an ideal world, it's already in the right place */
2156 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2157 /* No need to move it */
2159 /* Remove this light from the list */
2160 lightInfo->prev->next = lightInfo->next;
2161 if (lightInfo->next != NULL) {
2162 lightInfo->next->prev = lightInfo->prev;
2165 /* Add in at appropriate place (inbetween prev and pos) */
2166 lightInfo->prev = prev;
2167 lightInfo->next = pos;
2169 This->stateBlock->lights = lightInfo;
2171 prev->next = lightInfo;
2174 pos->prev = lightInfo;
2178 /* Finally set up the light in gl itself */
2179 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2181 setup_light(iface, glIndex, lightInfo);
2182 glEnable(GL_LIGHT0 + glIndex);
2183 checkGLcall("glEnable GL_LIGHT0 new setup");
2192 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2194 PLIGHTINFOEL *lightInfo = NULL;
2195 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2196 TRACE("(%p) : for idx(%ld)\n", This, Index);
2198 /* Locate the light in the live lights */
2199 lightInfo = This->stateBlock->lights;
2200 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2202 if (lightInfo == NULL) {
2203 TRACE("Light enabled state requested but light not defined\n");
2204 return D3DERR_INVALIDCALL;
2206 *pEnable = lightInfo->lightEnabled;
2211 * Get / Set Clip Planes
2213 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2214 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2215 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2217 /* Validate Index */
2218 if (Index >= GL_LIMITS(clipplanes)) {
2219 TRACE("Application has requested clipplane this device doesn't support\n");
2220 return D3DERR_INVALIDCALL;
2223 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2224 This->updateStateBlock->set.clipplane[Index] = TRUE;
2225 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2226 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2227 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2228 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2230 /* Handle recording of state blocks */
2231 if (This->isRecordingState) {
2232 TRACE("Recording... not performing anything\n");
2240 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2241 glMatrixMode(GL_MODELVIEW);
2243 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2245 TRACE("Clipplane [%f,%f,%f,%f]\n",
2246 This->updateStateBlock->clipplane[Index][0],
2247 This->updateStateBlock->clipplane[Index][1],
2248 This->updateStateBlock->clipplane[Index][2],
2249 This->updateStateBlock->clipplane[Index][3]);
2250 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2251 checkGLcall("glClipPlane");
2259 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2260 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2261 TRACE("(%p) : for idx %ld\n", This, Index);
2263 /* Validate Index */
2264 if (Index >= GL_LIMITS(clipplanes)) {
2265 TRACE("Application has requested clipplane this device doesn't support\n");
2266 return D3DERR_INVALIDCALL;
2269 pPlane[0] = This->stateBlock->clipplane[Index][0];
2270 pPlane[1] = This->stateBlock->clipplane[Index][1];
2271 pPlane[2] = This->stateBlock->clipplane[Index][2];
2272 pPlane[3] = This->stateBlock->clipplane[Index][3];
2277 * Get / Set Clip Plane Status
2278 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2280 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2281 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2282 FIXME("(%p) : stub\n", This);
2283 if (NULL == pClipStatus) {
2284 return D3DERR_INVALIDCALL;
2286 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2287 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2291 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2292 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2293 FIXME("(%p) : stub\n", This);
2294 if (NULL == pClipStatus) {
2295 return D3DERR_INVALIDCALL;
2297 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2298 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2303 * Get / Set Material
2304 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2306 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2307 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2309 This->updateStateBlock->changed.material = TRUE;
2310 This->updateStateBlock->set.material = TRUE;
2311 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2313 /* Handle recording of state blocks */
2314 if (This->isRecordingState) {
2315 TRACE("Recording... not performing anything\n");
2320 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2321 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2322 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2323 pMaterial->Ambient.b, pMaterial->Ambient.a);
2324 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2325 pMaterial->Specular.b, pMaterial->Specular.a);
2326 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2327 pMaterial->Emissive.b, pMaterial->Emissive.a);
2328 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2330 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2331 checkGLcall("glMaterialfv(GL_AMBIENT)");
2332 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2333 checkGLcall("glMaterialfv(GL_DIFFUSE)");
2335 /* Only change material color if specular is enabled, otherwise it is set to black */
2336 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2337 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2338 checkGLcall("glMaterialfv(GL_SPECULAR");
2340 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2341 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2342 checkGLcall("glMaterialfv(GL_SPECULAR");
2344 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2345 checkGLcall("glMaterialfv(GL_EMISSION)");
2346 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2347 checkGLcall("glMaterialf(GL_SHININESS");
2353 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2354 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2355 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2356 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2357 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2358 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2359 pMaterial->Ambient.b, pMaterial->Ambient.a);
2360 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2361 pMaterial->Specular.b, pMaterial->Specular.a);
2362 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2363 pMaterial->Emissive.b, pMaterial->Emissive.a);
2364 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2372 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2373 UINT BaseVertexIndex) {
2374 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2375 IWineD3DIndexBuffer *oldIdxs;
2377 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2378 oldIdxs = This->updateStateBlock->pIndexData;
2380 This->updateStateBlock->changed.indices = TRUE;
2381 This->updateStateBlock->set.indices = TRUE;
2382 This->updateStateBlock->pIndexData = pIndexData;
2383 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2385 /* Handle recording of state blocks */
2386 if (This->isRecordingState) {
2387 TRACE("Recording... not performing anything\n");
2392 IUnknown *indexBufferParent;
2393 /* Getting the parent causes a addRef... it gets released when the indicies are clear */
2394 IWineD3DIndexBuffer_GetParent(pIndexData, &indexBufferParent);
2397 IUnknown *indexBufferParent;
2398 IWineD3DIndexBuffer_GetParent(oldIdxs, &indexBufferParent);
2399 IUnknown_Release(indexBufferParent);
2400 IUnknown_Release(indexBufferParent);
2405 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2406 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2408 *ppIndexData = This->stateBlock->pIndexData;
2410 /* up ref count on ppindexdata */
2412 IWineD3DIndexBuffer_AddRef(*ppIndexData);
2413 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2414 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
2416 TRACE("(%p) No index data set\n", This);
2418 TRACE("Returning %p %d \n",*ppIndexData, *pBaseVertexIndex);
2424 * Get / Set Viewports
2426 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2427 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2429 TRACE("(%p)\n", This);
2430 This->updateStateBlock->changed.viewport = TRUE;
2431 This->updateStateBlock->set.viewport = TRUE;
2432 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2434 /* Handle recording of state blocks */
2435 if (This->isRecordingState) {
2436 TRACE("Recording... not performing anything\n");
2442 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2443 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2445 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2446 checkGLcall("glDepthRange");
2447 /* Note: GL requires lower left, DirectX supplies upper left */
2448 /* TODO: replace usage of renderTarget with context management */
2449 glViewport(pViewport->X,
2450 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2451 pViewport->Width, pViewport->Height);
2453 checkGLcall("glViewport");
2461 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2462 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2463 TRACE("(%p)\n", This);
2464 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2469 * Get / Set Render States
2470 * TODO: Verify against dx9 definitions
2472 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2474 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2475 DWORD OldValue = This->stateBlock->renderState[State];
2477 /* Simple way of referring to either a DWORD or a 4 byte float */
2483 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2484 This->updateStateBlock->changed.renderState[State] = TRUE;
2485 This->updateStateBlock->set.renderState[State] = TRUE;
2486 This->updateStateBlock->renderState[State] = Value;
2488 /* Handle recording of state blocks */
2489 if (This->isRecordingState) {
2490 TRACE("Recording... not performing anything\n");
2497 case WINED3DRS_FILLMODE :
2498 switch ((D3DFILLMODE) Value) {
2499 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2500 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2501 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2503 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
2505 checkGLcall("glPolygonMode (fillmode)");
2508 case WINED3DRS_LIGHTING :
2510 glEnable(GL_LIGHTING);
2511 checkGLcall("glEnable GL_LIGHTING");
2513 glDisable(GL_LIGHTING);
2514 checkGLcall("glDisable GL_LIGHTING");
2518 case WINED3DRS_ZENABLE :
2519 switch ((D3DZBUFFERTYPE) Value) {
2521 glDisable(GL_DEPTH_TEST);
2522 checkGLcall("glDisable GL_DEPTH_TEST");
2525 glEnable(GL_DEPTH_TEST);
2526 checkGLcall("glEnable GL_DEPTH_TEST");
2529 glEnable(GL_DEPTH_TEST);
2530 checkGLcall("glEnable GL_DEPTH_TEST");
2531 FIXME("W buffer is not well handled\n");
2534 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2538 case WINED3DRS_CULLMODE :
2540 /* If we are culling "back faces with clockwise vertices" then
2541 set front faces to be counter clockwise and enable culling
2543 switch ((D3DCULL) Value) {
2545 glDisable(GL_CULL_FACE);
2546 checkGLcall("glDisable GL_CULL_FACE");
2549 glEnable(GL_CULL_FACE);
2550 checkGLcall("glEnable GL_CULL_FACE");
2551 if (This->renderUpsideDown) {
2553 checkGLcall("glFrontFace GL_CW");
2555 glFrontFace(GL_CCW);
2556 checkGLcall("glFrontFace GL_CCW");
2558 glCullFace(GL_BACK);
2561 glEnable(GL_CULL_FACE);
2562 checkGLcall("glEnable GL_CULL_FACE");
2563 if (This->renderUpsideDown) {
2564 glFrontFace(GL_CCW);
2565 checkGLcall("glFrontFace GL_CCW");
2568 checkGLcall("glFrontFace GL_CW");
2570 glCullFace(GL_BACK);
2573 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2577 case WINED3DRS_SHADEMODE :
2578 switch ((D3DSHADEMODE) Value) {
2580 glShadeModel(GL_FLAT);
2581 checkGLcall("glShadeModel");
2583 case D3DSHADE_GOURAUD:
2584 glShadeModel(GL_SMOOTH);
2585 checkGLcall("glShadeModel");
2587 case D3DSHADE_PHONG:
2588 FIXME("D3DSHADE_PHONG isn't supported?\n");
2591 return D3DERR_INVALIDCALL;
2593 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2597 case WINED3DRS_DITHERENABLE :
2599 glEnable(GL_DITHER);
2600 checkGLcall("glEnable GL_DITHER");
2602 glDisable(GL_DITHER);
2603 checkGLcall("glDisable GL_DITHER");
2607 case WINED3DRS_ZWRITEENABLE :
2610 checkGLcall("glDepthMask");
2613 checkGLcall("glDepthMask");
2617 case WINED3DRS_ZFUNC :
2619 int glParm = GL_LESS;
2621 switch ((D3DCMPFUNC) Value) {
2622 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2623 case D3DCMP_LESS: glParm=GL_LESS; break;
2624 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2625 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2626 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2627 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2628 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2629 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2631 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2633 glDepthFunc(glParm);
2634 checkGLcall("glDepthFunc");
2638 case WINED3DRS_AMBIENT :
2641 D3DCOLORTOGLFLOAT4(Value, col);
2642 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2643 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2644 checkGLcall("glLightModel for MODEL_AMBIENT");
2649 case WINED3DRS_ALPHABLENDENABLE :
2652 checkGLcall("glEnable GL_BLEND");
2654 glDisable(GL_BLEND);
2655 checkGLcall("glDisable GL_BLEND");
2659 case WINED3DRS_SRCBLEND :
2660 case WINED3DRS_DESTBLEND :
2662 int newVal = GL_ZERO;
2664 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2665 case D3DBLEND_ONE : newVal = GL_ONE; break;
2666 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2667 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2668 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2669 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2670 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2671 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2672 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2673 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2674 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2676 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2677 This->srcBlend = newVal;
2678 This->dstBlend = newVal;
2681 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2682 This->srcBlend = newVal;
2683 This->dstBlend = newVal;
2686 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2689 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2690 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2691 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2692 glBlendFunc(This->srcBlend, This->dstBlend);
2694 checkGLcall("glBlendFunc");
2698 case WINED3DRS_ALPHATESTENABLE :
2700 glEnable(GL_ALPHA_TEST);
2701 checkGLcall("glEnable GL_ALPHA_TEST");
2703 glDisable(GL_ALPHA_TEST);
2704 checkGLcall("glDisable GL_ALPHA_TEST");
2708 case WINED3DRS_ALPHAFUNC :
2710 int glParm = GL_LESS;
2711 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2713 switch ((D3DCMPFUNC) Value) {
2714 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2715 case D3DCMP_LESS: glParm = GL_LESS; break;
2716 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2717 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2718 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2719 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2720 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2721 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2723 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2725 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2726 glAlphaFunc(glParm, ref);
2727 This->alphafunc = glParm;
2728 checkGLcall("glAlphaFunc");
2732 case WINED3DRS_ALPHAREF :
2734 int glParm = This->alphafunc;
2737 ref = ((float) Value) / 255.0f;
2738 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2739 glAlphaFunc(glParm, ref);
2740 checkGLcall("glAlphaFunc");
2744 case WINED3DRS_CLIPPLANEENABLE :
2745 case WINED3DRS_CLIPPING :
2747 /* Ensure we only do the changed clip planes */
2748 DWORD enable = 0xFFFFFFFF;
2749 DWORD disable = 0x00000000;
2751 /* If enabling / disabling all */
2752 if (State == WINED3DRS_CLIPPING) {
2754 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2757 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2761 enable = Value & ~OldValue;
2762 disable = ~Value & OldValue;
2765 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2766 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2767 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2768 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2769 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2770 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2772 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2773 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2774 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2775 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2776 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2777 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2779 /** update clipping status */
2781 This->stateBlock->clip_status.ClipUnion = 0;
2782 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
2784 This->stateBlock->clip_status.ClipUnion = 0;
2785 This->stateBlock->clip_status.ClipIntersection = 0;
2790 case WINED3DRS_BLENDOP :
2792 int glParm = GL_FUNC_ADD;
2794 switch ((D3DBLENDOP) Value) {
2795 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2796 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2797 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2798 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2799 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2801 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2803 TRACE("glBlendEquation(%x)\n", glParm);
2804 glBlendEquation(glParm);
2805 checkGLcall("glBlendEquation");
2809 case WINED3DRS_TEXTUREFACTOR :
2813 /* Note the texture color applies to all textures whereas
2814 GL_TEXTURE_ENV_COLOR applies to active only */
2816 D3DCOLORTOGLFLOAT4(Value, col);
2817 /* Set the default alpha blend color */
2818 glBlendColor(col[0], col[1], col[2], col[3]);
2819 checkGLcall("glBlendColor");
2821 /* And now the default texture color as well */
2822 for (i = 0; i < GL_LIMITS(textures); i++) {
2824 /* Note the D3DRS value applies to all textures, but GL has one
2825 per texture, so apply it now ready to be used! */
2826 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2829 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2832 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2833 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2838 case WINED3DRS_SPECULARENABLE :
2840 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2841 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2842 specular color. This is wrong:
2843 Separate specular color means the specular colour is maintained separately, whereas
2844 single color means it is merged in. However in both cases they are being used to
2846 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2847 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2851 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2852 checkGLcall("glMaterialfv");
2853 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2854 glEnable(GL_COLOR_SUM_EXT);
2856 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2858 checkGLcall("glEnable(GL_COLOR_SUM)");
2860 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2862 /* for the case of enabled lighting: */
2863 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2864 checkGLcall("glMaterialfv");
2866 /* for the case of disabled lighting: */
2867 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2868 glDisable(GL_COLOR_SUM_EXT);
2870 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2872 checkGLcall("glDisable(GL_COLOR_SUM)");
2877 case WINED3DRS_STENCILENABLE :
2879 glEnable(GL_STENCIL_TEST);
2880 checkGLcall("glEnable GL_STENCIL_TEST");
2882 glDisable(GL_STENCIL_TEST);
2883 checkGLcall("glDisable GL_STENCIL_TEST");
2887 case WINED3DRS_STENCILFUNC :
2889 int glParm = GL_ALWAYS;
2890 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2891 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2893 switch ((D3DCMPFUNC) Value) {
2894 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2895 case D3DCMP_LESS: glParm=GL_LESS; break;
2896 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2897 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2898 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2899 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2900 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2901 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2903 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2905 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2906 This->stencilfunc = glParm;
2907 glStencilFunc(glParm, ref, mask);
2908 checkGLcall("glStencilFunc");
2912 case WINED3DRS_STENCILREF :
2914 int glParm = This->stencilfunc;
2916 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2919 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2920 glStencilFunc(glParm, ref, mask);
2921 checkGLcall("glStencilFunc");
2925 case WINED3DRS_STENCILMASK :
2927 int glParm = This->stencilfunc;
2928 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2929 GLuint mask = Value;
2931 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2932 glStencilFunc(glParm, ref, mask);
2933 checkGLcall("glStencilFunc");
2937 case WINED3DRS_STENCILFAIL :
2943 fail = StencilOp(Value);
2944 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2945 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2946 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2947 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2949 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2950 glStencilOp(fail, zfail, zpass);
2951 checkGLcall("glStencilOp(fail, zfail, zpass);");
2954 case WINED3DRS_STENCILZFAIL :
2960 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2961 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2962 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2963 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2964 zfail = StencilOp(Value);
2966 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2967 glStencilOp(fail, zfail, zpass);
2968 checkGLcall("glStencilOp(fail, zfail, zpass);");
2971 case WINED3DRS_STENCILPASS :
2977 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2978 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2979 zpass = StencilOp(Value);
2980 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2981 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2983 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2984 glStencilOp(fail, zfail, zpass);
2985 checkGLcall("glStencilOp(fail, zfail, zpass);");
2989 case WINED3DRS_STENCILWRITEMASK :
2991 glStencilMask(Value);
2992 TRACE("glStencilMask(%lu)\n", Value);
2993 checkGLcall("glStencilMask");
2997 case WINED3DRS_FOGENABLE :
2999 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
3001 checkGLcall("glEnable GL_FOG");
3004 checkGLcall("glDisable GL_FOG");
3009 case WINED3DRS_RANGEFOGENABLE :
3012 TRACE("Enabled RANGEFOG");
3014 TRACE("Disabled RANGEFOG");
3019 case WINED3DRS_FOGCOLOR :
3022 D3DCOLORTOGLFLOAT4(Value, col);
3023 /* Set the default alpha blend color */
3024 glFogfv(GL_FOG_COLOR, &col[0]);
3025 checkGLcall("glFog GL_FOG_COLOR");
3029 case WINED3DRS_FOGTABLEMODE :
3031 glHint(GL_FOG_HINT, GL_NICEST);
3033 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3034 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3035 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3036 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3038 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3040 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3041 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3046 case WINED3DRS_FOGVERTEXMODE :
3048 glHint(GL_FOG_HINT, GL_FASTEST);
3050 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3051 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3052 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3053 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3055 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3057 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3058 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
3063 case WINED3DRS_FOGSTART :
3066 glFogfv(GL_FOG_START, &tmpvalue.f);
3067 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3068 TRACE("Fog Start == %f\n", tmpvalue.f);
3072 case WINED3DRS_FOGEND :
3075 glFogfv(GL_FOG_END, &tmpvalue.f);
3076 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3077 TRACE("Fog End == %f\n", tmpvalue.f);
3081 case WINED3DRS_FOGDENSITY :
3084 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3085 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3089 case WINED3DRS_VERTEXBLEND :
3091 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3092 TRACE("Vertex Blending state to %ld\n", Value);
3096 case WINED3DRS_TWEENFACTOR :
3099 This->updateStateBlock->tween_factor = tmpvalue.f;
3100 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3104 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
3106 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3110 case WINED3DRS_COLORVERTEX :
3111 case WINED3DRS_DIFFUSEMATERIALSOURCE :
3112 case WINED3DRS_SPECULARMATERIALSOURCE :
3113 case WINED3DRS_AMBIENTMATERIALSOURCE :
3114 case WINED3DRS_EMISSIVEMATERIALSOURCE :
3116 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3118 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3119 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3120 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3121 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3122 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3123 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3125 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3126 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3127 Parm = GL_AMBIENT_AND_DIFFUSE;
3131 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3133 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3135 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3142 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3144 This->tracking_color = NEEDS_TRACKING;
3145 This->tracking_parm = Parm;
3149 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3154 case WINED3DRS_LINEPATTERN :
3160 tmppattern.d = Value;
3162 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3164 if (tmppattern.lp.wRepeatFactor) {
3165 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3166 checkGLcall("glLineStipple(repeat, linepattern)");
3167 glEnable(GL_LINE_STIPPLE);
3168 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3170 glDisable(GL_LINE_STIPPLE);
3171 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3176 case WINED3DRS_ZBIAS : /* D3D8 only */
3180 TRACE("ZBias value %f\n", tmpvalue.f);
3181 glPolygonOffset(0, -tmpvalue.f);
3182 checkGLcall("glPolygonOffset(0, -Value)");
3183 glEnable(GL_POLYGON_OFFSET_FILL);
3184 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3185 glEnable(GL_POLYGON_OFFSET_LINE);
3186 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3187 glEnable(GL_POLYGON_OFFSET_POINT);
3188 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3190 glDisable(GL_POLYGON_OFFSET_FILL);
3191 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3192 glDisable(GL_POLYGON_OFFSET_LINE);
3193 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3194 glDisable(GL_POLYGON_OFFSET_POINT);
3195 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3200 case WINED3DRS_NORMALIZENORMALS :
3202 glEnable(GL_NORMALIZE);
3203 checkGLcall("glEnable(GL_NORMALIZE);");
3205 glDisable(GL_NORMALIZE);
3206 checkGLcall("glDisable(GL_NORMALIZE);");
3210 case WINED3DRS_POINTSIZE :
3212 TRACE("Set point size to %f\n", tmpvalue.f);
3213 glPointSize(tmpvalue.f);
3214 checkGLcall("glPointSize(...);");
3217 case WINED3DRS_POINTSIZE_MIN :
3218 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3220 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3221 checkGLcall("glPointParameterfEXT(...);");
3223 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3227 case WINED3DRS_POINTSIZE_MAX :
3228 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3230 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3231 checkGLcall("glPointParameterfEXT(...);");
3233 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3237 case WINED3DRS_POINTSCALE_A :
3238 case WINED3DRS_POINTSCALE_B :
3239 case WINED3DRS_POINTSCALE_C :
3240 case WINED3DRS_POINTSCALEENABLE :
3242 /* If enabled, supply the parameters, otherwise fall back to defaults */
3243 if (This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3244 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3245 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]);
3246 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]);
3247 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]);
3249 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3250 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3251 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3253 TRACE("WINED3DRS_POINTSCALEENABLE not supported on this opengl\n");
3256 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3257 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3258 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3259 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3261 TRACE("WINED3DRS_POINTSCALEENABLE not supported, but not on either\n");
3267 case WINED3DRS_COLORWRITEENABLE :
3269 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3270 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3271 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3272 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3273 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3274 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3275 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3276 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3277 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3278 checkGLcall("glColorMask(...)");
3282 case WINED3DRS_LOCALVIEWER :
3284 GLint state = (Value) ? 1 : 0;
3285 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3286 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3290 case WINED3DRS_LASTPIXEL :
3293 TRACE("Last Pixel Drawing Enabled\n");
3295 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3300 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3303 TRACE("Software Processing Enabled\n");
3305 TRACE("Software Processing Disabled\n");
3310 /** not supported */
3311 case WINED3DRS_ZVISIBLE :
3314 return D3DERR_INVALIDCALL;
3317 /* Unhandled yet...! */
3318 case WINED3DRS_EDGEANTIALIAS :
3319 case WINED3DRS_WRAP0 :
3320 case WINED3DRS_WRAP1 :
3321 case WINED3DRS_WRAP2 :
3322 case WINED3DRS_WRAP3 :
3323 case WINED3DRS_WRAP4 :
3324 case WINED3DRS_WRAP5 :
3325 case WINED3DRS_WRAP6 :
3326 case WINED3DRS_WRAP7 :
3328 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
3329 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
3330 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
3331 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
3332 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
3334 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
3336 TRACE("(%p)->(%d,%ld) Texture wraping not yet supported\n",This, State, Value);
3338 case WINED3DRS_POINTSPRITEENABLE :
3339 case WINED3DRS_MULTISAMPLEANTIALIAS :
3340 case WINED3DRS_MULTISAMPLEMASK :
3341 case WINED3DRS_PATCHEDGESTYLE :
3342 case WINED3DRS_PATCHSEGMENTS :
3343 case WINED3DRS_DEBUGMONITORTOKEN :
3344 case WINED3DRS_POSITIONORDER :
3345 case WINED3DRS_NORMALORDER :
3346 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3347 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3350 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3358 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3359 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3360 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3361 *pValue = This->stateBlock->renderState[State];
3366 * Get / Set Sampler States
3367 * TODO: Verify against dx9 definitions
3370 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3371 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3373 * SetSampler is designed to allow for more than the standard up to 8 textures
3374 * and Geforce has stopped supporting more than 6 standard textures in openGL.
3375 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3377 * http://developer.nvidia.com/object/General_FAQ.html#t6
3379 * There are two new settings for GForce
3381 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3382 * and the texture one:
3383 * GL_MAX_TEXTURE_COORDS_ARB.
3384 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3386 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
3387 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
3389 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
3390 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE, Sampler, Type);
3391 return D3DERR_INVALIDCALL;
3393 TRACE("Setting sampler %ld %d to %ld \n", Sampler, Type, Value);
3394 This->updateStateBlock->samplerState[Sampler][Type] = Value;
3395 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
3396 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
3398 /* Handle recording of state blocks */
3399 if (This->isRecordingState) {
3400 TRACE("Recording... not performing anything\n");
3407 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3408 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3409 /** TODO: check that sampler is in range **/
3410 *Value = This->updateStateBlock->samplerState[Sampler][Type];
3411 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
3416 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3417 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3420 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3421 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3422 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3428 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3429 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3430 GLint scissorBox[4];
3433 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3434 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
3435 pRect->left = scissorBox[1];
3436 pRect->top = scissorBox[2];
3437 pRect->right = scissorBox[1] + scissorBox[3];
3438 pRect->bottom = scissorBox[2] + scissorBox[4];
3439 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3444 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3445 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3447 TRACE("(%p) : pDecl=%p\n", This, pDecl);
3449 /* TODO: what about recording stateblocks? */
3450 if (NULL != pDecl) {
3451 IWineD3DVertexDeclaration_AddRef(pDecl);
3453 if (NULL != This->updateStateBlock->vertexDecl) {
3454 IWineD3DVertexDeclaration_Release(This->updateStateBlock->vertexDecl);
3456 This->updateStateBlock->vertexDecl = pDecl;
3457 This->updateStateBlock->changed.vertexDecl = TRUE;
3458 This->updateStateBlock->set.vertexDecl = TRUE;
3462 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3463 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3465 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3467 *ppDecl = This->updateStateBlock->vertexDecl;
3468 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3472 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
3473 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3474 IWineD3DVertexShader *oldShader = This->updateStateBlock->vertexShader;
3476 This->updateStateBlock->vertexShader = pShader;
3477 This->updateStateBlock->changed.vertexShader = TRUE;
3478 This->updateStateBlock->set.vertexShader = TRUE;
3480 if (This->isRecordingState) {
3481 TRACE("Recording... not performing anything\n");
3485 if (pShader != NULL) {
3486 IUnknown *newVertexShaderParent;
3487 /* GetParent will add a ref, so leave it hanging until the vertex buffer is cleared */
3488 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3489 IWineD3DVertexShader_GetParent(pShader, &newVertexShaderParent);
3491 TRACE("Clear down the shader\n");
3493 if (oldShader != NULL) {
3494 IUnknown *oldVertexShaderParent;
3495 IWineD3DVertexShader_GetParent(oldShader, &oldVertexShaderParent);
3496 IUnknown_Release(oldVertexShaderParent);
3497 IUnknown_Release(oldVertexShaderParent);
3500 * TODO: merge HAL shaders context switching from prototype
3505 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
3506 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3508 if (NULL == ppShader) {
3509 return D3DERR_INVALIDCALL;
3511 *ppShader = This->stateBlock->vertexShader;
3512 if( NULL != *ppShader)
3513 IWineD3DVertexShader_AddRef(*ppShader);
3515 TRACE("(%p) : returning %p\n", This, *ppShader);
3519 #define GET_SHADER_CONSTANT(_vertexshaderconstant, _count, _sizecount) \
3520 int count = min(_count, MAX_VSHADER_CONSTANTS - (StartRegister + 1)); \
3521 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3522 return D3DERR_INVALIDCALL; \
3523 memcpy(pConstantData, This->updateStateBlock->_vertexshaderconstant + (StartRegister * _sizecount), count * (sizeof(*pConstantData) * _sizecount));
3525 #define SET_SHADER_CONSTANT(_vertexshaderconstant, _count, _sizecount) \
3526 int count = min(_count, MAX_VSHADER_CONSTANTS - (StartRegister + 1)); \
3527 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3528 return D3DERR_INVALIDCALL; \
3529 memcpy(This->updateStateBlock->_vertexshaderconstant + (StartRegister * _sizecount), pConstantData, count * (sizeof(*pConstantData) * _sizecount)); \
3530 This->updateStateBlock->changed.vertexShader = TRUE; \
3531 This->updateStateBlock->set.vertexShader = TRUE;
3533 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
3534 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3535 static BOOL showFixmes = TRUE;
3536 SET_SHADER_CONSTANT(vertexShaderConstantB, BoolCount, 1);
3537 #if 0 /* TODO: a bitmasp to say which constant type we should load */
3538 memset(This->updateStateBlock->vsibfBitmap + StartRegister, WINESHADER_CONSTANTB, BoolCount);
3540 /* clean out the other constants? */
3541 if(showFixmes || TRUE) {
3542 FIXME("(%p) : stub\n", This);
3548 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
3549 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3550 static BOOL showFixmes = TRUE;
3551 #if 0 /* TODO: a bitmasp to say which constant type we should load */
3552 for (i = 0; i < BoolCount; i++ ) {
3553 if (This->updateStateBlock->vsibfBitmap[StartRegister + i] != WINESHADER_CONSTANTB) {
3554 /* the constant for this register isn't a boolean */
3555 return D3DERR_INVALIDCALL;
3559 GET_SHADER_CONSTANT(vertexShaderConstantB, BoolCount, 1);
3560 if(showFixmes || TRUE) {
3561 FIXME("(%p) : stub\n", This);
3567 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
3568 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3569 static BOOL showFixmes = TRUE;
3570 #if 0 /* TODO: a bitmasp to say which constant type we should load */
3571 memset(This->updateStateBlock->vsibfBitmap + StartRegister, WINESHADER_CONSTANTI, Vector4iCount);
3573 SET_SHADER_CONSTANT(vertexShaderConstantI, Vector4iCount, 4);
3574 /* clean out the other constants? */
3575 if(showFixmes || TRUE) {
3576 FIXME("(%p) : stub\n", This);
3582 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
3583 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3584 static BOOL showFixmes = TRUE;
3585 #if 0 /* TODO: a bitmap to say which constant type we should load */
3586 for (i = 0; i < Vector4iCount; i++ ) {
3587 if (This->updateStateBlock->vsibfBitmap[StartRegister + i] != WINESHADER_CONSTANTI) {
3588 /* the constant for this register isn't a boolean */
3589 return D3DERR_INVALIDCALL;
3593 GET_SHADER_CONSTANT(vertexShaderConstantI, Vector4iCount, 4);
3594 if(showFixmes || TRUE) {
3595 FIXME("(%p) : stub\n", This);
3601 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
3602 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3603 static BOOL showFixmes = TRUE;
3604 #if 0 /* TODO: a bitmasp to say which constant type we should load */
3605 memset(This->updateStateBlock->vsibfBitmap + StartRegister, WINESHADER_CONSTANTF, Vector4fCount);
3607 SET_SHADER_CONSTANT(vertexShaderConstantF, Vector4fCount, 4);
3608 /* clean out the other constants? */
3610 TRACE("(%p) : ConstantF isn't intergrated properly with the other constants.\n", This);
3616 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
3617 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3618 static BOOL showFixmes = TRUE;
3619 #if 0 /* TODO: a bitmap to say which constant type we should load */
3620 for (i = 0; i < Vector4fCount; i++ ) {
3621 if (This->updateStateBlock->vsibfBitmap[StartRegister + i] != WINESHADER_CONSTANTF) {
3622 /* the constant for this register isn't a boolean */
3623 return D3DERR_INVALIDCALL;
3627 GET_SHADER_CONSTANT(vertexShaderConstantF, Vector4fCount, 4);
3629 TRACE("(%p) : ConstantF isn't intergrated properly with the other constants.\n", This);
3635 #undef SET_SHADER_CONSTANT
3636 #undef GET_SHADER_CONSTANT
3639 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
3641 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3642 IWineD3DPixelShader *oldpShader = This->updateStateBlock->pixelShader;
3643 static BOOL showFixmes = TRUE;
3645 /** FIXME: reference counting? **/
3646 This->updateStateBlock->pixelShader = pShader;
3647 This->updateStateBlock->changed.pixelShader = TRUE;
3648 This->updateStateBlock->set.pixelShader = TRUE;
3650 if (pShader == NULL) {
3651 /* clear down the shader */
3652 TRACE("Clear down the shader\n");
3655 FIXME("(%p) : stub pShader(%p)\n", This, pShader);
3660 /* Handle recording of state blocks */
3661 if (This->isRecordingState) {
3662 TRACE("Recording... not performing anything\n");
3666 * TODO: merge HAL shaders context switching from prototype
3669 /* manage reference counting. */
3670 if (pShader != NULL) {
3671 IWineD3DPixelShader_GetParent(pShader, &parent); /* get parent adds a ref for us*/
3674 if (oldpShader != NULL) {
3675 IWineD3DPixelShader_GetParent(oldpShader, &parent);
3676 IUnknown_Release(parent); /* once for the getparent */
3677 IUnknown_Release(parent); /* and once for the ref */
3685 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3686 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3688 if (ppShader == NULL) {
3689 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
3690 return D3DERR_INVALIDCALL;
3693 *ppShader = This->updateStateBlock->pixelShader;
3694 if (NULL != ppShader) {
3695 IWineD3DPixelShader_AddRef(*ppShader);
3697 TRACE("(%p) : returning %p\n", This, *ppShader);
3701 #define GET_SHADER_CONSTANT(_pixelshaderconstant, _count, _sizecount) \
3702 int count = min(_count, MAX_PSHADER_CONSTANTS - (StartRegister + 1)); \
3703 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3704 return D3DERR_INVALIDCALL; \
3705 memcpy(pConstantData, This->updateStateBlock->_pixelshaderconstant + (StartRegister * _sizecount), count * (sizeof(*pConstantData) * _sizecount)); \
3708 #define SET_SHADER_CONSTANT(_pixelshaderconstant, _count, _sizecount) \
3709 int count = min(_count, MAX_PSHADER_CONSTANTS - (StartRegister + 1)); \
3710 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3711 return D3DERR_INVALIDCALL; \
3712 memcpy(This->updateStateBlock->_pixelshaderconstant + (StartRegister * _sizecount), pConstantData, count * (sizeof(*pConstantData) * _sizecount)); \
3713 This->updateStateBlock->changed.pixelShader = TRUE; \
3714 This->updateStateBlock->set.pixelShader = TRUE;
3717 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
3718 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3719 static BOOL showFixmes = TRUE;
3720 SET_SHADER_CONSTANT(pixelShaderConstantB, BoolCount, 1);
3722 FIXME("(%p) : stub\n", This);
3729 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
3730 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3731 static BOOL showFixmes = TRUE;
3732 GET_SHADER_CONSTANT(pixelShaderConstantB, BoolCount, 1);
3734 FIXME("(%p) : stub\n", This);
3740 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
3741 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3742 static BOOL showFixmes = TRUE;
3743 SET_SHADER_CONSTANT(pixelShaderConstantI, Vector4iCount, 4);
3745 FIXME("(%p) : stub\n", This);
3751 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
3752 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3753 static BOOL showFixmes = TRUE;
3754 GET_SHADER_CONSTANT(pixelShaderConstantI, Vector4iCount, 4);
3756 FIXME("(%p) : stub\n", This);
3762 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
3763 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3764 static BOOL showFixmes = TRUE;
3765 SET_SHADER_CONSTANT(pixelShaderConstantF, Vector4fCount, 4);
3767 FIXME("(%p) : stub\n", This);
3773 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
3774 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3775 static BOOL showFixmes = TRUE;
3776 GET_SHADER_CONSTANT(pixelShaderConstantF, Vector4fCount, 4);
3778 FIXME("(%p) : stub\n", This);
3784 #undef SET_SHADER_CONSTANT
3785 #undef GET_SHADER_CONSTANT
3787 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
3788 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3789 FIXME("(%p) : stub\n", This);
3794 * Apply / Get / Set Texture Stage States
3795 * TODO: Verify against dx9 definitions
3798 /* 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 */
3799 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
3800 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3801 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
3802 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3804 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3806 /* Check that the stage is within limits */
3807 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
3808 TRACE("Attempt to access invalid texture rejected\n");
3815 case WINED3DTSS_ALPHAOP :
3816 case WINED3DTSS_COLOROP :
3817 /* nothing to do as moved to drawprim for now */
3819 case WINED3DTSS_ADDRESSW :
3820 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
3821 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
3822 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3825 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
3826 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
3827 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3828 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3831 case WINED3DTSS_TEXCOORDINDEX :
3833 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3835 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
3836 one flag, you can still specify an index value, which the system uses to
3837 determine the texture wrapping mode.
3838 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3839 means use the vertex position (camera-space) as the input texture coordinates
3840 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
3841 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3842 to the TEXCOORDINDEX value */
3845 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3847 switch (Value & 0xFFFF0000) {
3848 case D3DTSS_TCI_PASSTHRU:
3849 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3850 glDisable(GL_TEXTURE_GEN_S);
3851 glDisable(GL_TEXTURE_GEN_T);
3852 glDisable(GL_TEXTURE_GEN_R);
3853 glDisable(GL_TEXTURE_GEN_Q);
3854 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
3857 case D3DTSS_TCI_CAMERASPACEPOSITION:
3858 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3859 as the input texture coordinates for this stage's texture transformation. This
3860 equates roughly to EYE_LINEAR */
3862 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3863 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3864 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3865 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3866 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3868 glMatrixMode(GL_MODELVIEW);
3871 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3872 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3873 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3874 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3877 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3878 glEnable(GL_TEXTURE_GEN_S);
3879 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3880 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3881 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3882 glEnable(GL_TEXTURE_GEN_T);
3883 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3884 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3885 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3886 glEnable(GL_TEXTURE_GEN_R);
3887 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3888 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3889 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3893 case D3DTSS_TCI_CAMERASPACENORMAL:
3895 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3896 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3897 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3898 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3899 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3900 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
3902 glMatrixMode(GL_MODELVIEW);
3905 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3906 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3907 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3908 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3911 glEnable(GL_TEXTURE_GEN_S);
3912 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3913 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3914 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3915 glEnable(GL_TEXTURE_GEN_T);
3916 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3917 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3918 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3919 glEnable(GL_TEXTURE_GEN_R);
3920 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3921 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3922 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3927 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3929 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3930 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3931 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3932 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3933 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3934 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
3936 glMatrixMode(GL_MODELVIEW);
3939 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3940 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3941 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3942 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3945 glEnable(GL_TEXTURE_GEN_S);
3946 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3947 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3948 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3949 glEnable(GL_TEXTURE_GEN_T);
3950 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3951 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3952 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3953 glEnable(GL_TEXTURE_GEN_R);
3954 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3955 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3956 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3961 /* Unhandled types: */
3964 /* ? disable GL_TEXTURE_GEN_n ? */
3965 glDisable(GL_TEXTURE_GEN_S);
3966 glDisable(GL_TEXTURE_GEN_T);
3967 glDisable(GL_TEXTURE_GEN_R);
3968 glDisable(GL_TEXTURE_GEN_Q);
3969 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
3976 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
3977 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);
3980 case WINED3DTSS_BUMPENVMAT00 :
3981 case WINED3DTSS_BUMPENVMAT01 :
3982 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
3984 case WINED3DTSS_BUMPENVMAT10 :
3985 case WINED3DTSS_BUMPENVMAT11 :
3986 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
3989 case WINED3DTSS_BUMPENVLSCALE :
3990 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3993 case WINED3DTSS_BUMPENVLOFFSET :
3994 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3997 case WINED3DTSS_RESULTARG :
3998 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4002 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
4003 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4012 * Get / Set Texture Stage States
4013 * TODO: Verify against dx9 definitions
4015 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
4016 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4018 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4020 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4022 /* Reject invalid texture units */
4023 if (Stage >= GL_LIMITS(textures)) {
4024 TRACE("Attempt to access invalid texture rejected\n");
4025 return D3DERR_INVALIDCALL;
4028 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
4029 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
4030 This->updateStateBlock->textureState[Stage][Type] = Value;
4035 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4036 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4037 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4038 *pValue = This->updateStateBlock->textureState[Stage][Type];
4045 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4047 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4048 IWineD3DBaseTexture *oldTexture;
4050 oldTexture = This->updateStateBlock->textures[Stage];
4051 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
4053 #if 0 /* TODO: check so vertex textures */
4054 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
4055 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
4060 /* Reject invalid texture units */
4061 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4062 WARN("Attempt to access invalid texture rejected\n");
4063 return D3DERR_INVALIDCALL;
4066 oldTexture = This->updateStateBlock->textures[Stage];
4067 TRACE("GL_LIMITS %d\n",GL_LIMITS(textures));
4068 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
4070 This->updateStateBlock->set.textures[Stage] = TRUE;
4071 This->updateStateBlock->changed.textures[Stage] = TRUE;
4072 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
4073 This->updateStateBlock->textures[Stage] = pTexture;
4075 /* Handle recording of state blocks */
4076 if (This->isRecordingState) {
4077 TRACE("Recording... not performing anything\n");
4081 /** NOTE: MSDN says that setTexture increases the reference count,
4082 * and the the application nust set the texture back to null (or have a leaky application),
4083 * This means we should pass the refcount upto the parent
4084 *******************************/
4085 if (NULL != This->updateStateBlock->textures[Stage]) {
4086 IUnknown *textureParent;
4087 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[Stage], (IUnknown **)&textureParent);
4088 /** NOTE: GetParent will increase the ref count for me, I won't clean up until the texture is set to NULL **/
4091 if (NULL != oldTexture) {
4092 IUnknown *textureParent;
4093 IWineD3DBaseTexture_GetParent(oldTexture, (IUnknown **)&textureParent);
4094 IUnknown_Release(textureParent);
4095 IUnknown_Release(textureParent); /** NOTE: Twice because GetParent adds a ref **/
4102 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4103 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4104 TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */) \n", This, Stage, ppTexture);
4106 /* Reject invalid texture units */
4107 if (Stage >= GL_LIMITS(textures)) {
4108 TRACE("Attempt to access invalid texture rejected\n");
4109 return D3DERR_INVALIDCALL;
4111 *ppTexture=This->updateStateBlock->textures[Stage];
4113 IWineD3DBaseTexture_AddRef(*ppTexture);
4115 return D3DERR_INVALIDCALL;
4122 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type,
4123 IWineD3DSurface **ppBackBuffer) {
4124 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4125 IWineD3DSwapChain *swapChain;
4128 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4130 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4132 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4133 IWineD3DSwapChain_Release(swapChain);
4135 *ppBackBuffer = NULL;
4140 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4141 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4142 WARN("(%p) : stub, calling idirect3d for now\n", This);
4143 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4146 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
4147 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4148 IWineD3DSwapChain *swapChain;
4151 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4153 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4154 IWineD3DSwapChain_Release(swapChain);
4156 FIXME("(%p) Error getting display mode\n", This);
4161 * Stateblock related functions
4164 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4165 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4166 IWineD3DStateBlockImpl *object;
4167 TRACE("(%p)", This);
4168 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4169 if (NULL == object ) {
4170 FIXME("(%p)Error allocating memory for stateblock\n", This);
4171 return E_OUTOFMEMORY;
4173 TRACE("(%p) creted object %p\n", This, object);
4174 object->wineD3DDevice= This;
4175 /** FIXME: object->parent = parent; **/
4176 object->parent = NULL;
4177 object->blockType = WINED3DSBT_ALL;
4179 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
4181 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4182 This->updateStateBlock = object;
4183 This->isRecordingState = TRUE;
4185 TRACE("(%p) recording stateblock %p\n",This , object);
4189 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4190 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4192 if (!This->isRecordingState) {
4193 FIXME("(%p) not recording! returning error\n", This);
4194 *ppStateBlock = NULL;
4195 return D3DERR_INVALIDCALL;
4198 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4199 This->isRecordingState = FALSE;
4200 This->updateStateBlock = This->stateBlock;
4201 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4202 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4203 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4208 * Scene related functions
4210 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4211 /* At the moment we have no need for any functionality at the beginning
4213 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4214 TRACE("(%p) : stub\n", This);
4218 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4219 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4220 TRACE("(%p)\n", This);
4222 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4224 checkGLcall("glFlush");
4226 TRACE("End Scene\n");
4227 if(This->renderTarget != NULL) {
4229 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4230 IUnknown *targetContainer = NULL;
4231 if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
4232 || D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
4233 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
4234 /** always dirtify for now. we must find a better way to see that surface have been modified
4235 (Modifications should will only occur via draw-primitive, but we do need better locking
4236 switching to render-to-texture should remove the overhead though.
4238 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4239 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
4240 IWineD3DSurface_PreLoad(This->renderTarget);
4241 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4242 IUnknown_Release(targetContainer);
4245 This->sceneEnded = TRUE;
4250 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4251 CONST RECT* pSourceRect, CONST RECT* pDestRect,
4252 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4253 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4254 IWineD3DSwapChain *swapChain = NULL;
4256 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4258 TRACE("(%p) Presenting the frame\n", This);
4260 for(i = 0 ; i < swapchains ; i ++) {
4262 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4263 TRACE("presentinng chain %d, %p\n", i, swapChain);
4264 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4265 IWineD3DSwapChain_Release(swapChain);
4271 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4272 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4273 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4275 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4276 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4277 when the depth-buffer format does not contain stencil buffer information, this method fails. */
4278 GLbitfield glMask = 0;
4279 GLboolean old_ztest;
4280 GLfloat old_z_clear_value;
4281 GLint old_stencil_clear_value;
4282 GLfloat old_color_clear_value[4];
4284 CONST D3DRECT* curRect;
4286 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4287 Count, pRects, Flags, Z, Stencil);
4291 glEnable(GL_SCISSOR_TEST);
4292 checkGLcall("glEnable GL_SCISSOR_TEST");
4294 if (Count > 0 && pRects) {
4300 /* Only set the values up once, as they are not changing */
4301 if (Flags & D3DCLEAR_STENCIL) {
4302 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4303 glClearStencil(Stencil);
4304 checkGLcall("glClearStencil");
4305 glMask = glMask | GL_STENCIL_BUFFER_BIT;
4306 glStencilMask(0xFFFFFFFF);
4309 if (Flags & D3DCLEAR_ZBUFFER) {
4310 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4311 glDepthMask(GL_TRUE);
4312 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4314 checkGLcall("glClearDepth");
4315 glMask = glMask | GL_DEPTH_BUFFER_BIT;
4318 if (Flags & D3DCLEAR_TARGET) {
4319 TRACE("Clearing screen with glClear to color %lx\n", Color);
4320 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4321 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
4322 ((Color >> 8) & 0xFF) / 255.0f,
4323 ((Color >> 0) & 0xFF) / 255.0f,
4324 ((Color >> 24) & 0xFF) / 255.0f);
4325 checkGLcall("glClearColor");
4327 /* Clear ALL colors! */
4328 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4329 glMask = glMask | GL_COLOR_BUFFER_BIT;
4332 /* Now process each rect in turn */
4333 for (i = 0; i < Count || i == 0; i++) {
4336 /* Note gl uses lower left, width/height */
4337 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4338 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4339 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4340 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4341 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4342 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4343 checkGLcall("glScissor");
4345 glScissor(This->stateBlock->viewport.X,
4346 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
4347 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4348 This->stateBlock->viewport.Width,
4349 This->stateBlock->viewport.Height);
4350 checkGLcall("glScissor");
4353 /* Clear the selected rectangle (or full screen) */
4355 checkGLcall("glClear");
4357 /* Step to the next rectangle */
4358 if (curRect) curRect = curRect + sizeof(D3DRECT);
4361 /* Restore the old values (why..?) */
4362 if (Flags & D3DCLEAR_STENCIL) {
4363 glClearStencil(old_stencil_clear_value);
4364 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4366 if (Flags & D3DCLEAR_ZBUFFER) {
4367 glDepthMask(old_ztest);
4368 glClearDepth(old_z_clear_value);
4370 if (Flags & D3DCLEAR_TARGET) {
4371 glClearColor(old_color_clear_value[0],
4372 old_color_clear_value[1],
4373 old_color_clear_value[2],
4374 old_color_clear_value[3]);
4375 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4376 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4377 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4378 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4381 glDisable(GL_SCISSOR_TEST);
4382 checkGLcall("glDisable");
4391 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4392 UINT PrimitiveCount) {
4394 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4395 This->stateBlock->streamIsUP = FALSE;
4397 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4398 debug_d3dprimitivetype(PrimitiveType),
4399 StartVertex, PrimitiveCount);
4400 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
4401 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
4407 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4408 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4409 D3DPRIMITIVETYPE PrimitiveType,
4410 INT baseVIndex, UINT minIndex,
4411 UINT NumVertices, UINT startIndex, UINT primCount) {
4413 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4415 IWineD3DIndexBuffer *pIB;
4416 D3DINDEXBUFFER_DESC IdxBufDsc;
4418 pIB = This->stateBlock->pIndexData;
4419 This->stateBlock->streamIsUP = FALSE;
4421 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d \n", This,
4422 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4423 minIndex, NumVertices, startIndex, baseVIndex, primCount);
4425 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4426 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4432 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
4433 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
4438 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4439 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4440 UINT VertexStreamZeroStride) {
4441 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4443 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4444 debug_d3dprimitivetype(PrimitiveType),
4445 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4447 if (This->stateBlock->streamSource[0] != NULL) {
4448 IUnknown *vertexBufferParent;
4449 IWineD3DVertexBuffer_GetParent(This->stateBlock->streamSource[0], &vertexBufferParent);
4450 IUnknown_Release(vertexBufferParent);
4451 IUnknown_Release(vertexBufferParent);
4454 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4455 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4456 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4457 This->stateBlock->streamIsUP = TRUE;
4459 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
4460 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
4461 /* stream zero settings set to null at end, as per the msdn
4462 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
4464 This->stateBlock->streamStride[0] = 0;
4465 This->stateBlock->streamSource[0] = NULL;
4467 /*stream zero settings set to null at end, as per the msdn */
4471 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4472 UINT MinVertexIndex, UINT NumVertices,
4473 UINT PrimitiveCount, CONST void* pIndexData,
4474 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4475 UINT VertexStreamZeroStride) {
4477 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4479 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4480 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4481 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
4482 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4484 if (IndexDataFormat == WINED3DFMT_INDEX16) {
4490 if (This->stateBlock->streamSource[0] != NULL) {
4491 IUnknown *vertexBufferParent;
4492 IWineD3DVertexBuffer_GetParent(This->stateBlock->streamSource[0], &vertexBufferParent);
4493 This->stateBlock->streamSource[0] = NULL;
4494 IUnknown_Release(vertexBufferParent);
4495 IUnknown_Release(vertexBufferParent);
4498 if (This->stateBlock->pIndexData) {
4499 IUnknown *indexBufferParent;
4500 IWineD3DIndexBuffer_GetParent(This->stateBlock->pIndexData, &indexBufferParent);
4501 This->stateBlock->pIndexData = NULL;
4502 IUnknown_Release(indexBufferParent);
4503 IUnknown_Release(indexBufferParent);
4506 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4507 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4508 This->stateBlock->streamIsUP = TRUE;
4509 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4511 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
4512 /* stream zero settings set to null at end as per the msdn
4513 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
4516 /* stream zero settings set to null at end as per the msdn */
4517 This->stateBlock->streamSource[0] = NULL;
4518 This->stateBlock->streamStride[0] = 0;
4523 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4524 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
4525 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4526 D3DRESOURCETYPE sourceType;
4527 D3DRESOURCETYPE destinationType;
4528 IWineD3DTextureImpl *pDestTexture = (IWineD3DTextureImpl *)pDestinationTexture;
4529 IWineD3DTextureImpl *pSrcTexture = (IWineD3DTextureImpl *)pSourceTexture;
4532 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
4533 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
4534 if(sourceType != D3DRTYPE_TEXTURE && destinationType != D3DRTYPE_TEXTURE){
4535 FIXME("(%p) Only D3DRTYPE_TEXTURE to D3DRTYPE_TEXTURE supported\n", This);
4536 return D3DERR_INVALIDCALL;
4538 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
4540 /** TODO: Get rid of the casts to IWineD3DBaseTextureImpl
4541 repalce surfaces[x] with GetSurfaceLevel, or GetCubeMapSurface etc..
4542 think about moving the code into texture, and adding a member to base texture to occomplish this **/
4544 /* Make sure that the destination texture is loaded */
4545 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
4546 TRACE("Loading source texture\n");
4548 if(pSrcTexture->surfaces[0] == NULL || pDestTexture->surfaces[0] == NULL){
4549 FIXME("(%p) Texture src %p or dest %p has not surface %p %p\n", This, pSrcTexture, pDestTexture,
4550 pSrcTexture->surfaces[0], pDestTexture->surfaces[0]);
4553 if(((IWineD3DSurfaceImpl *)pSrcTexture->surfaces[0])->resource.pool != D3DPOOL_SYSTEMMEM ||
4554 ((IWineD3DSurfaceImpl *)pDestTexture->surfaces[0])->resource.pool != D3DPOOL_DEFAULT){
4556 FIXME("(%p) source %p must be SYSTEMMEM and dest %p must be DEFAULT\n",This, pSrcTexture, pDestTexture);
4557 return D3DERR_INVALIDCALL;
4559 /** TODO: check that both textures have the same number of levels **/
4561 if(IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) !=IWineD3DBaseTexture_GetLevelCount(pSourceTexture))
4562 return D3DERR_INVALIDCALL;
4564 /** TODO: move this code into baseTexture? device should never touch impl*'s **/
4565 for(i = 0 ; i < IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) ; i++){
4566 IWineD3DDevice_UpdateSurface(iface, pSrcTexture->surfaces[i], NULL, pDestTexture->surfaces[i], NULL);
4572 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
4573 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
4574 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
4575 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4577 TRACE("(%p) : stub\n", This);
4580 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
4581 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4583 TRACE("(%p) : stub\n", This);
4587 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
4588 IWineD3DSwapChain *swapChain;
4590 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4592 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
4593 IWineD3DSwapChain_Release(swapChain);
4598 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4599 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4600 /* return a sensible default */
4602 /* TODO: If the window is minimized then validate device shold return something other than d3d_ok */
4603 FIXME("(%p) : stub\n", This);
4607 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4608 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4610 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4611 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4612 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4613 return D3DERR_INVALIDCALL;
4615 for (j = 0; j < 256; ++j) {
4616 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
4617 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
4618 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
4619 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
4621 TRACE("(%p) : returning\n", This);
4625 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4626 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4628 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4629 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4630 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4631 return D3DERR_INVALIDCALL;
4633 for (j = 0; j < 256; ++j) {
4634 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
4635 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
4636 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
4637 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
4639 TRACE("(%p) : returning\n", This);
4643 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4644 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4645 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4646 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4647 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4648 return D3DERR_INVALIDCALL;
4650 /*TODO: stateblocks */
4651 This->currentPalette = PaletteNumber;
4652 TRACE("(%p) : returning\n", This);
4656 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4657 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4658 if (PaletteNumber == NULL) {
4659 WARN("(%p) : returning Invalid Call\n", This);
4660 return D3DERR_INVALIDCALL;
4662 /*TODO: stateblocks */
4663 *PaletteNumber = This->currentPalette;
4664 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
4668 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4669 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4670 static BOOL showFixmes = TRUE;
4672 FIXME("(%p) : stub\n", This);
4676 This->updateStateBlock->softwareVertexProcessing = bSoftware;
4681 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4682 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4683 static BOOL showFixmes = TRUE;
4685 FIXME("(%p) : stub\n", This);
4688 return This->updateStateBlock->softwareVertexProcessing;
4692 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
4693 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4694 IWineD3DSwapChain *swapChain;
4697 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
4699 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4701 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
4702 IWineD3DSwapChain_Release(swapChain);
4704 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error \n", This);
4710 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4711 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4712 static BOOL showfixmes = TRUE;
4713 if(nSegments != 0.0f) {
4715 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4722 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4723 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4724 static BOOL showfixmes = TRUE;
4726 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4733 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4734 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4735 /** TODO: remove casts to IWineD3DSurfaceImpl
4736 * NOTE: move code to surface to accomplish this
4737 ****************************************/
4738 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
4739 int srcWidth, srcHeight;
4740 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
4741 WINED3DFORMAT destFormat, srcFormat;
4743 int destLeft, destTop;
4744 D3DPOOL srcPool, destPool;
4746 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
4747 glDescriptor *glDescription = NULL;
4748 GLenum textureDimensions = GL_TEXTURE_2D;
4749 IWineD3DBaseTexture *baseTexture;
4751 WINED3DSURFACE_DESC winedesc;
4753 memset(&winedesc, 0, sizeof(winedesc));
4754 winedesc.Width = &srcSurfaceWidth;
4755 winedesc.Height = &srcSurfaceHeight;
4756 winedesc.Pool = &srcPool;
4757 winedesc.Format = &srcFormat;
4759 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
4761 winedesc.Width = &destSurfaceWidth;
4762 winedesc.Height = &destSurfaceHeight;
4763 winedesc.Pool = &destPool;
4764 winedesc.Format = &destFormat;
4765 winedesc.Size = &destSize;
4767 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
4769 if(srcPool != D3DPOOL_SYSTEMMEM || destPool != D3DPOOL_DEFAULT){
4770 FIXME("source %p must be SYSTEMMEM and dest %p must be DEFAULT\n", pSourceSurface, pDestinationSurface);
4771 return D3DERR_INVALIDCALL;
4773 /* TODO: change this to use bindTexture */
4774 /* Make sure the surface is loaded and upto date */
4775 IWineD3DSurface_PreLoad(pDestinationSurface);
4777 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
4781 /* this needs to be done in lines if the sourceRect != the sourceWidth */
4782 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
4783 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
4784 destLeft = pDestPoint ? pDestPoint->x : 0;
4785 destTop = pDestPoint ? pDestPoint->y : 0;
4788 /* This function doesn't support compressed textures
4789 the pitch is just bytesPerPixel * width */
4791 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
4792 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
4793 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
4794 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
4796 /* TODO DXT formats */
4798 if(pSourceRect != NULL && pSourceRect->top != 0){
4799 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
4801 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
4803 ,glDescription->level
4808 ,glDescription->glFormat
4809 ,glDescription->glType
4810 ,IWineD3DSurface_GetData(pSourceSurface)
4814 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
4815 /* need to lock the surface to get the data */
4816 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
4818 /* TODO: Cube and volume support */
4820 /* not a whole row so we have to do it a line at a time */
4822 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
4823 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
4825 for(j = destTop ; j < (srcHeight + destTop) ; j++){
4827 glTexSubImage2D(glDescription->target
4828 ,glDescription->level
4833 ,glDescription->glFormat
4834 ,glDescription->glType
4835 ,data/* could be quicker using */
4840 } else { /* Full width, so just write out the whole texture */
4842 if (WINED3DFMT_DXT1 == destFormat ||
4843 WINED3DFMT_DXT3 == destFormat ||
4844 WINED3DFMT_DXT5 == destFormat) {
4845 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
4846 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
4847 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
4848 FIXME("Updating part of a compressed texture is not supported at the moment\n");
4849 } if (destFormat != srcFormat) {
4850 FIXME("Updating mixed format compressed texture is not curretly support\n");
4852 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
4853 glDescription->level,
4854 glDescription->glFormatInternal,
4859 IWineD3DSurface_GetData(pSourceSurface));
4862 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
4867 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
4868 to repack the data from pow2Width/Height to expected Width,Height, this makes the
4869 data returned by GetData non-power2 width/height with hardware non-power2
4870 pow2Width/height are set to surface width height, repacking isn't needed so it
4871 doesn't matter which function gets called. */
4872 glTexSubImage2D(glDescription->target
4873 ,glDescription->level
4878 ,glDescription->glFormat
4879 ,glDescription->glType
4880 ,IWineD3DSurface_GetData(pSourceSurface)
4885 checkGLcall("glTexSubImage2D");
4886 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
4887 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
4888 * surface bigger than it needs to be hmm.. */
4889 if (D3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
4890 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
4891 IWineD3DBaseTexture_Release(baseTexture);
4894 glDisable(textureDimensions); /* This needs to be managed better.... */
4900 /* Implementation details at http://developer.nvidia.com/attach/6494
4902 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
4903 hmm.. no longer supported use
4904 OpenGL evaluators or tessellate surfaces within your application.
4907 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
4908 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4909 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4910 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p) \n", This, Handle, pNumSegs, pRectPatchInfo);
4911 FIXME("(%p) : Stub\n", This);
4916 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
4917 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4918 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4919 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p) \n", This, Handle, pNumSegs, pTriPatchInfo);
4920 FIXME("(%p) : Stub\n", This);
4924 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
4925 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4926 TRACE("(%p) Handle(%d)\n", This, Handle);
4927 FIXME("(%p) : Stub\n", This);
4931 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
4932 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
4933 fill a surface with a block of color! */
4934 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4935 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
4936 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
4937 IWineD3DSwapChainImpl *container = NULL;
4938 BOOL isRenderTarget = FALSE;
4939 unsigned int width, height;
4940 unsigned int top, left;
4943 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
4945 if (surface->resource.pool != D3DPOOL_DEFAULT) {
4946 FIXME("call to colorfill with non D3DPOOL_DEFAULT surface\n");
4947 return D3DERR_INVALIDCALL;
4950 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
4951 if (D3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
4952 if (D3DUSAGE_RENDERTARGET & surface->resource.usage) {
4953 /* TODO: make sure we set everything back to the way it was, and context management!
4954 glGetIntegerv(GL_READ_BUFFER, &prev_read);
4955 vcheckGLcall("glIntegerv");
4956 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
4957 vcheckGLcall("glIntegerv");
4959 TRACE("Color fill to render targets may cause some graphics issues\n");
4960 if (pSurface == container->frontBuffer) {
4961 glDrawBuffer(GL_FRONT);
4963 glDrawBuffer(GL_BACK);
4966 if (D3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
4967 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld \n", surface, surface->resource.usage);
4969 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
4971 if (container != NULL) {
4972 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
4974 /* we can use GL_STENCIL_INDEX etc...*/
4977 if (container != NULL) {
4978 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
4980 isRenderTarget = TRUE;
4982 /* TODO: drawing to GL_FRONT and GL_BACK */
4983 /* TODO: see if things can be speeded up by using the correct
4984 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
4985 if (pRect == NULL) {
4988 width = surface->currentDesc.Width;
4989 height = surface->currentDesc.Height;
4993 width = pRect->x2 - left;
4994 height = pRect->y2 - top;
4997 data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
4998 /* Create a 'line' of color color, in the correct format for the surface */
4999 for (u = 0 ; u < width ; u ++) {
5004 if (isRenderTarget == FALSE) {
5005 glDescriptor *glDesc;
5006 IWineD3DSurface_PreLoad(pSurface);
5008 /* draw a block of the coloured line on the sufrace */
5009 IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
5010 for (v = 0 ; v< height;v++) {
5011 glTexSubImage2D(glDesc->target
5012 ,glDesc->level /* level */
5022 checkGLcall("glTexSubImage2D");
5024 glDisable(glDesc->target);
5026 /** FIXME: Using GLClear may be faster **/
5027 glRasterPos2i(left, top);
5028 glPixelZoom((float)width ,(float)height);
5029 glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
5030 checkGLcall("glDrawPixels");
5032 HeapFree(GetProcessHeap(), 0, data);
5038 /* rendertarget and deptth stencil functions */
5039 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
5040 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5042 /* FIXME: Implelent RenderTargetIndex >0 */
5043 if(RenderTargetIndex > 0)
5044 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
5046 *ppRenderTarget = This->renderTarget;
5047 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
5048 /* Note inc ref on returned surface */
5049 if(*ppRenderTarget != NULL)
5050 IWineD3DSurface_AddRef(*ppRenderTarget);
5054 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5055 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5056 *ppZStencilSurface = This->depthStencilBuffer;
5057 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
5059 if(*ppZStencilSurface != NULL) {
5060 /* Note inc ref on returned surface */
5061 IWineD3DSurface_AddRef(*ppZStencilSurface);
5066 /* internal static helper functions */
5067 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5068 IWineD3DSurface *RenderSurface);
5070 HRESULT WINAPI static IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain);
5072 HRESULT WINAPI static IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context);
5074 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5075 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5076 HRESULT hr = D3D_OK;
5077 WINED3DVIEWPORT viewport;
5079 TRACE("(%p) Swapping rendertarget\n",This);
5080 if (RenderTargetIndex > 0) {
5081 FIXME("(%p) Render targets other than the first are not supported\n",This);
5082 RenderTargetIndex = 0;
5085 /* MSDN says that null disables the render target
5086 but a device must always be associated with a render target
5087 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5089 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5092 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5093 FIXME("Trying to set render target 0 to NULL\n");
5094 return D3DERR_INVALIDCALL;
5096 /* TODO: replace Impl* usage with interface usage */
5097 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & D3DUSAGE_RENDERTARGET) {
5098 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);
5099 return D3DERR_INVALIDCALL;
5101 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
5102 * builds, but I think wine counts as a 'debug' build for now.
5103 ******************************/
5104 /* If we are trying to set what we already have, don't bother */
5105 if (pRenderTarget == This->renderTarget) {
5106 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5108 /* Otherwise, set the render target up */
5110 if (FALSE == This->sceneEnded) {
5111 IWineD3DDevice_EndScene(iface);
5113 TRACE("clearing renderer\n");
5114 /* IWineD3DDeviceImpl_CleanRender(iface); */
5115 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5116 depending on the renter target implementation being used.
5117 A shared context implementation will share all buffers between all rendertargets (including swapchains),
5118 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5119 stencil buffer and incure an extra memory overhead */
5120 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
5123 if (SUCCEEDED(hr)) {
5124 /* Finally, reset the viewport as the MSDN states. */
5125 /* TODO: Replace impl usage */
5126 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
5127 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
5130 viewport.MaxZ = 1.0f;
5131 viewport.MinZ = 0.0f;
5132 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
5134 FIXME("Unknown error setting the render target\n");
5136 This->sceneEnded = FALSE;
5140 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
5141 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5142 HRESULT hr = D3D_OK;
5143 IWineD3DSurface *tmp;
5145 TRACE("(%p) Swapping z-buffer\n",This);
5147 if (pNewZStencil == This->stencilBufferTarget) {
5148 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5150 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5151 * depending on the renter target implementation being used.
5152 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5153 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5154 * stencil buffer and incure an extra memory overhead
5155 ******************************************************/
5158 tmp = This->stencilBufferTarget;
5159 This->stencilBufferTarget = pNewZStencil;
5160 /* should we be calling the parent or the wined3d surface? */
5161 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
5162 if (NULL != tmp) IWineD3DSurface_Release(tmp);
5164 /** TODO: glEnable/glDisable on depth/stencil depending on
5165 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
5166 **********************************************************/
5173 /* Internal functions not in DirectX */
5174 /** TODO: move this off to the opengl context manager
5175 *(the swapchain doesn't need to know anything about offscreen rendering!)
5176 ****************************************************/
5178 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
5180 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5182 TRACE("(%p), %p\n", This, swapchain);
5184 if (swapchain->win != swapchain->drawable) {
5185 /* Set everything back the way it ws */
5186 swapchain->render_ctx = swapchain->glCtx;
5187 swapchain->drawable = swapchain->win;
5192 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
5193 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
5194 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5197 unsigned int height;
5198 WINED3DFORMAT format;
5199 WINED3DSURFACE_DESC surfaceDesc;
5200 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5201 surfaceDesc.Width = &width;
5202 surfaceDesc.Height = &height;
5203 surfaceDesc.Format = &format;
5204 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5206 /* I need a get width/height function (and should do something with the format) */
5207 for (i = 0; i < CONTEXT_CACHE; ++i) {
5208 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
5209 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
5210 the pSurface can be set to 0 allowing it to be reused from cache **/
5211 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
5212 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
5213 *context = &This->contextCache[i];
5216 if (This->contextCache[i].Width == 0) {
5217 This->contextCache[i].pSurface = pSurface;
5218 This->contextCache[i].Width = width;
5219 This->contextCache[i].Height = height;
5220 *context = &This->contextCache[i];
5224 if (i == CONTEXT_CACHE) {
5225 int minUsage = 0x7FFFFFFF; /* MAX_INT */
5226 glContext *dropContext = 0;
5227 for (i = 0; i < CONTEXT_CACHE; i++) {
5228 if (This->contextCache[i].usedcount < minUsage) {
5229 dropContext = &This->contextCache[i];
5230 minUsage = This->contextCache[i].usedcount;
5233 /* clean up the context (this doesn't work for ATI at the moment */
5235 glXDestroyContext(swapchain->display, dropContext->context);
5236 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
5239 dropContext->Width = 0;
5240 dropContext->pSurface = pSurface;
5241 *context = dropContext;
5243 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
5244 for (i = 0; i < CONTEXT_CACHE; i++) {
5245 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
5249 if (*context != NULL)
5252 return E_OUTOFMEMORY;
5255 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
5256 * the functionality needs splitting up so that we don't do more than we should do.
5257 * this only seems to impact performance a little.
5258 ******************************/
5259 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5260 IWineD3DSurface *RenderSurface) {
5261 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5263 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
5264 HRESULT ret = D3DERR_INVALIDCALL;
5265 IWineD3DSurface *tmp;
5267 * Currently only active for GLX >= 1.3
5268 * for others versions we'll have to use GLXPixmaps
5270 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
5271 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
5272 * so only check OpenGL version
5273 * ..........................
5274 * I don't believe that it is a problem with NVidia headers,
5275 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
5276 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
5278 * Your application will report GLX version 1.2 on glXQueryVersion.
5279 * However, it is safe to call the GLX 1.3 functions as described below.
5281 #if defined(GL_VERSION_1_3)
5283 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
5284 GLXFBConfig* cfgs = NULL;
5288 IWineD3DSwapChain *currentSwapchain;
5289 IWineD3DSwapChainImpl *swapchain;
5290 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
5291 * but switch them off if the StencilSurface is set to NULL
5292 ** *********************************************************/
5293 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
5294 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
5297 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
5298 it StencilSurface != NULL && zBufferTarget == NULL switch it on
5301 #define PUSH1(att) attribs[nAttribs++] = (att);
5302 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
5304 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
5306 /** TODO: remove the reff to Impl (context manager should fix this!) **/
5307 IWineD3DSwapChainImpl *impSwapChain;
5308 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
5309 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
5310 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
5315 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
5316 PUSH2(GLX_X_RENDERABLE, TRUE);
5317 PUSH2(GLX_DOUBLEBUFFER, TRUE);
5318 TRACE("calling makeglcfg\n");
5319 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
5322 TRACE("calling chooseFGConfig\n");
5323 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5326 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
5327 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
5328 why we failed and only show this message once! */
5329 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"); /**/
5331 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
5332 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
5333 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
5334 PUSH2(GLX_DOUBLEBUFFER, FALSE);
5335 TRACE("calling makeglcfg\n");
5336 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
5338 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5345 for (i = 0; i < nCfgs; ++i) {
5346 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
5347 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
5348 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
5351 if (NULL != This->renderTarget) {
5353 vcheckGLcall("glFlush");
5354 /** This is only useful if the old render target was a swapchain,
5355 * we need to supercede this with a function that displays
5356 * the current buffer on the screen. This is easy to do in glx1.3 but
5357 * we need to do copy-write pixels in glx 1.2.
5358 ************************************************/
5359 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
5361 printf("Hit Enter to get next frame ...\n");
5367 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain) != D3D_OK) {
5368 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
5369 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
5373 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
5374 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
5375 **********************************************************************/
5376 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == D3D_OK) {
5377 /* We also need to make sure that the lights &co are also in the context of the swapchains */
5378 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
5379 TRACE("making swapchain active\n");
5380 if (RenderSurface != This->renderTarget) {
5381 if (RenderSurface == swapchain->backBuffer) {
5383 /* This could be flagged so that some operations work directly with the front buffer */
5384 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
5386 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
5388 TRACE("Error in setting current context: context %p drawable %ld !\n",
5389 impSwapChain->glCtx, impSwapChain->win);
5392 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5394 checkGLcall("glXMakeContextCurrent");
5396 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5398 else if (pbuffer_support == TRUE && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
5400 /** ********************************************************************
5401 * This is a quickly hacked out implementation of offscreen textures.
5402 * It will work in most cases but there may be problems if the client
5403 * modifies the texture directly, or expects the contents of the rendertarget
5406 * There are some real speed vs compatibility issues here:
5407 * we should really use a new context for every texture, but that eats ram.
5408 * we should also be restoring the texture to the pbuffer but that eats CPU
5409 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
5410 * but if this means reusing the display backbuffer then we need to make sure that
5411 * states are correctly preserved.
5412 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
5413 * and gain a good performance increase at the cost of compatibility.
5414 * I would suggest that, when this is the case, a user configurable flag be made
5415 * available, allowing the user to choose the best emulated experience for them.
5416 *********************************************************************/
5418 XVisualInfo *visinfo;
5419 glContext *newContext;
5421 /* Here were using a shared context model */
5422 if (D3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
5423 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5426 /* If the context doesn't exist then create a new one */
5427 /* TODO: This should really be part of findGlContext */
5428 if (NULL == newContext->context) {
5430 TRACE("making new buffer\n");
5432 PUSH2(GLX_PBUFFER_WIDTH, newContext->Width);
5433 PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
5436 newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
5438 /** ****************************************
5439 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
5441 * In future releases, we may provide the calls glXCreateNewContext,
5442 * glXQueryDrawable and glXMakeContextCurrent.
5443 * so until then we have to use glXGetVisualFromFBConfig &co..
5444 ********************************************/
5447 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
5449 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
5451 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
5455 if (NULL == newContext || NULL == newContext->context) {
5456 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5458 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
5459 if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
5460 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
5463 /* Clean up the old context */
5464 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5465 /* Set the current context of the swapchain to the new context */
5466 impSwapChain->drawable = newContext->drawable;
5467 impSwapChain->render_ctx = newContext->context;
5471 #if 1 /* Apply the stateblock to the new context
5472 FIXME: This is a bit of a hack, each context should know it's own state,
5473 the directX current directX state should then be applied to the context */
5476 IWineD3DStateBlockImpl *oldUpdateStateBlock;
5477 oldUpdateStateBlock = This->updateStateBlock;
5478 oldRecording= This->isRecordingState;
5479 This->isRecordingState = FALSE;
5480 This->updateStateBlock = This->stateBlock;
5481 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
5483 This->isRecordingState = oldRecording;
5484 This->updateStateBlock = oldUpdateStateBlock;
5489 /* clean up the current rendertargets swapchain (if it belonged to one) */
5490 if (currentSwapchain != NULL) {
5491 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
5494 /* Were done with the opengl context management, setup the rendertargets */
5496 tmp = This->renderTarget;
5497 This->renderTarget = RenderSurface;
5498 IWineD3DSurface_AddRef(This->renderTarget);
5499 IWineD3DSurface_Release(tmp);
5505 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
5506 /* Check that the container is not a swapchain member */
5508 IWineD3DSwapChain *tmpSwapChain;
5509 if (D3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
5510 This->renderUpsideDown = TRUE;
5512 This->renderUpsideDown = FALSE;
5513 IWineD3DSwapChain_Release(tmpSwapChain);
5515 /* Force updating the cull mode */
5516 TRACE("setting render state\n");
5517 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
5518 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
5520 /* Force updating projection matrix */
5521 This->last_was_rhw = FALSE;
5522 This->proj_valid = FALSE;
5530 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
5531 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
5536 if ( NULL != impSwapChain) {
5537 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
5545 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
5546 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
5547 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5548 /* TODO: the use of Impl is deprecated. */
5549 /* some basic validation checks */
5550 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
5552 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
5554 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
5555 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
5556 return D3DERR_INVALIDCALL;
5558 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
5559 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
5560 return D3DERR_INVALIDCALL;
5562 /* TODO: make the cursor 'real' */
5564 This->xHotSpot = XHotSpot;
5565 This->yHotSpot = YHotSpot;
5570 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
5571 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5572 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
5574 This->xScreenSpace = XScreenSpace;
5575 This->yScreenSpace = YScreenSpace;
5581 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
5582 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5583 TRACE("(%p) : visible(%d)\n", This, bShow);
5585 This->bCursorVisible = bShow;
5590 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
5591 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5592 FIXME("(%p) : stub\n", This); /* No way of notifying yet! */
5597 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
5598 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5599 /** FIXME: Resource tracking needs to be done,
5600 * The closes we can do to this is set the priorities of all managed textures low
5601 * and then reset them.
5602 ***********************************************************/
5603 FIXME("(%p) : stub\n", This);
5607 HRESULT WINAPI IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
5608 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5609 /** FIXME: Resource trascking needs to be done.
5610 * in effect this pulls all non only default
5611 * textures out of video memory and deletes all glTextures (glDeleteTextures)
5612 * and should clear down the context and set it up according to pPresentationParameters
5613 ***********************************************************/
5614 FIXME("(%p) : stub\n", This);
5618 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
5619 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5620 /** FIXME: always true at the moment **/
5621 if(bEnableDialogs == FALSE) {
5622 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
5628 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
5629 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5631 FIXME("(%p) : stub\n", This);
5632 /* Setup some reasonable defaults */
5633 pParameters->AdapterOrdinal = 0; /* always for now */
5634 pParameters->DeviceType = D3DDEVTYPE_HAL; /* always for now */
5635 pParameters->hFocusWindow = 0;
5636 pParameters->BehaviorFlags =0;
5640 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
5641 IWineD3DSwapChain *swapchain;
5642 HRESULT hrc = D3D_OK;
5644 TRACE("Relaying to swapchain\n");
5646 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
5647 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (D3DGAMMARAMP *)pRamp);
5648 IWineD3DSwapChain_Release(swapchain);
5653 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
5654 IWineD3DSwapChain *swapchain;
5655 HRESULT hrc = D3D_OK;
5657 TRACE("Relaying to swapchain\n");
5659 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
5660 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
5661 IWineD3DSwapChain_Release(swapchain);
5667 /** ********************************************************
5668 * Notification functions
5669 ** ********************************************************/
5670 /** This function must be called in the release of a resource when ref == 0,
5671 * the contents of resource must still be correct,
5672 * any handels to other resource held by the caller must be closed
5673 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
5674 *****************************************************/
5675 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5676 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5677 ResourceList* resourceList;
5679 TRACE("(%p) : resource %p\n", This, resource);
5681 EnterCriticalSection(&resourceStoreCriticalSection);
5683 /* add a new texture to the frot of the linked list */
5684 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
5685 resourceList->resource = resource;
5687 /* Get the old head */
5688 resourceList->next = This->resources;
5690 This->resources = resourceList;
5691 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
5694 LeaveCriticalSection(&resourceStoreCriticalSection);
5699 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5700 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5701 ResourceList* resourceList = NULL;
5702 ResourceList* previousResourceList = NULL;
5704 TRACE("(%p) : resource %p\n", This, resource);
5707 EnterCriticalSection(&resourceStoreCriticalSection);
5709 resourceList = This->resources;
5711 while (resourceList != NULL) {
5712 if(resourceList->resource == resource) break;
5713 previousResourceList = resourceList;
5714 resourceList = resourceList->next;
5717 if (resourceList == NULL) {
5718 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
5720 LeaveCriticalSection(&resourceStoreCriticalSection);
5724 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
5726 /* make sure we don't leave a hole in the list */
5727 if (previousResourceList != NULL) {
5728 previousResourceList->next = resourceList->next;
5730 This->resources = resourceList->next;
5734 LeaveCriticalSection(&resourceStoreCriticalSection);
5740 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
5741 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5744 TRACE("(%p) : resource %p\n", This, resource);
5745 switch(IWineD3DResource_GetType(resource)){
5746 case D3DRTYPE_SURFACE:
5747 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
5749 case D3DRTYPE_TEXTURE:
5750 case D3DRTYPE_CUBETEXTURE:
5751 case D3DRTYPE_VOLUMETEXTURE:
5752 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
5753 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5754 IUnknown *textureParent;
5755 IWineD3DBaseTexture_GetParent(This->stateBlock->textures[counter], &textureParent);
5756 /* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
5757 FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter, resource, textureParent);
5758 IUnknown_Release(textureParent);
5759 This->stateBlock->textures[counter] = NULL;
5761 if (This->updateStateBlock != This->stateBlock ){
5762 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5763 IUnknown *textureParent;
5764 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[counter], &textureParent);
5765 /* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
5766 FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter, resource, textureParent);
5767 IUnknown_Release(textureParent);
5768 This->updateStateBlock->textures[counter] = NULL;
5773 case D3DRTYPE_VOLUME:
5774 /* TODO: nothing really? */
5776 case D3DRTYPE_VERTEXBUFFER:
5777 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
5780 TRACE("Cleaning up stream pointers\n");
5782 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
5783 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
5784 FINDOUT: should changes.streamSource[StreamNumber] be set ?
5786 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5787 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
5788 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
5789 This->updateStateBlock->streamSource[streamNumber] = 0;
5790 /* Set changed flag? */
5793 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) */
5794 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
5795 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
5796 This->stateBlock->streamSource[streamNumber] = 0;
5799 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
5800 else { /* This shouldn't happen */
5801 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
5808 case D3DRTYPE_INDEXBUFFER:
5809 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
5810 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5811 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5812 This->updateStateBlock->pIndexData = NULL;
5815 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
5816 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5817 This->stateBlock->pIndexData = NULL;
5823 FIXME("(%p) unknown resource type %p %u \n", This, resource, IWineD3DResource_GetType(resource));
5828 /* Remove the resoruce from the resourceStore */
5829 IWineD3DDeviceImpl_RemoveResource(iface, resource);
5831 TRACE("Resource released\n");
5836 /** This function is to be called by the swapchain when it is released and it's ref = 0
5837 *****************************************************/
5838 void WINAPI IWineD3DDeviceImpl_SwapChainReleased(IWineD3DDevice *iface, IWineD3DSwapChain *swapChain){
5839 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5840 SwapChainList **nextSwapchain;
5841 nextSwapchain = &This->swapchains;
5843 /* Check to see if the swapchian is being used as the render target */
5844 if (This->renderTarget != NULL) {
5845 IWineD3DSurface *swapchainBackBuffer;
5847 IWineD3DSwapChain_GetBackBuffer(swapChain, 0 ,( D3DBACKBUFFER_TYPE) 0, &swapchainBackBuffer);
5848 if (This->renderTarget == swapchainBackBuffer) {
5849 /* Don't know what to do, so warn and carry on as usual (which in this case leaves the renderterget in limbo) */
5850 FIXME("Atempting to release a swapchain that is currently beuing used as a render target, behaviour is undefined\n");
5854 /* Go through the swapchain list and try to find the swapchain being released */
5855 while(*nextSwapchain != NULL && (*nextSwapchain)->swapchain != swapChain) {
5856 nextSwapchain = &(*nextSwapchain)->next;
5859 /* Check to see if we found the swapchain */
5860 if (NULL != *nextSwapchain) {
5861 /* We found the swapchain so remove it from the list */
5862 TRACE("(%p) releasing swapchain(%p)\n", iface, swapChain);
5863 HeapFree(GetProcessHeap(), 0 , *nextSwapchain);
5864 *nextSwapchain = (*nextSwapchain)->next;
5866 /* We didn't find the swapchain on the list, this can only heppen because of a programming error in wined3d */
5867 FIXME("(%p) Attempting to release a swapchain (%p) that hasn't been stored\n", iface, swapChain);
5870 TRACE("swapchain (%p) released\n", swapChain);
5874 /**********************************************************
5875 * IWineD3DDevice VTbl follows
5876 **********************************************************/
5878 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
5880 /*** IUnknown methods ***/
5881 IWineD3DDeviceImpl_QueryInterface,
5882 IWineD3DDeviceImpl_AddRef,
5883 IWineD3DDeviceImpl_Release,
5884 /*** IWineD3DDevice methods ***/
5885 IWineD3DDeviceImpl_GetParent,
5886 /*** Creation methods**/
5887 IWineD3DDeviceImpl_CreateVertexBuffer,
5888 IWineD3DDeviceImpl_CreateIndexBuffer,
5889 IWineD3DDeviceImpl_CreateStateBlock,
5890 IWineD3DDeviceImpl_CreateSurface,
5891 IWineD3DDeviceImpl_CreateTexture,
5892 IWineD3DDeviceImpl_CreateVolumeTexture,
5893 IWineD3DDeviceImpl_CreateVolume,
5894 IWineD3DDeviceImpl_CreateCubeTexture,
5895 IWineD3DDeviceImpl_CreateQuery,
5896 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
5897 IWineD3DDeviceImpl_CreateVertexDeclaration,
5898 IWineD3DDeviceImpl_CreateVertexShader,
5899 IWineD3DDeviceImpl_CreatePixelShader,
5900 /*** Odd functions **/
5901 IWineD3DDeviceImpl_EvictManagedResources,
5902 IWineD3DDeviceImpl_GetAvailableTextureMem,
5903 IWineD3DDeviceImpl_GetBackBuffer,
5904 IWineD3DDeviceImpl_GetCreationParameters,
5905 IWineD3DDeviceImpl_GetDeviceCaps,
5906 IWineD3DDeviceImpl_GetDirect3D,
5907 IWineD3DDeviceImpl_GetDisplayMode,
5908 IWineD3DDeviceImpl_GetNumberOfSwapChains,
5909 IWineD3DDeviceImpl_GetRasterStatus,
5910 IWineD3DDeviceImpl_GetSwapChain,
5911 IWineD3DDeviceImpl_Reset,
5912 IWineD3DDeviceImpl_SetDialogBoxMode,
5913 IWineD3DDeviceImpl_SetCursorProperties,
5914 IWineD3DDeviceImpl_SetCursorPosition,
5915 IWineD3DDeviceImpl_ShowCursor,
5916 IWineD3DDeviceImpl_TestCooperativeLevel,
5917 /*** Getters and setters **/
5918 IWineD3DDeviceImpl_SetClipPlane,
5919 IWineD3DDeviceImpl_GetClipPlane,
5920 IWineD3DDeviceImpl_SetClipStatus,
5921 IWineD3DDeviceImpl_GetClipStatus,
5922 IWineD3DDeviceImpl_SetCurrentTexturePalette,
5923 IWineD3DDeviceImpl_GetCurrentTexturePalette,
5924 IWineD3DDeviceImpl_SetDepthStencilSurface,
5925 IWineD3DDeviceImpl_GetDepthStencilSurface,
5926 IWineD3DDeviceImpl_SetFVF,
5927 IWineD3DDeviceImpl_GetFVF,
5928 IWineD3DDeviceImpl_SetGammaRamp,
5929 IWineD3DDeviceImpl_GetGammaRamp,
5930 IWineD3DDeviceImpl_SetIndices,
5931 IWineD3DDeviceImpl_GetIndices,
5932 IWineD3DDeviceImpl_SetLight,
5933 IWineD3DDeviceImpl_GetLight,
5934 IWineD3DDeviceImpl_SetLightEnable,
5935 IWineD3DDeviceImpl_GetLightEnable,
5936 IWineD3DDeviceImpl_SetMaterial,
5937 IWineD3DDeviceImpl_GetMaterial,
5938 IWineD3DDeviceImpl_SetNPatchMode,
5939 IWineD3DDeviceImpl_GetNPatchMode,
5940 IWineD3DDeviceImpl_SetPaletteEntries,
5941 IWineD3DDeviceImpl_GetPaletteEntries,
5942 IWineD3DDeviceImpl_SetPixelShader,
5943 IWineD3DDeviceImpl_GetPixelShader,
5944 IWineD3DDeviceImpl_SetPixelShaderConstantB,
5945 IWineD3DDeviceImpl_GetPixelShaderConstantB,
5946 IWineD3DDeviceImpl_SetPixelShaderConstantI,
5947 IWineD3DDeviceImpl_GetPixelShaderConstantI,
5948 IWineD3DDeviceImpl_SetPixelShaderConstantF,
5949 IWineD3DDeviceImpl_GetPixelShaderConstantF,
5950 IWineD3DDeviceImpl_SetRenderState,
5951 IWineD3DDeviceImpl_GetRenderState,
5952 IWineD3DDeviceImpl_SetRenderTarget,
5953 IWineD3DDeviceImpl_GetRenderTarget,
5954 IWineD3DDeviceImpl_SetSamplerState,
5955 IWineD3DDeviceImpl_GetSamplerState,
5956 IWineD3DDeviceImpl_SetScissorRect,
5957 IWineD3DDeviceImpl_GetScissorRect,
5958 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
5959 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
5960 IWineD3DDeviceImpl_SetStreamSource,
5961 IWineD3DDeviceImpl_GetStreamSource,
5962 IWineD3DDeviceImpl_SetStreamSourceFreq,
5963 IWineD3DDeviceImpl_GetStreamSourceFreq,
5964 IWineD3DDeviceImpl_SetTexture,
5965 IWineD3DDeviceImpl_GetTexture,
5966 IWineD3DDeviceImpl_SetTextureStageState,
5967 IWineD3DDeviceImpl_GetTextureStageState,
5968 IWineD3DDeviceImpl_SetTransform,
5969 IWineD3DDeviceImpl_GetTransform,
5970 IWineD3DDeviceImpl_SetVertexDeclaration,
5971 IWineD3DDeviceImpl_GetVertexDeclaration,
5972 IWineD3DDeviceImpl_SetVertexShader,
5973 IWineD3DDeviceImpl_GetVertexShader,
5974 IWineD3DDeviceImpl_SetVertexShaderConstantB,
5975 IWineD3DDeviceImpl_GetVertexShaderConstantB,
5976 IWineD3DDeviceImpl_SetVertexShaderConstantI,
5977 IWineD3DDeviceImpl_GetVertexShaderConstantI,
5978 IWineD3DDeviceImpl_SetVertexShaderConstantF,
5979 IWineD3DDeviceImpl_GetVertexShaderConstantF,
5980 IWineD3DDeviceImpl_SetViewport,
5981 IWineD3DDeviceImpl_GetViewport,
5982 IWineD3DDeviceImpl_MultiplyTransform,
5983 IWineD3DDeviceImpl_ValidateDevice,
5984 IWineD3DDeviceImpl_ProcessVertices,
5985 /*** State block ***/
5986 IWineD3DDeviceImpl_BeginStateBlock,
5987 IWineD3DDeviceImpl_EndStateBlock,
5988 /*** Scene management ***/
5989 IWineD3DDeviceImpl_BeginScene,
5990 IWineD3DDeviceImpl_EndScene,
5991 IWineD3DDeviceImpl_Present,
5992 IWineD3DDeviceImpl_Clear,
5994 IWineD3DDeviceImpl_DrawPrimitive,
5995 IWineD3DDeviceImpl_DrawIndexedPrimitive,
5996 IWineD3DDeviceImpl_DrawPrimitiveUP,
5997 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
5998 IWineD3DDeviceImpl_DrawRectPatch,
5999 IWineD3DDeviceImpl_DrawTriPatch,
6000 IWineD3DDeviceImpl_DeletePatch,
6001 IWineD3DDeviceImpl_ColorFill,
6002 IWineD3DDeviceImpl_UpdateTexture,
6003 IWineD3DDeviceImpl_UpdateSurface,
6004 IWineD3DDeviceImpl_StretchRect,
6005 IWineD3DDeviceImpl_GetRenderTargetData,
6006 IWineD3DDeviceImpl_GetFrontBufferData,
6007 /*** Internal use IWineD3DDevice methods ***/
6008 IWineD3DDeviceImpl_SetupTextureStates,
6009 /*** object tracking ***/
6010 IWineD3DDeviceImpl_SwapChainReleased,
6011 IWineD3DDeviceImpl_ResourceReleased
6015 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
6016 WINED3DRS_ALPHABLENDENABLE ,
6017 WINED3DRS_ALPHAFUNC ,
6018 WINED3DRS_ALPHAREF ,
6019 WINED3DRS_ALPHATESTENABLE ,
6021 WINED3DRS_COLORWRITEENABLE ,
6022 WINED3DRS_DESTBLEND ,
6023 WINED3DRS_DITHERENABLE ,
6024 WINED3DRS_FILLMODE ,
6025 WINED3DRS_FOGDENSITY ,
6027 WINED3DRS_FOGSTART ,
6028 WINED3DRS_LASTPIXEL ,
6029 WINED3DRS_SHADEMODE ,
6030 WINED3DRS_SRCBLEND ,
6031 WINED3DRS_STENCILENABLE ,
6032 WINED3DRS_STENCILFAIL ,
6033 WINED3DRS_STENCILFUNC ,
6034 WINED3DRS_STENCILMASK ,
6035 WINED3DRS_STENCILPASS ,
6036 WINED3DRS_STENCILREF ,
6037 WINED3DRS_STENCILWRITEMASK ,
6038 WINED3DRS_STENCILZFAIL ,
6039 WINED3DRS_TEXTUREFACTOR ,
6050 WINED3DRS_ZWRITEENABLE
6053 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
6054 WINED3DTSS_ADDRESSW ,
6055 WINED3DTSS_ALPHAARG0 ,
6056 WINED3DTSS_ALPHAARG1 ,
6057 WINED3DTSS_ALPHAARG2 ,
6058 WINED3DTSS_ALPHAOP ,
6059 WINED3DTSS_BUMPENVLOFFSET ,
6060 WINED3DTSS_BUMPENVLSCALE ,
6061 WINED3DTSS_BUMPENVMAT00 ,
6062 WINED3DTSS_BUMPENVMAT01 ,
6063 WINED3DTSS_BUMPENVMAT10 ,
6064 WINED3DTSS_BUMPENVMAT11 ,
6065 WINED3DTSS_COLORARG0 ,
6066 WINED3DTSS_COLORARG1 ,
6067 WINED3DTSS_COLORARG2 ,
6068 WINED3DTSS_COLOROP ,
6069 WINED3DTSS_RESULTARG ,
6070 WINED3DTSS_TEXCOORDINDEX ,
6071 WINED3DTSS_TEXTURETRANSFORMFLAGS
6074 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
6075 WINED3DSAMP_ADDRESSU ,
6076 WINED3DSAMP_ADDRESSV ,
6077 WINED3DSAMP_ADDRESSW ,
6078 WINED3DSAMP_BORDERCOLOR ,
6079 WINED3DSAMP_MAGFILTER ,
6080 WINED3DSAMP_MINFILTER ,
6081 WINED3DSAMP_MIPFILTER ,
6082 WINED3DSAMP_MIPMAPLODBIAS ,
6083 WINED3DSAMP_MAXMIPLEVEL ,
6084 WINED3DSAMP_MAXANISOTROPY ,
6085 WINED3DSAMP_SRGBTEXTURE ,
6086 WINED3DSAMP_ELEMENTINDEX
6089 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
6091 WINED3DRS_AMBIENTMATERIALSOURCE ,
6092 WINED3DRS_CLIPPING ,
6093 WINED3DRS_CLIPPLANEENABLE ,
6094 WINED3DRS_COLORVERTEX ,
6095 WINED3DRS_DIFFUSEMATERIALSOURCE ,
6096 WINED3DRS_EMISSIVEMATERIALSOURCE ,
6097 WINED3DRS_FOGDENSITY ,
6099 WINED3DRS_FOGSTART ,
6100 WINED3DRS_FOGTABLEMODE ,
6101 WINED3DRS_FOGVERTEXMODE ,
6102 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
6103 WINED3DRS_LIGHTING ,
6104 WINED3DRS_LOCALVIEWER ,
6105 WINED3DRS_MULTISAMPLEANTIALIAS ,
6106 WINED3DRS_MULTISAMPLEMASK ,
6107 WINED3DRS_NORMALIZENORMALS ,
6108 WINED3DRS_PATCHEDGESTYLE ,
6109 WINED3DRS_POINTSCALE_A ,
6110 WINED3DRS_POINTSCALE_B ,
6111 WINED3DRS_POINTSCALE_C ,
6112 WINED3DRS_POINTSCALEENABLE ,
6113 WINED3DRS_POINTSIZE ,
6114 WINED3DRS_POINTSIZE_MAX ,
6115 WINED3DRS_POINTSIZE_MIN ,
6116 WINED3DRS_POINTSPRITEENABLE ,
6117 WINED3DRS_RANGEFOGENABLE ,
6118 WINED3DRS_SPECULARMATERIALSOURCE ,
6119 WINED3DRS_TWEENFACTOR ,
6120 WINED3DRS_VERTEXBLEND
6123 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
6124 WINED3DTSS_TEXCOORDINDEX ,
6125 WINED3DTSS_TEXTURETRANSFORMFLAGS
6128 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
6129 WINED3DSAMP_DMAPOFFSET