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 FIXME("(%p) : Stub\n", This);
1472 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice* iface, IWineD3D** ppD3D) {
1473 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1474 *ppD3D= This->wineD3D;
1475 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1476 IWineD3D_AddRef(*ppD3D);
1480 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1481 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1482 * Into the video ram as possible and seeing how many fit
1483 * you can also get the correct initial value from via X and ATI's driver
1484 *******************/
1485 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1486 static BOOL showfixmes = TRUE;
1488 FIXME("(%p) : stub, emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1489 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1492 TRACE("(%p) : emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1493 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1494 /* videomemory is simulated videomemory + AGP memory left */
1495 return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1503 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1504 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1506 /* Update the current state block */
1507 This->updateStateBlock->fvf = fvf;
1508 This->updateStateBlock->changed.fvf = TRUE;
1509 This->updateStateBlock->set.fvf = TRUE;
1511 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1512 /* clear down the vertex declaration
1513 NOTE: Axis and Allies doesn't work properly otherwise
1514 (may be a stateblock problem though!)
1516 /* No difference if recording or not */
1517 return IWineD3DDevice_SetVertexDeclaration(iface, NULL);
1522 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1523 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1524 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1525 *pfvf = This->stateBlock->fvf;
1530 * Get / Set Stream Source
1532 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1533 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1534 IWineD3DVertexBuffer *oldSrc;
1536 oldSrc = This->stateBlock->streamSource[StreamNumber];
1537 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1539 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
1540 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
1541 This->updateStateBlock->streamStride[StreamNumber] = Stride;
1542 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
1543 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
1545 /* Handle recording of state blocks */
1546 if (This->isRecordingState) {
1547 TRACE("Recording... not performing anything\n");
1551 /* Not recording... */
1552 if (pStreamData != NULL) {
1553 IUnknown *newVertexBufferParent;
1554 /* GetParent will add a ref, so leave it hanging until the vertex buffer is cleared */
1555 IWineD3DVertexBuffer_GetParent(pStreamData, &newVertexBufferParent);
1557 if (oldSrc != NULL) {
1558 IUnknown *oldVertexBufferParent;
1559 IWineD3DVertexBuffer_GetParent(oldSrc, &oldVertexBufferParent);
1560 IUnknown_Release(oldVertexBufferParent);
1561 IUnknown_Release(oldVertexBufferParent);
1567 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
1568 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1570 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
1571 *pStream = This->stateBlock->streamSource[StreamNumber];
1572 *pStride = This->stateBlock->streamStride[StreamNumber];
1573 *pOffset = This->stateBlock->streamOffset[StreamNumber];
1574 if (*pStream != NULL) IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
1578 /*Should be quite easy, just an extension of vertexdata
1580 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1582 The divider is a bit odd though
1584 VertexOffset = StartVertex / Divider * StreamStride +
1585 VertexIndex / Divider * StreamStride + StreamOffset
1588 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
1589 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1591 FIXME("(%p) : stub\n", This);
1595 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
1596 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1598 FIXME("(%p) : stub\n", This);
1603 * Get / Set & Multiply Transform
1605 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1606 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1608 /* Most of this routine, comments included copied from ddraw tree initially: */
1609 TRACE("(%p) : Transform State=%d\n", This, d3dts);
1611 /* Handle recording of state blocks */
1612 if (This->isRecordingState) {
1613 TRACE("Recording... not performing anything\n");
1614 This->updateStateBlock->changed.transform[d3dts] = TRUE;
1615 This->updateStateBlock->set.transform[d3dts] = TRUE;
1616 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1621 * If the new matrix is the same as the current one,
1622 * we cut off any further processing. this seems to be a reasonable
1623 * optimization because as was noticed, some apps (warcraft3 for example)
1624 * tend towards setting the same matrix repeatedly for some reason.
1626 * From here on we assume that the new matrix is different, wherever it matters.
1628 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1629 TRACE("The app is setting the same matrix over again\n");
1632 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1636 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1637 where ViewMat = Camera space, WorldMat = world space.
1639 In OpenGL, camera and world space is combined into GL_MODELVIEW
1640 matrix. The Projection matrix stay projection matrix.
1643 /* Capture the times we can just ignore the change for now */
1644 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1645 This->modelview_valid = FALSE;
1648 } else if (d3dts == D3DTS_PROJECTION) {
1649 This->proj_valid = FALSE;
1652 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1653 /* Indexed Vertex Blending Matrices 256 -> 511 */
1654 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1655 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1659 /* Now we really are going to have to change a matrix */
1662 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1663 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
1664 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1667 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1668 * NOTE: We have to reset the positions even if the light/plane is not currently
1669 * enabled, since the call to enable it will not reset the position.
1670 * NOTE2: Apparently texture transforms do NOT need reapplying
1673 PLIGHTINFOEL *lightChain = NULL;
1674 This->modelview_valid = FALSE;
1675 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
1677 glMatrixMode(GL_MODELVIEW);
1678 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1680 glLoadMatrixf((float *)lpmatrix);
1681 checkGLcall("glLoadMatrixf(...)");
1684 lightChain = This->stateBlock->lights;
1685 while (lightChain && lightChain->glIndex != -1) {
1686 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1687 checkGLcall("glLightfv posn");
1688 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1689 checkGLcall("glLightfv dirn");
1690 lightChain = lightChain->next;
1693 /* Reset Clipping Planes if clipping is enabled */
1694 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1695 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1696 checkGLcall("glClipPlane");
1700 } else { /* What was requested!?? */
1701 WARN("invalid matrix specified: %i\n", d3dts);
1704 /* Release lock, all done */
1709 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1710 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1711 TRACE("(%p) : for Transform State %d\n", This, State);
1712 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1716 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1717 D3DMATRIX *mat = NULL;
1720 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1721 * below means it will be recorded in a state block change, but it
1722 * works regardless where it is recorded.
1723 * If this is found to be wrong, change to StateBlock.
1725 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1726 TRACE("(%p) : For state %u\n", This, State);
1728 if (State < HIGHEST_TRANSFORMSTATE)
1730 mat = &This->updateStateBlock->transforms[State];
1732 FIXME("Unhandled transform state!!\n");
1735 /* Copied from ddraw code: */
1736 temp.u.s._11 = (mat->u.s._11 * pMatrix->u.s._11) + (mat->u.s._21 * pMatrix->u.s._12) +
1737 (mat->u.s._31 * pMatrix->u.s._13) + (mat->u.s._41 * pMatrix->u.s._14);
1738 temp.u.s._21 = (mat->u.s._11 * pMatrix->u.s._21) + (mat->u.s._21 * pMatrix->u.s._22) +
1739 (mat->u.s._31 * pMatrix->u.s._23) + (mat->u.s._41 * pMatrix->u.s._24);
1740 temp.u.s._31 = (mat->u.s._11 * pMatrix->u.s._31) + (mat->u.s._21 * pMatrix->u.s._32) +
1741 (mat->u.s._31 * pMatrix->u.s._33) + (mat->u.s._41 * pMatrix->u.s._34);
1742 temp.u.s._41 = (mat->u.s._11 * pMatrix->u.s._41) + (mat->u.s._21 * pMatrix->u.s._42) +
1743 (mat->u.s._31 * pMatrix->u.s._43) + (mat->u.s._41 * pMatrix->u.s._44);
1745 temp.u.s._12 = (mat->u.s._12 * pMatrix->u.s._11) + (mat->u.s._22 * pMatrix->u.s._12) +
1746 (mat->u.s._32 * pMatrix->u.s._13) + (mat->u.s._42 * pMatrix->u.s._14);
1747 temp.u.s._22 = (mat->u.s._12 * pMatrix->u.s._21) + (mat->u.s._22 * pMatrix->u.s._22) +
1748 (mat->u.s._32 * pMatrix->u.s._23) + (mat->u.s._42 * pMatrix->u.s._24);
1749 temp.u.s._32 = (mat->u.s._12 * pMatrix->u.s._31) + (mat->u.s._22 * pMatrix->u.s._32) +
1750 (mat->u.s._32 * pMatrix->u.s._33) + (mat->u.s._42 * pMatrix->u.s._34);
1751 temp.u.s._42 = (mat->u.s._12 * pMatrix->u.s._41) + (mat->u.s._22 * pMatrix->u.s._42) +
1752 (mat->u.s._32 * pMatrix->u.s._43) + (mat->u.s._42 * pMatrix->u.s._44);
1754 temp.u.s._13 = (mat->u.s._13 * pMatrix->u.s._11) + (mat->u.s._23 * pMatrix->u.s._12) +
1755 (mat->u.s._33 * pMatrix->u.s._13) + (mat->u.s._43 * pMatrix->u.s._14);
1756 temp.u.s._23 = (mat->u.s._13 * pMatrix->u.s._21) + (mat->u.s._23 * pMatrix->u.s._22) +
1757 (mat->u.s._33 * pMatrix->u.s._23) + (mat->u.s._43 * pMatrix->u.s._24);
1758 temp.u.s._33 = (mat->u.s._13 * pMatrix->u.s._31) + (mat->u.s._23 * pMatrix->u.s._32) +
1759 (mat->u.s._33 * pMatrix->u.s._33) + (mat->u.s._43 * pMatrix->u.s._34);
1760 temp.u.s._43 = (mat->u.s._13 * pMatrix->u.s._41) + (mat->u.s._23 * pMatrix->u.s._42) +
1761 (mat->u.s._33 * pMatrix->u.s._43) + (mat->u.s._43 * pMatrix->u.s._44);
1763 temp.u.s._14 = (mat->u.s._14 * pMatrix->u.s._11) + (mat->u.s._24 * pMatrix->u.s._12) +
1764 (mat->u.s._34 * pMatrix->u.s._13) + (mat->u.s._44 * pMatrix->u.s._14);
1765 temp.u.s._24 = (mat->u.s._14 * pMatrix->u.s._21) + (mat->u.s._24 * pMatrix->u.s._22) +
1766 (mat->u.s._34 * pMatrix->u.s._23) + (mat->u.s._44 * pMatrix->u.s._24);
1767 temp.u.s._34 = (mat->u.s._14 * pMatrix->u.s._31) + (mat->u.s._24 * pMatrix->u.s._32) +
1768 (mat->u.s._34 * pMatrix->u.s._33) + (mat->u.s._44 * pMatrix->u.s._34);
1769 temp.u.s._44 = (mat->u.s._14 * pMatrix->u.s._41) + (mat->u.s._24 * pMatrix->u.s._42) +
1770 (mat->u.s._34 * pMatrix->u.s._43) + (mat->u.s._44 * pMatrix->u.s._44);
1772 /* Apply change via set transform - will reapply to eg. lights this way */
1773 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
1778 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
1780 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1781 you can reference any indexes you want as long as that number max are enabled at any
1782 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1783 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1784 but when recording, just build a chain pretty much of commands to be replayed. */
1786 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
1788 PLIGHTINFOEL *object, *temp;
1790 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1791 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1793 /* If recording state block, just add to end of lights chain */
1794 if (This->isRecordingState) {
1795 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1796 if (NULL == object) {
1797 return D3DERR_OUTOFVIDEOMEMORY;
1799 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1800 object->OriginalIndex = Index;
1801 object->glIndex = -1;
1802 object->changed = TRUE;
1804 /* Add to the END of the chain of lights changes to be replayed */
1805 if (This->updateStateBlock->lights == NULL) {
1806 This->updateStateBlock->lights = object;
1808 temp = This->updateStateBlock->lights;
1809 while (temp->next != NULL) temp=temp->next;
1810 temp->next = object;
1812 TRACE("Recording... not performing anything more\n");
1816 /* Ok, not recording any longer so do real work */
1817 object = This->stateBlock->lights;
1818 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1820 /* If we didn't find it in the list of lights, time to add it */
1821 if (object == NULL) {
1822 PLIGHTINFOEL *insertAt,*prevPos;
1824 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1825 if (NULL == object) {
1826 return D3DERR_OUTOFVIDEOMEMORY;
1828 object->OriginalIndex = Index;
1829 object->glIndex = -1;
1831 /* Add it to the front of list with the idea that lights will be changed as needed
1832 BUT after any lights currently assigned GL indexes */
1833 insertAt = This->stateBlock->lights;
1835 while (insertAt != NULL && insertAt->glIndex != -1) {
1837 insertAt = insertAt->next;
1840 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1841 This->stateBlock->lights = object;
1842 } else if (insertAt == NULL) { /* End of list */
1843 prevPos->next = object;
1844 object->prev = prevPos;
1845 } else { /* Middle of chain */
1846 if (prevPos == NULL) {
1847 This->stateBlock->lights = object;
1849 prevPos->next = object;
1851 object->prev = prevPos;
1852 object->next = insertAt;
1853 insertAt->prev = object;
1857 /* Initialze the object */
1858 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,
1859 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1860 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1861 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1862 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1863 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1864 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1866 /* Save away the information */
1867 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1869 switch (pLight->Type) {
1870 case D3DLIGHT_POINT:
1872 object->lightPosn[0] = pLight->Position.x;
1873 object->lightPosn[1] = pLight->Position.y;
1874 object->lightPosn[2] = pLight->Position.z;
1875 object->lightPosn[3] = 1.0f;
1876 object->cutoff = 180.0f;
1880 case D3DLIGHT_DIRECTIONAL:
1882 object->lightPosn[0] = -pLight->Direction.x;
1883 object->lightPosn[1] = -pLight->Direction.y;
1884 object->lightPosn[2] = -pLight->Direction.z;
1885 object->lightPosn[3] = 0.0;
1886 object->exponent = 0.0f;
1887 object->cutoff = 180.0f;
1892 object->lightPosn[0] = pLight->Position.x;
1893 object->lightPosn[1] = pLight->Position.y;
1894 object->lightPosn[2] = pLight->Position.z;
1895 object->lightPosn[3] = 1.0;
1898 object->lightDirn[0] = pLight->Direction.x;
1899 object->lightDirn[1] = pLight->Direction.y;
1900 object->lightDirn[2] = pLight->Direction.z;
1901 object->lightDirn[3] = 1.0;
1904 * opengl-ish and d3d-ish spot lights use too different models for the
1905 * light "intensity" as a function of the angle towards the main light direction,
1906 * so we only can approximate very roughly.
1907 * however spot lights are rather rarely used in games (if ever used at all).
1908 * furthermore if still used, probably nobody pays attention to such details.
1910 if (pLight->Falloff == 0) {
1913 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1915 if (rho < 0.0001) rho = 0.0001f;
1916 object->exponent = -0.3/log(cos(rho/2));
1917 object->cutoff = pLight->Phi*90/M_PI;
1923 FIXME("Unrecognized light type %d\n", pLight->Type);
1926 /* Update the live definitions if the light is currently assigned a glIndex */
1927 if (object->glIndex != -1) {
1928 setup_light(iface, object->glIndex, object);
1933 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
1934 PLIGHTINFOEL *lightInfo = NULL;
1935 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1936 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1938 /* Locate the light in the live lights */
1939 lightInfo = This->stateBlock->lights;
1940 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1942 if (lightInfo == NULL) {
1943 TRACE("Light information requested but light not defined\n");
1944 return D3DERR_INVALIDCALL;
1947 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
1952 * Get / Set Light Enable
1953 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
1955 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
1956 PLIGHTINFOEL *lightInfo = NULL;
1957 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1958 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1960 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1961 if (This->isRecordingState) {
1962 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1963 if (NULL == lightInfo) {
1964 return D3DERR_OUTOFVIDEOMEMORY;
1966 lightInfo->OriginalIndex = Index;
1967 lightInfo->glIndex = -1;
1968 lightInfo->enabledChanged = TRUE;
1970 /* Add to the END of the chain of lights changes to be replayed */
1971 if (This->updateStateBlock->lights == NULL) {
1972 This->updateStateBlock->lights = lightInfo;
1974 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
1975 while (temp->next != NULL) temp=temp->next;
1976 temp->next = lightInfo;
1978 TRACE("Recording... not performing anything more\n");
1982 /* Not recording... So, locate the light in the live lights */
1983 lightInfo = This->stateBlock->lights;
1984 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1986 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1987 if (lightInfo == NULL) {
1988 D3DLIGHT9 lightParms;
1989 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1990 wait until someone confirms it seems to work! */
1991 TRACE("Light enabled requested but light not defined, so defining one!\n");
1992 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1993 lightParms.Diffuse.r = 1.0;
1994 lightParms.Diffuse.g = 1.0;
1995 lightParms.Diffuse.b = 1.0;
1996 lightParms.Diffuse.a = 0.0;
1997 lightParms.Specular.r = 0.0;
1998 lightParms.Specular.g = 0.0;
1999 lightParms.Specular.b = 0.0;
2000 lightParms.Specular.a = 0.0;
2001 lightParms.Ambient.r = 0.0;
2002 lightParms.Ambient.g = 0.0;
2003 lightParms.Ambient.b = 0.0;
2004 lightParms.Ambient.a = 0.0;
2005 lightParms.Position.x = 0.0;
2006 lightParms.Position.y = 0.0;
2007 lightParms.Position.z = 0.0;
2008 lightParms.Direction.x = 0.0;
2009 lightParms.Direction.y = 0.0;
2010 lightParms.Direction.z = 1.0;
2011 lightParms.Range = 0.0;
2012 lightParms.Falloff = 0.0;
2013 lightParms.Attenuation0 = 0.0;
2014 lightParms.Attenuation1 = 0.0;
2015 lightParms.Attenuation2 = 0.0;
2016 lightParms.Theta = 0.0;
2017 lightParms.Phi = 0.0;
2018 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
2020 /* Search for it again! Should be fairly quick as near head of list */
2021 lightInfo = This->stateBlock->lights;
2022 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2023 if (lightInfo == NULL) {
2024 FIXME("Adding default lights has failed dismally\n");
2025 return D3DERR_INVALIDCALL;
2029 /* OK, we now have a light... */
2030 if (Enable == FALSE) {
2032 /* If we are disabling it, check it was enabled, and
2033 still only do something if it has assigned a glIndex (which it should have!) */
2034 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2035 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2037 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2038 checkGLcall("glDisable GL_LIGHT0+Index");
2041 TRACE("Nothing to do as light was not enabled\n");
2043 lightInfo->lightEnabled = FALSE;
2046 /* We are enabling it. If it is enabled, it's really simple */
2047 if (lightInfo->lightEnabled) {
2049 TRACE("Nothing to do as light was enabled\n");
2051 /* If it already has a glIndex, it's still simple */
2052 } else if (lightInfo->glIndex != -1) {
2053 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2054 lightInfo->lightEnabled = TRUE;
2056 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2057 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2060 /* Otherwise got to find space - lights are ordered gl indexes first */
2062 PLIGHTINFOEL *bsf = NULL;
2063 PLIGHTINFOEL *pos = This->stateBlock->lights;
2064 PLIGHTINFOEL *prev = NULL;
2068 /* Try to minimize changes as much as possible */
2069 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2071 /* Try to remember which index can be replaced if necessary */
2072 if (bsf==NULL && pos->lightEnabled == FALSE) {
2073 /* Found a light we can replace, save as best replacement */
2077 /* Step to next space */
2083 /* If we have too many active lights, fail the call */
2084 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2085 FIXME("Program requests too many concurrent lights\n");
2086 return D3DERR_INVALIDCALL;
2088 /* If we have allocated all lights, but not all are enabled,
2089 reuse one which is not enabled */
2090 } else if (Index == This->maxConcurrentLights) {
2091 /* use bsf - Simply swap the new light and the BSF one */
2092 PLIGHTINFOEL *bsfNext = bsf->next;
2093 PLIGHTINFOEL *bsfPrev = bsf->prev;
2096 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2097 if (bsf->prev != NULL) {
2098 bsf->prev->next = lightInfo;
2100 This->stateBlock->lights = lightInfo;
2103 /* If not side by side, lots of chains to update */
2104 if (bsf->next != lightInfo) {
2105 lightInfo->prev->next = bsf;
2106 bsf->next->prev = lightInfo;
2107 bsf->next = lightInfo->next;
2108 bsf->prev = lightInfo->prev;
2109 lightInfo->next = bsfNext;
2110 lightInfo->prev = bsfPrev;
2114 bsf->prev = lightInfo;
2115 bsf->next = lightInfo->next;
2116 lightInfo->next = bsf;
2117 lightInfo->prev = bsfPrev;
2122 glIndex = bsf->glIndex;
2124 lightInfo->glIndex = glIndex;
2125 lightInfo->lightEnabled = TRUE;
2127 /* Finally set up the light in gl itself */
2128 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2130 setup_light(iface, glIndex, lightInfo);
2131 glEnable(GL_LIGHT0 + glIndex);
2132 checkGLcall("glEnable GL_LIGHT0 new setup");
2135 /* If we reached the end of the allocated lights, with space in the
2136 gl lights, setup a new light */
2137 } else if (pos->glIndex == -1) {
2139 /* We reached the end of the allocated gl lights, so already
2140 know the index of the next one! */
2142 lightInfo->glIndex = glIndex;
2143 lightInfo->lightEnabled = TRUE;
2145 /* In an ideal world, it's already in the right place */
2146 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2147 /* No need to move it */
2149 /* Remove this light from the list */
2150 lightInfo->prev->next = lightInfo->next;
2151 if (lightInfo->next != NULL) {
2152 lightInfo->next->prev = lightInfo->prev;
2155 /* Add in at appropriate place (inbetween prev and pos) */
2156 lightInfo->prev = prev;
2157 lightInfo->next = pos;
2159 This->stateBlock->lights = lightInfo;
2161 prev->next = lightInfo;
2164 pos->prev = lightInfo;
2168 /* Finally set up the light in gl itself */
2169 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2171 setup_light(iface, glIndex, lightInfo);
2172 glEnable(GL_LIGHT0 + glIndex);
2173 checkGLcall("glEnable GL_LIGHT0 new setup");
2182 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2184 PLIGHTINFOEL *lightInfo = NULL;
2185 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2186 TRACE("(%p) : for idx(%ld)\n", This, Index);
2188 /* Locate the light in the live lights */
2189 lightInfo = This->stateBlock->lights;
2190 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2192 if (lightInfo == NULL) {
2193 TRACE("Light enabled state requested but light not defined\n");
2194 return D3DERR_INVALIDCALL;
2196 *pEnable = lightInfo->lightEnabled;
2201 * Get / Set Clip Planes
2203 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2204 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2205 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2207 /* Validate Index */
2208 if (Index >= GL_LIMITS(clipplanes)) {
2209 TRACE("Application has requested clipplane this device doesn't support\n");
2210 return D3DERR_INVALIDCALL;
2213 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2214 This->updateStateBlock->set.clipplane[Index] = TRUE;
2215 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2216 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2217 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2218 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2220 /* Handle recording of state blocks */
2221 if (This->isRecordingState) {
2222 TRACE("Recording... not performing anything\n");
2230 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2231 glMatrixMode(GL_MODELVIEW);
2233 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2235 TRACE("Clipplane [%f,%f,%f,%f]\n",
2236 This->updateStateBlock->clipplane[Index][0],
2237 This->updateStateBlock->clipplane[Index][1],
2238 This->updateStateBlock->clipplane[Index][2],
2239 This->updateStateBlock->clipplane[Index][3]);
2240 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2241 checkGLcall("glClipPlane");
2249 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2250 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2251 TRACE("(%p) : for idx %ld\n", This, Index);
2253 /* Validate Index */
2254 if (Index >= GL_LIMITS(clipplanes)) {
2255 TRACE("Application has requested clipplane this device doesn't support\n");
2256 return D3DERR_INVALIDCALL;
2259 pPlane[0] = This->stateBlock->clipplane[Index][0];
2260 pPlane[1] = This->stateBlock->clipplane[Index][1];
2261 pPlane[2] = This->stateBlock->clipplane[Index][2];
2262 pPlane[3] = This->stateBlock->clipplane[Index][3];
2267 * Get / Set Clip Plane Status
2268 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2270 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2271 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2272 FIXME("(%p) : stub\n", This);
2273 if (NULL == pClipStatus) {
2274 return D3DERR_INVALIDCALL;
2276 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2277 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2281 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2282 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2283 FIXME("(%p) : stub\n", This);
2284 if (NULL == pClipStatus) {
2285 return D3DERR_INVALIDCALL;
2287 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2288 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2293 * Get / Set Material
2294 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2296 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2297 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2299 This->updateStateBlock->changed.material = TRUE;
2300 This->updateStateBlock->set.material = TRUE;
2301 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2303 /* Handle recording of state blocks */
2304 if (This->isRecordingState) {
2305 TRACE("Recording... not performing anything\n");
2310 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2311 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2312 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2313 pMaterial->Ambient.b, pMaterial->Ambient.a);
2314 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2315 pMaterial->Specular.b, pMaterial->Specular.a);
2316 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2317 pMaterial->Emissive.b, pMaterial->Emissive.a);
2318 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2320 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2321 checkGLcall("glMaterialfv(GL_AMBIENT)");
2322 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2323 checkGLcall("glMaterialfv(GL_DIFFUSE)");
2325 /* Only change material color if specular is enabled, otherwise it is set to black */
2326 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2327 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2328 checkGLcall("glMaterialfv(GL_SPECULAR");
2330 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2331 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2332 checkGLcall("glMaterialfv(GL_SPECULAR");
2334 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2335 checkGLcall("glMaterialfv(GL_EMISSION)");
2336 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2337 checkGLcall("glMaterialf(GL_SHININESS");
2343 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2344 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2345 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2346 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2347 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2348 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2349 pMaterial->Ambient.b, pMaterial->Ambient.a);
2350 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2351 pMaterial->Specular.b, pMaterial->Specular.a);
2352 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2353 pMaterial->Emissive.b, pMaterial->Emissive.a);
2354 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2362 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2363 UINT BaseVertexIndex) {
2364 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2365 IWineD3DIndexBuffer *oldIdxs;
2367 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2368 oldIdxs = This->updateStateBlock->pIndexData;
2370 This->updateStateBlock->changed.indices = TRUE;
2371 This->updateStateBlock->set.indices = TRUE;
2372 This->updateStateBlock->pIndexData = pIndexData;
2373 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2375 /* Handle recording of state blocks */
2376 if (This->isRecordingState) {
2377 TRACE("Recording... not performing anything\n");
2382 IUnknown *indexBufferParent;
2383 /* Getting the parent causes a addRef... it gets released when the indicies are clear */
2384 IWineD3DIndexBuffer_GetParent(pIndexData, &indexBufferParent);
2387 IUnknown *indexBufferParent;
2388 IWineD3DIndexBuffer_GetParent(oldIdxs, &indexBufferParent);
2389 IUnknown_Release(indexBufferParent);
2390 IUnknown_Release(indexBufferParent);
2395 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2396 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2398 *ppIndexData = This->stateBlock->pIndexData;
2400 /* up ref count on ppindexdata */
2402 IWineD3DIndexBuffer_AddRef(*ppIndexData);
2403 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2404 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
2406 TRACE("(%p) No index data set\n", This);
2408 TRACE("Returning %p %d \n",*ppIndexData, *pBaseVertexIndex);
2414 * Get / Set Viewports
2416 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2417 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2419 TRACE("(%p)\n", This);
2420 This->updateStateBlock->changed.viewport = TRUE;
2421 This->updateStateBlock->set.viewport = TRUE;
2422 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2424 /* Handle recording of state blocks */
2425 if (This->isRecordingState) {
2426 TRACE("Recording... not performing anything\n");
2432 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2433 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2435 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2436 checkGLcall("glDepthRange");
2437 /* Note: GL requires lower left, DirectX supplies upper left */
2438 /* TODO: replace usage of renderTarget with context management */
2439 glViewport(pViewport->X,
2440 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2441 pViewport->Width, pViewport->Height);
2443 checkGLcall("glViewport");
2451 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2452 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2453 TRACE("(%p)\n", This);
2454 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2459 * Get / Set Render States
2460 * TODO: Verify against dx9 definitions
2462 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2464 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2465 DWORD OldValue = This->stateBlock->renderState[State];
2467 /* Simple way of referring to either a DWORD or a 4 byte float */
2473 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2474 This->updateStateBlock->changed.renderState[State] = TRUE;
2475 This->updateStateBlock->set.renderState[State] = TRUE;
2476 This->updateStateBlock->renderState[State] = Value;
2478 /* Handle recording of state blocks */
2479 if (This->isRecordingState) {
2480 TRACE("Recording... not performing anything\n");
2487 case WINED3DRS_FILLMODE :
2488 switch ((D3DFILLMODE) Value) {
2489 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2490 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2491 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2493 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
2495 checkGLcall("glPolygonMode (fillmode)");
2498 case WINED3DRS_LIGHTING :
2500 glEnable(GL_LIGHTING);
2501 checkGLcall("glEnable GL_LIGHTING");
2503 glDisable(GL_LIGHTING);
2504 checkGLcall("glDisable GL_LIGHTING");
2508 case WINED3DRS_ZENABLE :
2509 switch ((D3DZBUFFERTYPE) Value) {
2511 glDisable(GL_DEPTH_TEST);
2512 checkGLcall("glDisable GL_DEPTH_TEST");
2515 glEnable(GL_DEPTH_TEST);
2516 checkGLcall("glEnable GL_DEPTH_TEST");
2519 glEnable(GL_DEPTH_TEST);
2520 checkGLcall("glEnable GL_DEPTH_TEST");
2521 FIXME("W buffer is not well handled\n");
2524 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2528 case WINED3DRS_CULLMODE :
2530 /* If we are culling "back faces with clockwise vertices" then
2531 set front faces to be counter clockwise and enable culling
2533 switch ((D3DCULL) Value) {
2535 glDisable(GL_CULL_FACE);
2536 checkGLcall("glDisable GL_CULL_FACE");
2539 glEnable(GL_CULL_FACE);
2540 checkGLcall("glEnable GL_CULL_FACE");
2541 if (This->renderUpsideDown) {
2543 checkGLcall("glFrontFace GL_CW");
2545 glFrontFace(GL_CCW);
2546 checkGLcall("glFrontFace GL_CCW");
2548 glCullFace(GL_BACK);
2551 glEnable(GL_CULL_FACE);
2552 checkGLcall("glEnable GL_CULL_FACE");
2553 if (This->renderUpsideDown) {
2554 glFrontFace(GL_CCW);
2555 checkGLcall("glFrontFace GL_CCW");
2558 checkGLcall("glFrontFace GL_CW");
2560 glCullFace(GL_BACK);
2563 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2567 case WINED3DRS_SHADEMODE :
2568 switch ((D3DSHADEMODE) Value) {
2570 glShadeModel(GL_FLAT);
2571 checkGLcall("glShadeModel");
2573 case D3DSHADE_GOURAUD:
2574 glShadeModel(GL_SMOOTH);
2575 checkGLcall("glShadeModel");
2577 case D3DSHADE_PHONG:
2578 FIXME("D3DSHADE_PHONG isn't supported?\n");
2581 return D3DERR_INVALIDCALL;
2583 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2587 case WINED3DRS_DITHERENABLE :
2589 glEnable(GL_DITHER);
2590 checkGLcall("glEnable GL_DITHER");
2592 glDisable(GL_DITHER);
2593 checkGLcall("glDisable GL_DITHER");
2597 case WINED3DRS_ZWRITEENABLE :
2600 checkGLcall("glDepthMask");
2603 checkGLcall("glDepthMask");
2607 case WINED3DRS_ZFUNC :
2609 int glParm = GL_LESS;
2611 switch ((D3DCMPFUNC) Value) {
2612 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2613 case D3DCMP_LESS: glParm=GL_LESS; break;
2614 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2615 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2616 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2617 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2618 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2619 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2621 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2623 glDepthFunc(glParm);
2624 checkGLcall("glDepthFunc");
2628 case WINED3DRS_AMBIENT :
2631 D3DCOLORTOGLFLOAT4(Value, col);
2632 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2633 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2634 checkGLcall("glLightModel for MODEL_AMBIENT");
2639 case WINED3DRS_ALPHABLENDENABLE :
2642 checkGLcall("glEnable GL_BLEND");
2644 glDisable(GL_BLEND);
2645 checkGLcall("glDisable GL_BLEND");
2649 case WINED3DRS_SRCBLEND :
2650 case WINED3DRS_DESTBLEND :
2652 int newVal = GL_ZERO;
2654 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2655 case D3DBLEND_ONE : newVal = GL_ONE; break;
2656 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2657 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2658 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2659 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2660 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2661 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2662 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2663 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2664 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2666 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2667 This->srcBlend = newVal;
2668 This->dstBlend = newVal;
2671 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2672 This->srcBlend = newVal;
2673 This->dstBlend = newVal;
2676 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2679 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2680 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2681 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2682 glBlendFunc(This->srcBlend, This->dstBlend);
2684 checkGLcall("glBlendFunc");
2688 case WINED3DRS_ALPHATESTENABLE :
2690 glEnable(GL_ALPHA_TEST);
2691 checkGLcall("glEnable GL_ALPHA_TEST");
2693 glDisable(GL_ALPHA_TEST);
2694 checkGLcall("glDisable GL_ALPHA_TEST");
2698 case WINED3DRS_ALPHAFUNC :
2700 int glParm = GL_LESS;
2701 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2703 switch ((D3DCMPFUNC) Value) {
2704 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2705 case D3DCMP_LESS: glParm = GL_LESS; break;
2706 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2707 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2708 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2709 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2710 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2711 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2713 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2715 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2716 glAlphaFunc(glParm, ref);
2717 This->alphafunc = glParm;
2718 checkGLcall("glAlphaFunc");
2722 case WINED3DRS_ALPHAREF :
2724 int glParm = This->alphafunc;
2727 ref = ((float) Value) / 255.0f;
2728 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2729 glAlphaFunc(glParm, ref);
2730 checkGLcall("glAlphaFunc");
2734 case WINED3DRS_CLIPPLANEENABLE :
2735 case WINED3DRS_CLIPPING :
2737 /* Ensure we only do the changed clip planes */
2738 DWORD enable = 0xFFFFFFFF;
2739 DWORD disable = 0x00000000;
2741 /* If enabling / disabling all */
2742 if (State == WINED3DRS_CLIPPING) {
2744 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2747 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2751 enable = Value & ~OldValue;
2752 disable = ~Value & OldValue;
2755 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2756 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2757 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2758 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2759 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2760 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2762 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2763 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2764 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2765 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2766 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2767 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2769 /** update clipping status */
2771 This->stateBlock->clip_status.ClipUnion = 0;
2772 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
2774 This->stateBlock->clip_status.ClipUnion = 0;
2775 This->stateBlock->clip_status.ClipIntersection = 0;
2780 case WINED3DRS_BLENDOP :
2782 int glParm = GL_FUNC_ADD;
2784 switch ((D3DBLENDOP) Value) {
2785 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2786 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2787 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2788 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2789 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2791 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2793 TRACE("glBlendEquation(%x)\n", glParm);
2794 glBlendEquation(glParm);
2795 checkGLcall("glBlendEquation");
2799 case WINED3DRS_TEXTUREFACTOR :
2803 /* Note the texture color applies to all textures whereas
2804 GL_TEXTURE_ENV_COLOR applies to active only */
2806 D3DCOLORTOGLFLOAT4(Value, col);
2807 /* Set the default alpha blend color */
2808 glBlendColor(col[0], col[1], col[2], col[3]);
2809 checkGLcall("glBlendColor");
2811 /* And now the default texture color as well */
2812 for (i = 0; i < GL_LIMITS(textures); i++) {
2814 /* Note the D3DRS value applies to all textures, but GL has one
2815 per texture, so apply it now ready to be used! */
2816 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2819 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2822 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2823 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2828 case WINED3DRS_SPECULARENABLE :
2830 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2831 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2832 specular color. This is wrong:
2833 Separate specular color means the specular colour is maintained separately, whereas
2834 single color means it is merged in. However in both cases they are being used to
2836 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2837 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2841 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2842 checkGLcall("glMaterialfv");
2843 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2844 glEnable(GL_COLOR_SUM_EXT);
2846 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2848 checkGLcall("glEnable(GL_COLOR_SUM)");
2850 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2852 /* for the case of enabled lighting: */
2853 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2854 checkGLcall("glMaterialfv");
2856 /* for the case of disabled lighting: */
2857 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2858 glDisable(GL_COLOR_SUM_EXT);
2860 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2862 checkGLcall("glDisable(GL_COLOR_SUM)");
2867 case WINED3DRS_STENCILENABLE :
2869 glEnable(GL_STENCIL_TEST);
2870 checkGLcall("glEnable GL_STENCIL_TEST");
2872 glDisable(GL_STENCIL_TEST);
2873 checkGLcall("glDisable GL_STENCIL_TEST");
2877 case WINED3DRS_STENCILFUNC :
2879 int glParm = GL_ALWAYS;
2880 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2881 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2883 switch ((D3DCMPFUNC) Value) {
2884 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2885 case D3DCMP_LESS: glParm=GL_LESS; break;
2886 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2887 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2888 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2889 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2890 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2891 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2893 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2895 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2896 This->stencilfunc = glParm;
2897 glStencilFunc(glParm, ref, mask);
2898 checkGLcall("glStencilFunc");
2902 case WINED3DRS_STENCILREF :
2904 int glParm = This->stencilfunc;
2906 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2909 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2910 glStencilFunc(glParm, ref, mask);
2911 checkGLcall("glStencilFunc");
2915 case WINED3DRS_STENCILMASK :
2917 int glParm = This->stencilfunc;
2918 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2919 GLuint mask = Value;
2921 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2922 glStencilFunc(glParm, ref, mask);
2923 checkGLcall("glStencilFunc");
2927 case WINED3DRS_STENCILFAIL :
2933 fail = StencilOp(Value);
2934 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2935 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2936 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2937 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2939 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2940 glStencilOp(fail, zfail, zpass);
2941 checkGLcall("glStencilOp(fail, zfail, zpass);");
2944 case WINED3DRS_STENCILZFAIL :
2950 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2951 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2952 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2953 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2954 zfail = StencilOp(Value);
2956 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2957 glStencilOp(fail, zfail, zpass);
2958 checkGLcall("glStencilOp(fail, zfail, zpass);");
2961 case WINED3DRS_STENCILPASS :
2967 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2968 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2969 zpass = StencilOp(Value);
2970 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2971 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2973 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2974 glStencilOp(fail, zfail, zpass);
2975 checkGLcall("glStencilOp(fail, zfail, zpass);");
2979 case WINED3DRS_STENCILWRITEMASK :
2981 glStencilMask(Value);
2982 TRACE("glStencilMask(%lu)\n", Value);
2983 checkGLcall("glStencilMask");
2987 case WINED3DRS_FOGENABLE :
2989 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2991 checkGLcall("glEnable GL_FOG");
2994 checkGLcall("glDisable GL_FOG");
2999 case WINED3DRS_RANGEFOGENABLE :
3002 TRACE("Enabled RANGEFOG");
3004 TRACE("Disabled RANGEFOG");
3009 case WINED3DRS_FOGCOLOR :
3012 D3DCOLORTOGLFLOAT4(Value, col);
3013 /* Set the default alpha blend color */
3014 glFogfv(GL_FOG_COLOR, &col[0]);
3015 checkGLcall("glFog GL_FOG_COLOR");
3019 case WINED3DRS_FOGTABLEMODE :
3021 glHint(GL_FOG_HINT, GL_NICEST);
3023 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3024 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3025 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3026 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3028 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3030 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3031 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3036 case WINED3DRS_FOGVERTEXMODE :
3038 glHint(GL_FOG_HINT, GL_FASTEST);
3040 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3041 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3042 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3043 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3045 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3047 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3048 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
3053 case WINED3DRS_FOGSTART :
3056 glFogfv(GL_FOG_START, &tmpvalue.f);
3057 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3058 TRACE("Fog Start == %f\n", tmpvalue.f);
3062 case WINED3DRS_FOGEND :
3065 glFogfv(GL_FOG_END, &tmpvalue.f);
3066 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3067 TRACE("Fog End == %f\n", tmpvalue.f);
3071 case WINED3DRS_FOGDENSITY :
3074 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3075 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3079 case WINED3DRS_VERTEXBLEND :
3081 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3082 TRACE("Vertex Blending state to %ld\n", Value);
3086 case WINED3DRS_TWEENFACTOR :
3089 This->updateStateBlock->tween_factor = tmpvalue.f;
3090 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3094 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
3096 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3100 case WINED3DRS_COLORVERTEX :
3101 case WINED3DRS_DIFFUSEMATERIALSOURCE :
3102 case WINED3DRS_SPECULARMATERIALSOURCE :
3103 case WINED3DRS_AMBIENTMATERIALSOURCE :
3104 case WINED3DRS_EMISSIVEMATERIALSOURCE :
3106 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3108 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3109 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3110 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3111 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3112 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3113 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3115 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3116 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3117 Parm = GL_AMBIENT_AND_DIFFUSE;
3121 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3123 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3125 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3132 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3134 This->tracking_color = NEEDS_TRACKING;
3135 This->tracking_parm = Parm;
3139 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3144 case WINED3DRS_LINEPATTERN :
3150 tmppattern.d = Value;
3152 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3154 if (tmppattern.lp.wRepeatFactor) {
3155 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3156 checkGLcall("glLineStipple(repeat, linepattern)");
3157 glEnable(GL_LINE_STIPPLE);
3158 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3160 glDisable(GL_LINE_STIPPLE);
3161 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3166 case WINED3DRS_ZBIAS : /* D3D8 only */
3170 TRACE("ZBias value %f\n", tmpvalue.f);
3171 glPolygonOffset(0, -tmpvalue.f);
3172 checkGLcall("glPolygonOffset(0, -Value)");
3173 glEnable(GL_POLYGON_OFFSET_FILL);
3174 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3175 glEnable(GL_POLYGON_OFFSET_LINE);
3176 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3177 glEnable(GL_POLYGON_OFFSET_POINT);
3178 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3180 glDisable(GL_POLYGON_OFFSET_FILL);
3181 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3182 glDisable(GL_POLYGON_OFFSET_LINE);
3183 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3184 glDisable(GL_POLYGON_OFFSET_POINT);
3185 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3190 case WINED3DRS_NORMALIZENORMALS :
3192 glEnable(GL_NORMALIZE);
3193 checkGLcall("glEnable(GL_NORMALIZE);");
3195 glDisable(GL_NORMALIZE);
3196 checkGLcall("glDisable(GL_NORMALIZE);");
3200 case WINED3DRS_POINTSIZE :
3202 TRACE("Set point size to %f\n", tmpvalue.f);
3203 glPointSize(tmpvalue.f);
3204 checkGLcall("glPointSize(...);");
3207 case WINED3DRS_POINTSIZE_MIN :
3208 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3210 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3211 checkGLcall("glPointParameterfEXT(...);");
3213 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3217 case WINED3DRS_POINTSIZE_MAX :
3218 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3220 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3221 checkGLcall("glPointParameterfEXT(...);");
3223 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3227 case WINED3DRS_POINTSCALE_A :
3228 case WINED3DRS_POINTSCALE_B :
3229 case WINED3DRS_POINTSCALE_C :
3230 case WINED3DRS_POINTSCALEENABLE :
3232 /* If enabled, supply the parameters, otherwise fall back to defaults */
3233 if (This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3234 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3235 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]);
3236 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]);
3237 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]);
3239 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3240 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3241 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3243 TRACE("WINED3DRS_POINTSCALEENABLE not supported on this opengl\n");
3246 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3247 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3248 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3249 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3251 TRACE("WINED3DRS_POINTSCALEENABLE not supported, but not on either\n");
3257 case WINED3DRS_COLORWRITEENABLE :
3259 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3260 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3261 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3262 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3263 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3264 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3265 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3266 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3267 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3268 checkGLcall("glColorMask(...)");
3272 case WINED3DRS_LOCALVIEWER :
3274 GLint state = (Value) ? 1 : 0;
3275 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3276 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3280 case WINED3DRS_LASTPIXEL :
3283 TRACE("Last Pixel Drawing Enabled\n");
3285 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3290 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3293 TRACE("Software Processing Enabled\n");
3295 TRACE("Software Processing Disabled\n");
3300 /** not supported */
3301 case WINED3DRS_ZVISIBLE :
3304 return D3DERR_INVALIDCALL;
3307 /* Unhandled yet...! */
3308 case WINED3DRS_EDGEANTIALIAS :
3309 case WINED3DRS_WRAP0 :
3310 case WINED3DRS_WRAP1 :
3311 case WINED3DRS_WRAP2 :
3312 case WINED3DRS_WRAP3 :
3313 case WINED3DRS_WRAP4 :
3314 case WINED3DRS_WRAP5 :
3315 case WINED3DRS_WRAP6 :
3316 case WINED3DRS_WRAP7 :
3318 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
3319 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
3320 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
3321 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
3322 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
3324 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
3326 TRACE("(%p)->(%d,%ld) Texture wraping not yet supported\n",This, State, Value);
3328 case WINED3DRS_POINTSPRITEENABLE :
3329 case WINED3DRS_MULTISAMPLEANTIALIAS :
3330 case WINED3DRS_MULTISAMPLEMASK :
3331 case WINED3DRS_PATCHEDGESTYLE :
3332 case WINED3DRS_PATCHSEGMENTS :
3333 case WINED3DRS_DEBUGMONITORTOKEN :
3334 case WINED3DRS_POSITIONORDER :
3335 case WINED3DRS_NORMALORDER :
3336 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3337 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3340 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3348 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3349 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3350 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3351 *pValue = This->stateBlock->renderState[State];
3356 * Get / Set Sampler States
3357 * TODO: Verify against dx9 definitions
3360 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3361 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3363 * SetSampler is designed to allow for more than the standard up to 8 textures
3364 * and Geforce has stopped supporting more than 6 standard textures in openGL.
3365 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3367 * http://developer.nvidia.com/object/General_FAQ.html#t6
3369 * There are two new settings for GForce
3371 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3372 * and the texture one:
3373 * GL_MAX_TEXTURE_COORDS_ARB.
3374 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3376 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
3377 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
3379 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
3380 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE, Sampler, Type);
3381 return D3DERR_INVALIDCALL;
3383 TRACE("Setting sampler %ld %d to %ld \n", Sampler, Type, Value);
3384 This->updateStateBlock->samplerState[Sampler][Type] = Value;
3386 /* Handle recording of state blocks */
3387 if (This->isRecordingState) {
3388 TRACE("Recording... not performing anything\n");
3395 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3396 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3397 /** TODO: check that sampler is in range **/
3398 *Value = This->updateStateBlock->samplerState[Sampler][Type];
3399 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
3404 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3405 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3408 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3409 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3410 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3416 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3417 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3418 GLint scissorBox[4];
3421 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3422 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
3423 pRect->left = scissorBox[1];
3424 pRect->top = scissorBox[2];
3425 pRect->right = scissorBox[1] + scissorBox[3];
3426 pRect->bottom = scissorBox[2] + scissorBox[4];
3427 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3432 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3433 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3435 TRACE("(%p) : pDecl=%p\n", This, pDecl);
3437 /* TODO: what about recording stateblocks? */
3438 if (NULL != pDecl) {
3439 IWineD3DVertexDeclaration_AddRef(pDecl);
3441 if (NULL != This->updateStateBlock->vertexDecl) {
3442 IWineD3DVertexDeclaration_Release(This->updateStateBlock->vertexDecl);
3444 This->updateStateBlock->vertexDecl = pDecl;
3445 This->updateStateBlock->changed.vertexDecl = TRUE;
3446 This->updateStateBlock->set.vertexDecl = TRUE;
3450 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3451 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3453 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3455 *ppDecl = This->updateStateBlock->vertexDecl;
3456 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3460 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
3461 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3462 IWineD3DVertexShader *oldShader = This->updateStateBlock->vertexShader;
3464 This->updateStateBlock->vertexShader = pShader;
3465 This->updateStateBlock->changed.vertexShader = TRUE;
3466 This->updateStateBlock->set.vertexShader = TRUE;
3468 if (This->isRecordingState) {
3469 TRACE("Recording... not performing anything\n");
3473 if (pShader != NULL) {
3474 IUnknown *newVertexShaderParent;
3475 /* GetParent will add a ref, so leave it hanging until the vertex buffer is cleared */
3476 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3477 IWineD3DVertexShader_GetParent(pShader, &newVertexShaderParent);
3479 TRACE("Clear down the shader\n");
3481 if (oldShader != NULL) {
3482 IUnknown *oldVertexShaderParent;
3483 IWineD3DVertexShader_GetParent(oldShader, &oldVertexShaderParent);
3484 IUnknown_Release(oldVertexShaderParent);
3485 IUnknown_Release(oldVertexShaderParent);
3488 * TODO: merge HAL shaders context switching from prototype
3493 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
3494 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3496 if (NULL == ppShader) {
3497 return D3DERR_INVALIDCALL;
3499 *ppShader = This->stateBlock->vertexShader;
3500 if( NULL != *ppShader)
3501 IWineD3DVertexShader_AddRef(*ppShader);
3503 TRACE("(%p) : returning %p\n", This, *ppShader);
3507 #define GET_SHADER_CONSTANT(_vertexshaderconstant, _count, _sizecount) \
3508 int count = min(_count, MAX_VSHADER_CONSTANTS - (StartRegister + 1)); \
3509 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3510 return D3DERR_INVALIDCALL; \
3511 memcpy(pConstantData, This->updateStateBlock->_vertexshaderconstant + (StartRegister * _sizecount), count * (sizeof(*pConstantData) * _sizecount));
3513 #define SET_SHADER_CONSTANT(_vertexshaderconstant, _count, _sizecount) \
3514 int count = min(_count, MAX_VSHADER_CONSTANTS - (StartRegister + 1)); \
3515 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3516 return D3DERR_INVALIDCALL; \
3517 memcpy(This->updateStateBlock->_vertexshaderconstant + (StartRegister * _sizecount), pConstantData, count * (sizeof(*pConstantData) * _sizecount)); \
3518 This->updateStateBlock->changed.vertexShader = TRUE; \
3519 This->updateStateBlock->set.vertexShader = TRUE;
3521 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
3522 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3523 static BOOL showFixmes = TRUE;
3524 SET_SHADER_CONSTANT(vertexShaderConstantB, BoolCount, 1);
3525 #if 0 /* TODO: a bitmasp to say which constant type we should load */
3526 memset(This->updateStateBlock->vsibfBitmap + StartRegister, WINESHADER_CONSTANTB, BoolCount);
3528 /* clean out the other constants? */
3529 if(showFixmes || TRUE) {
3530 FIXME("(%p) : stub\n", This);
3536 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
3537 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3538 static BOOL showFixmes = TRUE;
3539 #if 0 /* TODO: a bitmasp to say which constant type we should load */
3540 for (i = 0; i < BoolCount; i++ ) {
3541 if (This->updateStateBlock->vsibfBitmap[StartRegister + i] != WINESHADER_CONSTANTB) {
3542 /* the constant for this register isn't a boolean */
3543 return D3DERR_INVALIDCALL;
3547 GET_SHADER_CONSTANT(vertexShaderConstantB, BoolCount, 1);
3548 if(showFixmes || TRUE) {
3549 FIXME("(%p) : stub\n", This);
3555 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
3556 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3557 static BOOL showFixmes = TRUE;
3558 #if 0 /* TODO: a bitmasp to say which constant type we should load */
3559 memset(This->updateStateBlock->vsibfBitmap + StartRegister, WINESHADER_CONSTANTI, Vector4iCount);
3561 SET_SHADER_CONSTANT(vertexShaderConstantI, Vector4iCount, 4);
3562 /* clean out the other constants? */
3563 if(showFixmes || TRUE) {
3564 FIXME("(%p) : stub\n", This);
3570 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
3571 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3572 static BOOL showFixmes = TRUE;
3573 #if 0 /* TODO: a bitmap to say which constant type we should load */
3574 for (i = 0; i < Vector4iCount; i++ ) {
3575 if (This->updateStateBlock->vsibfBitmap[StartRegister + i] != WINESHADER_CONSTANTI) {
3576 /* the constant for this register isn't a boolean */
3577 return D3DERR_INVALIDCALL;
3581 GET_SHADER_CONSTANT(vertexShaderConstantI, Vector4iCount, 4);
3582 if(showFixmes || TRUE) {
3583 FIXME("(%p) : stub\n", This);
3589 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
3590 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3591 static BOOL showFixmes = TRUE;
3592 #if 0 /* TODO: a bitmasp to say which constant type we should load */
3593 memset(This->updateStateBlock->vsibfBitmap + StartRegister, WINESHADER_CONSTANTF, Vector4fCount);
3595 SET_SHADER_CONSTANT(vertexShaderConstantF, Vector4fCount, 4);
3596 /* clean out the other constants? */
3598 TRACE("(%p) : ConstantF isn't intergrated properly with the other constants.\n", This);
3604 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
3605 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3606 static BOOL showFixmes = TRUE;
3607 #if 0 /* TODO: a bitmap to say which constant type we should load */
3608 for (i = 0; i < Vector4fCount; i++ ) {
3609 if (This->updateStateBlock->vsibfBitmap[StartRegister + i] != WINESHADER_CONSTANTF) {
3610 /* the constant for this register isn't a boolean */
3611 return D3DERR_INVALIDCALL;
3615 GET_SHADER_CONSTANT(vertexShaderConstantF, Vector4fCount, 4);
3617 TRACE("(%p) : ConstantF isn't intergrated properly with the other constants.\n", This);
3623 #undef SET_SHADER_CONSTANT
3624 #undef GET_SHADER_CONSTANT
3627 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
3628 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3629 TRACE("(%p) : stub\n", This);
3633 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3634 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3635 TRACE("(%p) : stub\n", This);
3640 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
3641 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3642 TRACE("(%p) : stub\n", This);
3646 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
3647 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3648 TRACE("(%p) : stub\n", This);
3652 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
3653 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3654 TRACE("(%p) : stub\n", This);
3658 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
3659 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3660 TRACE("(%p) : stub\n", This);
3664 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
3665 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3666 TRACE("(%p) : stub\n", This);
3670 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
3671 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3672 TRACE("(%p) : stub\n", This);
3676 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
3677 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3678 FIXME("(%p) : stub\n", This);
3683 * Apply / Get / Set Texture Stage States
3684 * TODO: Verify against dx9 definitions
3687 /* 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 */
3688 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
3689 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3690 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
3691 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3693 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3695 /* Check that the stage is within limits */
3696 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
3697 TRACE("Attempt to access invalid texture rejected\n");
3704 case WINED3DTSS_ALPHAOP :
3705 case WINED3DTSS_COLOROP :
3708 if ((Value == D3DTOP_DISABLE) && (Type == WINED3DTSS_COLOROP)) {
3709 /* TODO: Disable by making this and all later levels disabled */
3710 glDisable(GL_TEXTURE_1D);
3711 checkGLcall("Disable GL_TEXTURE_1D");
3712 glDisable(GL_TEXTURE_2D);
3713 checkGLcall("Disable GL_TEXTURE_2D");
3714 glDisable(GL_TEXTURE_3D);
3715 checkGLcall("Disable GL_TEXTURE_3D");
3716 break; /* Don't bother setting the texture operations */
3718 /* Enable only the appropriate texture dimension */
3719 if (Type == WINED3DTSS_COLOROP) {
3720 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3721 glEnable(GL_TEXTURE_1D);
3722 checkGLcall("Enable GL_TEXTURE_1D");
3724 glDisable(GL_TEXTURE_1D);
3725 checkGLcall("Disable GL_TEXTURE_1D");
3727 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3728 if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
3729 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
3730 checkGLcall("Enable GL_TEXTURE_2D");
3732 glEnable(GL_TEXTURE_2D);
3733 checkGLcall("Enable GL_TEXTURE_2D");
3736 glDisable(GL_TEXTURE_2D);
3737 checkGLcall("Disable GL_TEXTURE_2D");
3739 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3740 glEnable(GL_TEXTURE_3D);
3741 checkGLcall("Enable GL_TEXTURE_3D");
3743 glDisable(GL_TEXTURE_3D);
3744 checkGLcall("Disable GL_TEXTURE_3D");
3746 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3747 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3748 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3750 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3751 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3755 /* Drop through... (Except disable case) */
3756 case WINED3DTSS_COLORARG0 :
3757 case WINED3DTSS_COLORARG1 :
3758 case WINED3DTSS_COLORARG2 :
3759 case WINED3DTSS_ALPHAARG0 :
3760 case WINED3DTSS_ALPHAARG1 :
3761 case WINED3DTSS_ALPHAARG2 :
3763 BOOL isAlphaArg = (Type == WINED3DTSS_ALPHAOP || Type == WINED3DTSS_ALPHAARG1 ||
3764 Type == WINED3DTSS_ALPHAARG2 || Type == WINED3DTSS_ALPHAARG0);
3766 set_tex_op(iface, TRUE, Stage, This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAOP],
3767 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG1],
3768 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG2],
3769 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG0]);
3771 set_tex_op(iface, FALSE, Stage, This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP],
3772 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG1],
3773 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG2],
3774 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG0]);
3780 case WINED3DTSS_ADDRESSW :
3782 GLint wrapParm = GL_REPEAT;
3785 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3786 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3787 case D3DTADDRESS_BORDER:
3789 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3790 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3792 /* FIXME: Not right, but better */
3793 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3794 wrapParm = GL_REPEAT;
3798 case D3DTADDRESS_MIRROR:
3800 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3801 wrapParm = GL_MIRRORED_REPEAT_ARB;
3803 /* Unsupported in OpenGL pre-1.4 */
3804 FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3805 wrapParm = GL_REPEAT;
3809 case D3DTADDRESS_MIRRORONCE:
3811 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3812 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3814 FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3815 wrapParm = GL_REPEAT;
3821 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3822 wrapParm = GL_REPEAT;
3825 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
3826 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3827 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->textureState[Stage][Type] = Value;
4033 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4034 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4035 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4036 *pValue = This->updateStateBlock->textureState[Stage][Type];
4043 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4045 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4046 IWineD3DBaseTexture *oldTexture;
4048 oldTexture = This->updateStateBlock->textures[Stage];
4049 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
4051 #if 0 /* TODO: check so vertex textures */
4052 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
4053 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
4058 /* Reject invalid texture units */
4059 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4060 WARN("Attempt to access invalid texture rejected\n");
4061 return D3DERR_INVALIDCALL;
4064 oldTexture = This->updateStateBlock->textures[Stage];
4065 TRACE("GL_LIMITS %d\n",GL_LIMITS(textures));
4066 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
4068 This->updateStateBlock->set.textures[Stage] = TRUE;
4069 This->updateStateBlock->changed.textures[Stage] = TRUE;
4070 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
4071 This->updateStateBlock->textures[Stage] = pTexture;
4073 /* Handle recording of state blocks */
4074 if (This->isRecordingState) {
4075 TRACE("Recording... not performing anything\n");
4079 /** NOTE: MSDN says that setTexture increases the reference count,
4080 * and the the application nust set the texture back to null (or have a leaky application),
4081 * This means we should pass the refcount upto the parent
4082 *******************************/
4083 if (NULL != This->updateStateBlock->textures[Stage]) {
4084 IUnknown *textureParent;
4085 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[Stage], (IUnknown **)&textureParent);
4086 /** NOTE: GetParent will increase the ref count for me, I won't clean up until the texture is set to NULL **/
4089 if (NULL != oldTexture) {
4090 IUnknown *textureParent;
4091 IWineD3DBaseTexture_GetParent(oldTexture, (IUnknown **)&textureParent);
4092 IUnknown_Release(textureParent);
4093 IUnknown_Release(textureParent); /** NOTE: Twice because GetParent adds a ref **/
4100 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4101 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4102 TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */) \n", This, Stage, ppTexture);
4104 /* Reject invalid texture units */
4105 if (Stage >= GL_LIMITS(textures)) {
4106 TRACE("Attempt to access invalid texture rejected\n");
4107 return D3DERR_INVALIDCALL;
4109 *ppTexture=This->updateStateBlock->textures[Stage];
4111 IWineD3DBaseTexture_AddRef(*ppTexture);
4113 return D3DERR_INVALIDCALL;
4120 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type,
4121 IWineD3DSurface **ppBackBuffer) {
4122 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4123 IWineD3DSwapChain *swapChain;
4126 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4128 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4130 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4131 IWineD3DSwapChain_Release(swapChain);
4133 *ppBackBuffer = NULL;
4138 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4139 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4140 WARN("(%p) : stub, calling idirect3d for now\n", This);
4141 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4144 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
4145 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4146 IWineD3DSwapChain *swapChain;
4149 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4151 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4152 IWineD3DSwapChain_Release(swapChain);
4154 FIXME("(%p) Error getting display mode\n", This);
4159 * Stateblock related functions
4162 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4163 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4164 IWineD3DStateBlockImpl *object;
4165 TRACE("(%p)", This);
4166 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4167 if (NULL == object ) {
4168 FIXME("(%p)Error allocating memory for stateblock\n", This);
4169 return E_OUTOFMEMORY;
4171 TRACE("(%p) creted object %p\n", This, object);
4172 object->wineD3DDevice= This;
4173 /** FIXME: object->parent = parent; **/
4174 object->parent = NULL;
4175 object->blockType = WINED3DSBT_ALL;
4177 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
4179 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4180 This->updateStateBlock = object;
4181 This->isRecordingState = TRUE;
4183 TRACE("(%p) recording stateblock %p\n",This , object);
4187 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4188 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4190 if (!This->isRecordingState) {
4191 FIXME("(%p) not recording! returning error\n", This);
4192 *ppStateBlock = NULL;
4193 return D3DERR_INVALIDCALL;
4196 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4197 This->isRecordingState = FALSE;
4198 This->updateStateBlock = This->stateBlock;
4199 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4200 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4201 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4206 * Scene related functions
4208 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4209 /* At the moment we have no need for any functionality at the beginning
4211 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4212 TRACE("(%p) : stub\n", This);
4216 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4217 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4218 TRACE("(%p)\n", This);
4220 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4222 checkGLcall("glFlush");
4224 TRACE("End Scene\n");
4225 if(This->renderTarget != NULL) {
4227 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4228 IUnknown *targetContainer = NULL;
4229 if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
4230 || D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
4231 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
4232 /** always dirtify for now. we must find a better way to see that surface have been modified
4233 (Modifications should will only occur via draw-primitive, but we do need better locking
4234 switching to render-to-texture should remove the overhead though.
4236 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4237 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
4238 IWineD3DSurface_PreLoad(This->renderTarget);
4239 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4240 IUnknown_Release(targetContainer);
4243 This->sceneEnded = TRUE;
4248 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4249 CONST RECT* pSourceRect, CONST RECT* pDestRect,
4250 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4251 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4252 IWineD3DSwapChain *swapChain = NULL;
4254 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4256 TRACE("(%p) Presenting the frame\n", This);
4258 for(i = 0 ; i < swapchains ; i ++) {
4260 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4261 TRACE("presentinng chain %d, %p\n", i, swapChain);
4262 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4263 IWineD3DSwapChain_Release(swapChain);
4269 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4270 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4271 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4273 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4274 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4275 when the depth-buffer format does not contain stencil buffer information, this method fails. */
4276 GLbitfield glMask = 0;
4277 GLboolean old_ztest;
4278 GLfloat old_z_clear_value;
4279 GLint old_stencil_clear_value;
4280 GLfloat old_color_clear_value[4];
4282 CONST D3DRECT* curRect;
4284 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4285 Count, pRects, Flags, Z, Stencil);
4289 glEnable(GL_SCISSOR_TEST);
4290 checkGLcall("glEnable GL_SCISSOR_TEST");
4292 if (Count > 0 && pRects) {
4298 /* Only set the values up once, as they are not changing */
4299 if (Flags & D3DCLEAR_STENCIL) {
4300 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4301 glClearStencil(Stencil);
4302 checkGLcall("glClearStencil");
4303 glMask = glMask | GL_STENCIL_BUFFER_BIT;
4304 glStencilMask(0xFFFFFFFF);
4307 if (Flags & D3DCLEAR_ZBUFFER) {
4308 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4309 glDepthMask(GL_TRUE);
4310 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4312 checkGLcall("glClearDepth");
4313 glMask = glMask | GL_DEPTH_BUFFER_BIT;
4316 if (Flags & D3DCLEAR_TARGET) {
4317 TRACE("Clearing screen with glClear to color %lx\n", Color);
4318 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4319 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
4320 ((Color >> 8) & 0xFF) / 255.0f,
4321 ((Color >> 0) & 0xFF) / 255.0f,
4322 ((Color >> 24) & 0xFF) / 255.0f);
4323 checkGLcall("glClearColor");
4325 /* Clear ALL colors! */
4326 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4327 glMask = glMask | GL_COLOR_BUFFER_BIT;
4330 /* Now process each rect in turn */
4331 for (i = 0; i < Count || i == 0; i++) {
4334 /* Note gl uses lower left, width/height */
4335 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4336 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4337 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4338 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4339 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4340 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4341 checkGLcall("glScissor");
4343 glScissor(This->stateBlock->viewport.X,
4344 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
4345 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4346 This->stateBlock->viewport.Width,
4347 This->stateBlock->viewport.Height);
4348 checkGLcall("glScissor");
4351 /* Clear the selected rectangle (or full screen) */
4353 checkGLcall("glClear");
4355 /* Step to the next rectangle */
4356 if (curRect) curRect = curRect + sizeof(D3DRECT);
4359 /* Restore the old values (why..?) */
4360 if (Flags & D3DCLEAR_STENCIL) {
4361 glClearStencil(old_stencil_clear_value);
4362 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4364 if (Flags & D3DCLEAR_ZBUFFER) {
4365 glDepthMask(old_ztest);
4366 glClearDepth(old_z_clear_value);
4368 if (Flags & D3DCLEAR_TARGET) {
4369 glClearColor(old_color_clear_value[0],
4370 old_color_clear_value[1],
4371 old_color_clear_value[2],
4372 old_color_clear_value[3]);
4373 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4374 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4375 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4376 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4379 glDisable(GL_SCISSOR_TEST);
4380 checkGLcall("glDisable");
4389 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4390 UINT PrimitiveCount) {
4392 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4393 This->stateBlock->streamIsUP = FALSE;
4395 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4396 debug_d3dprimitivetype(PrimitiveType),
4397 StartVertex, PrimitiveCount);
4398 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
4399 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
4405 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4406 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4407 D3DPRIMITIVETYPE PrimitiveType,
4408 INT baseVIndex, UINT minIndex,
4409 UINT NumVertices, UINT startIndex, UINT primCount) {
4411 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4413 IWineD3DIndexBuffer *pIB;
4414 D3DINDEXBUFFER_DESC IdxBufDsc;
4416 pIB = This->stateBlock->pIndexData;
4417 This->stateBlock->streamIsUP = FALSE;
4419 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d \n", This,
4420 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4421 minIndex, NumVertices, startIndex, baseVIndex, primCount);
4423 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4424 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4430 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
4431 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
4436 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4437 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4438 UINT VertexStreamZeroStride) {
4439 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4441 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4442 debug_d3dprimitivetype(PrimitiveType),
4443 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4445 if (This->stateBlock->streamSource[0] != NULL) {
4446 IUnknown *vertexBufferParent;
4447 IWineD3DVertexBuffer_GetParent(This->stateBlock->streamSource[0], &vertexBufferParent);
4448 IUnknown_Release(vertexBufferParent);
4449 IUnknown_Release(vertexBufferParent);
4452 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4453 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4454 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4455 This->stateBlock->streamIsUP = TRUE;
4457 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
4458 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
4459 /* stream zero settings set to null at end, as per the msdn
4460 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
4462 This->stateBlock->streamStride[0] = 0;
4463 This->stateBlock->streamSource[0] = NULL;
4465 /*stream zero settings set to null at end, as per the msdn */
4469 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4470 UINT MinVertexIndex, UINT NumVertices,
4471 UINT PrimitiveCount, CONST void* pIndexData,
4472 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4473 UINT VertexStreamZeroStride) {
4475 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4477 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4478 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4479 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
4480 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4482 if (IndexDataFormat == WINED3DFMT_INDEX16) {
4488 if (This->stateBlock->streamSource[0] != NULL) {
4489 IUnknown *vertexBufferParent;
4490 IWineD3DVertexBuffer_GetParent(This->stateBlock->streamSource[0], &vertexBufferParent);
4491 This->stateBlock->streamSource[0] = NULL;
4492 IUnknown_Release(vertexBufferParent);
4493 IUnknown_Release(vertexBufferParent);
4496 if (This->stateBlock->pIndexData) {
4497 IUnknown *indexBufferParent;
4498 IWineD3DIndexBuffer_GetParent(This->stateBlock->pIndexData, &indexBufferParent);
4499 This->stateBlock->pIndexData = NULL;
4500 IUnknown_Release(indexBufferParent);
4501 IUnknown_Release(indexBufferParent);
4504 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4505 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4506 This->stateBlock->streamIsUP = TRUE;
4507 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4509 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
4510 /* stream zero settings set to null at end as per the msdn
4511 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
4514 /* stream zero settings set to null at end as per the msdn */
4515 This->stateBlock->streamSource[0] = NULL;
4516 This->stateBlock->streamStride[0] = 0;
4521 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4522 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
4523 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4524 D3DRESOURCETYPE sourceType;
4525 D3DRESOURCETYPE destinationType;
4526 IWineD3DTextureImpl *pDestTexture = (IWineD3DTextureImpl *)pDestinationTexture;
4527 IWineD3DTextureImpl *pSrcTexture = (IWineD3DTextureImpl *)pSourceTexture;
4530 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
4531 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
4532 if(sourceType != D3DRTYPE_TEXTURE && destinationType != D3DRTYPE_TEXTURE){
4533 FIXME("(%p) Only D3DRTYPE_TEXTURE to D3DRTYPE_TEXTURE supported\n", This);
4534 return D3DERR_INVALIDCALL;
4536 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
4538 /** TODO: Get rid of the casts to IWineD3DBaseTextureImpl
4539 repalce surfaces[x] with GetSurfaceLevel, or GetCubeMapSurface etc..
4540 think about moving the code into texture, and adding a member to base texture to occomplish this **/
4542 /* Make sure that the destination texture is loaded */
4543 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
4544 TRACE("Loading source texture\n");
4546 if(pSrcTexture->surfaces[0] == NULL || pDestTexture->surfaces[0] == NULL){
4547 FIXME("(%p) Texture src %p or dest %p has not surface %p %p\n", This, pSrcTexture, pDestTexture,
4548 pSrcTexture->surfaces[0], pDestTexture->surfaces[0]);
4551 if(((IWineD3DSurfaceImpl *)pSrcTexture->surfaces[0])->resource.pool != D3DPOOL_SYSTEMMEM ||
4552 ((IWineD3DSurfaceImpl *)pDestTexture->surfaces[0])->resource.pool != D3DPOOL_DEFAULT){
4554 FIXME("(%p) source %p must be SYSTEMMEM and dest %p must be DEFAULT\n",This, pSrcTexture, pDestTexture);
4555 return D3DERR_INVALIDCALL;
4557 /** TODO: check that both textures have the same number of levels **/
4559 if(IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) !=IWineD3DBaseTexture_GetLevelCount(pSourceTexture))
4560 return D3DERR_INVALIDCALL;
4562 /** TODO: move this code into baseTexture? device should never touch impl*'s **/
4563 for(i = 0 ; i < IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) ; i++){
4564 IWineD3DDevice_UpdateSurface(iface, pSrcTexture->surfaces[i], NULL, pDestTexture->surfaces[i], NULL);
4570 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
4571 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
4572 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
4573 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4575 TRACE("(%p) : stub\n", This);
4578 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
4579 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4581 TRACE("(%p) : stub\n", This);
4585 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
4586 IWineD3DSwapChain *swapChain;
4588 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4590 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
4591 IWineD3DSwapChain_Release(swapChain);
4596 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4597 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4598 /* return a sensible default */
4600 /* TODO: If the window is minimized then validate device shold return something other than d3d_ok */
4601 FIXME("(%p) : stub\n", This);
4605 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4606 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4608 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4609 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4610 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4611 return D3DERR_INVALIDCALL;
4613 for (j = 0; j < 256; ++j) {
4614 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
4615 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
4616 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
4617 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
4619 TRACE("(%p) : returning\n", This);
4623 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4624 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4626 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4627 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4628 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4629 return D3DERR_INVALIDCALL;
4631 for (j = 0; j < 256; ++j) {
4632 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
4633 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
4634 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
4635 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
4637 TRACE("(%p) : returning\n", This);
4641 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4642 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4643 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4644 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4645 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4646 return D3DERR_INVALIDCALL;
4648 /*TODO: stateblocks */
4649 This->currentPalette = PaletteNumber;
4650 TRACE("(%p) : returning\n", This);
4654 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4655 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4656 if (PaletteNumber == NULL) {
4657 WARN("(%p) : returning Invalid Call\n", This);
4658 return D3DERR_INVALIDCALL;
4660 /*TODO: stateblocks */
4661 *PaletteNumber = This->currentPalette;
4662 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
4666 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4667 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4668 static BOOL showFixmes = TRUE;
4670 FIXME("(%p) : stub\n", This);
4674 This->updateStateBlock->softwareVertexProcessing = bSoftware;
4679 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4680 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4681 static BOOL showFixmes = TRUE;
4683 FIXME("(%p) : stub\n", This);
4686 return This->updateStateBlock->softwareVertexProcessing;
4690 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
4691 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4693 pRasterStatus->InVBlank = TRUE;
4694 pRasterStatus->ScanLine = 0;
4695 FIXME("(%p) : stub\n", This);
4700 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4701 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4702 static BOOL showfixmes = TRUE;
4703 if(nSegments != 0.0f) {
4705 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4712 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4713 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4714 static BOOL showfixmes = TRUE;
4716 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4723 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4724 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4725 /** TODO: remove casts to IWineD3DSurfaceImpl
4726 * NOTE: move code to surface to accomplish this
4727 ****************************************/
4728 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
4729 int srcWidth, srcHeight;
4730 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
4731 WINED3DFORMAT destFormat, srcFormat;
4733 int destLeft, destTop;
4734 D3DPOOL srcPool, destPool;
4736 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
4737 glDescriptor *glDescription = NULL;
4738 GLenum textureDimensions = GL_TEXTURE_2D;
4739 IWineD3DBaseTexture *baseTexture;
4741 WINED3DSURFACE_DESC winedesc;
4743 memset(&winedesc, 0, sizeof(winedesc));
4744 winedesc.Width = &srcSurfaceWidth;
4745 winedesc.Height = &srcSurfaceHeight;
4746 winedesc.Pool = &srcPool;
4747 winedesc.Format = &srcFormat;
4749 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
4751 winedesc.Width = &destSurfaceWidth;
4752 winedesc.Height = &destSurfaceHeight;
4753 winedesc.Pool = &destPool;
4754 winedesc.Format = &destFormat;
4755 winedesc.Size = &destSize;
4757 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
4759 if(srcPool != D3DPOOL_SYSTEMMEM || destPool != D3DPOOL_DEFAULT){
4760 FIXME("source %p must be SYSTEMMEM and dest %p must be DEFAULT\n", pSourceSurface, pDestinationSurface);
4761 return D3DERR_INVALIDCALL;
4763 /* TODO: change this to use bindTexture */
4764 /* Make sure the surface is loaded and upto date */
4765 IWineD3DSurface_PreLoad(pDestinationSurface);
4767 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
4771 /* this needs to be done in lines if the sourceRect != the sourceWidth */
4772 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
4773 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
4774 destLeft = pDestPoint ? pDestPoint->x : 0;
4775 destTop = pDestPoint ? pDestPoint->y : 0;
4778 /* This function doesn't support compressed textures
4779 the pitch is just bytesPerPixel * width */
4781 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
4782 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
4783 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
4784 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
4786 /* TODO DXT formats */
4788 if(pSourceRect != NULL && pSourceRect->top != 0){
4789 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
4791 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
4793 ,glDescription->level
4798 ,glDescription->glFormat
4799 ,glDescription->glType
4800 ,IWineD3DSurface_GetData(pSourceSurface)
4804 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
4805 /* need to lock the surface to get the data */
4806 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
4808 /* TODO: Cube and volume support */
4810 /* not a whole row so we have to do it a line at a time */
4812 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
4813 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
4815 for(j = destTop ; j < (srcHeight + destTop) ; j++){
4817 glTexSubImage2D(glDescription->target
4818 ,glDescription->level
4823 ,glDescription->glFormat
4824 ,glDescription->glType
4825 ,data/* could be quicker using */
4830 } else { /* Full width, so just write out the whole texture */
4832 if (WINED3DFMT_DXT1 == destFormat ||
4833 WINED3DFMT_DXT3 == destFormat ||
4834 WINED3DFMT_DXT5 == destFormat) {
4835 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
4836 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
4837 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
4838 FIXME("Updating part of a compressed texture is not supported at the moment\n");
4839 } if (destFormat != srcFormat) {
4840 FIXME("Updating mixed format compressed texture is not curretly support\n");
4842 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
4843 glDescription->level,
4844 glDescription->glFormatInternal,
4849 IWineD3DSurface_GetData(pSourceSurface));
4852 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
4857 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
4858 to repack the data from pow2Width/Height to expected Width,Height, this makes the
4859 data returned by GetData non-power2 width/height with hardware non-power2
4860 pow2Width/height are set to surface width height, repacking isn't needed so it
4861 doesn't matter which function gets called. */
4862 glTexSubImage2D(glDescription->target
4863 ,glDescription->level
4868 ,glDescription->glFormat
4869 ,glDescription->glType
4870 ,IWineD3DSurface_GetData(pSourceSurface)
4875 checkGLcall("glTexSubImage2D");
4876 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
4877 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
4878 * surface bigger than it needs to be hmm.. */
4879 if (D3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
4880 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
4881 IWineD3DBaseTexture_Release(baseTexture);
4884 glDisable(textureDimensions); /* This needs to be managed better.... */
4890 /* Implementation details at http://developer.nvidia.com/attach/6494
4892 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
4893 hmm.. no longer supported use
4894 OpenGL evaluators or tessellate surfaces within your application.
4897 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
4898 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4899 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4900 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p) \n", This, Handle, pNumSegs, pRectPatchInfo);
4901 FIXME("(%p) : Stub\n", This);
4906 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
4907 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4908 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4909 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p) \n", This, Handle, pNumSegs, pTriPatchInfo);
4910 FIXME("(%p) : Stub\n", This);
4914 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
4915 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4916 TRACE("(%p) Handle(%d)\n", This, Handle);
4917 FIXME("(%p) : Stub\n", This);
4921 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
4922 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
4923 fill a surface with a block of color! */
4924 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4925 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
4926 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
4927 IWineD3DSwapChainImpl *container = NULL;
4928 BOOL isRenderTarget = FALSE;
4929 unsigned int width, height;
4930 unsigned int top, left;
4933 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
4935 if (surface->resource.pool != D3DPOOL_DEFAULT) {
4936 FIXME("call to colorfill with non D3DPOOL_DEFAULT surface\n");
4937 return D3DERR_INVALIDCALL;
4940 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
4941 if (D3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
4942 if (D3DUSAGE_RENDERTARGET & surface->resource.usage) {
4943 /* TODO: make sure we set everything back to the way it was, and context management!
4944 glGetIntegerv(GL_READ_BUFFER, &prev_read);
4945 vcheckGLcall("glIntegerv");
4946 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
4947 vcheckGLcall("glIntegerv");
4949 TRACE("Color fill to render targets may cause some graphics issues\n");
4950 if (pSurface == container->frontBuffer) {
4951 glDrawBuffer(GL_FRONT);
4953 glDrawBuffer(GL_BACK);
4956 if (D3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
4957 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld \n", surface, surface->resource.usage);
4959 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
4961 if (container != NULL) {
4962 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
4964 /* we can use GL_STENCIL_INDEX etc...*/
4967 if (container != NULL) {
4968 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
4970 isRenderTarget = TRUE;
4972 /* TODO: drawing to GL_FRONT and GL_BACK */
4973 /* TODO: see if things can be speeded up by using the correct
4974 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
4975 if (pRect == NULL) {
4978 width = surface->currentDesc.Width;
4979 height = surface->currentDesc.Height;
4983 width = pRect->x2 - left;
4984 height = pRect->y2 - top;
4987 data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
4988 /* Create a 'line' of color color, in the correct format for the surface */
4989 for (u = 0 ; u < width ; u ++) {
4994 if (isRenderTarget == FALSE) {
4995 glDescriptor *glDesc;
4996 IWineD3DSurface_PreLoad(pSurface);
4998 /* draw a block of the coloured line on the sufrace */
4999 IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
5000 for (v = 0 ; v< height;v++) {
5001 glTexSubImage2D(glDesc->target
5002 ,glDesc->level /* level */
5012 checkGLcall("glTexSubImage2D");
5014 glDisable(glDesc->target);
5016 /** FIXME: Using GLClear may be faster **/
5017 glRasterPos2i(left, top);
5018 glPixelZoom((float)width ,(float)height);
5019 glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
5020 checkGLcall("glDrawPixels");
5022 HeapFree(GetProcessHeap(), 0, data);
5028 /* rendertarget and deptth stencil functions */
5029 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
5030 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5032 /* FIXME: Implelent RenderTargetIndex >0 */
5033 if(RenderTargetIndex > 0)
5034 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
5036 *ppRenderTarget = This->renderTarget;
5037 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
5038 /* Note inc ref on returned surface */
5039 if(*ppRenderTarget != NULL)
5040 IWineD3DSurface_AddRef(*ppRenderTarget);
5044 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5045 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5046 *ppZStencilSurface = This->depthStencilBuffer;
5047 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
5049 if(*ppZStencilSurface != NULL) {
5050 /* Note inc ref on returned surface */
5051 IWineD3DSurface_AddRef(*ppZStencilSurface);
5056 /* internal static helper functions */
5057 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5058 IWineD3DSurface *RenderSurface);
5060 HRESULT WINAPI static IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain);
5062 HRESULT WINAPI static IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context);
5064 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5065 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5066 HRESULT hr = D3D_OK;
5067 WINED3DVIEWPORT viewport;
5069 TRACE("(%p) Swapping rendertarget\n",This);
5070 if (RenderTargetIndex > 0) {
5071 FIXME("(%p) Render targets other than the first are not supported\n",This);
5072 RenderTargetIndex = 0;
5075 /* MSDN says that null disables the render target
5076 but a device must always be associated with a render target
5077 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5079 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5082 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5083 FIXME("Trying to set render target 0 to NULL\n");
5084 return D3DERR_INVALIDCALL;
5086 /* TODO: replace Impl* usage with interface usage */
5087 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & D3DUSAGE_RENDERTARGET) {
5088 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);
5089 return D3DERR_INVALIDCALL;
5091 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
5092 * builds, but I think wine counts as a 'debug' build for now.
5093 ******************************/
5094 /* If we are trying to set what we already have, don't bother */
5095 if (pRenderTarget == This->renderTarget) {
5096 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5098 /* Otherwise, set the render target up */
5100 if (FALSE == This->sceneEnded) {
5101 IWineD3DDevice_EndScene(iface);
5103 TRACE("clearing renderer\n");
5104 /* IWineD3DDeviceImpl_CleanRender(iface); */
5105 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5106 depending on the renter target implementation being used.
5107 A shared context implementation will share all buffers between all rendertargets (including swapchains),
5108 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5109 stencil buffer and incure an extra memory overhead */
5110 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
5113 if (SUCCEEDED(hr)) {
5114 /* Finally, reset the viewport as the MSDN states. */
5115 /* TODO: Replace impl usage */
5116 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
5117 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
5120 viewport.MaxZ = 1.0f;
5121 viewport.MinZ = 0.0f;
5122 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
5124 FIXME("Unknown error setting the render target\n");
5126 This->sceneEnded = FALSE;
5130 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
5131 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5132 HRESULT hr = D3D_OK;
5133 IWineD3DSurface *tmp;
5135 TRACE("(%p) Swapping z-buffer\n",This);
5137 if (pNewZStencil == This->stencilBufferTarget) {
5138 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5140 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5141 * depending on the renter target implementation being used.
5142 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5143 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5144 * stencil buffer and incure an extra memory overhead
5145 ******************************************************/
5148 tmp = This->stencilBufferTarget;
5149 This->stencilBufferTarget = pNewZStencil;
5150 /* should we be calling the parent or the wined3d surface? */
5151 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
5152 if (NULL != tmp) IWineD3DSurface_Release(tmp);
5154 /** TODO: glEnable/glDisable on depth/stencil depending on
5155 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
5156 **********************************************************/
5163 /* Internal functions not in DirectX */
5164 /** TODO: move this off to the opengl context manager
5165 *(the swapchain doesn't need to know anything about offscreen rendering!)
5166 ****************************************************/
5168 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
5170 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5172 TRACE("(%p), %p\n", This, swapchain);
5174 if (swapchain->win != swapchain->drawable) {
5175 /* Set everything back the way it ws */
5176 swapchain->render_ctx = swapchain->glCtx;
5177 swapchain->drawable = swapchain->win;
5182 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
5183 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
5184 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5187 unsigned int height;
5188 WINED3DFORMAT format;
5189 WINED3DSURFACE_DESC surfaceDesc;
5190 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5191 surfaceDesc.Width = &width;
5192 surfaceDesc.Height = &height;
5193 surfaceDesc.Format = &format;
5194 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5196 /* I need a get width/height function (and should do something with the format) */
5197 for (i = 0; i < CONTEXT_CACHE; ++i) {
5198 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
5199 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
5200 the pSurface can be set to 0 allowing it to be reused from cache **/
5201 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
5202 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
5203 *context = &This->contextCache[i];
5206 if (This->contextCache[i].Width == 0) {
5207 This->contextCache[i].pSurface = pSurface;
5208 This->contextCache[i].Width = width;
5209 This->contextCache[i].Height = height;
5210 *context = &This->contextCache[i];
5214 if (i == CONTEXT_CACHE) {
5215 int minUsage = 0x7FFFFFFF; /* MAX_INT */
5216 glContext *dropContext = 0;
5217 for (i = 0; i < CONTEXT_CACHE; i++) {
5218 if (This->contextCache[i].usedcount < minUsage) {
5219 dropContext = &This->contextCache[i];
5220 minUsage = This->contextCache[i].usedcount;
5223 /* clean up the context (this doesn't work for ATI at the moment */
5225 glXDestroyContext(swapchain->display, dropContext->context);
5226 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
5229 dropContext->Width = 0;
5230 dropContext->pSurface = pSurface;
5231 *context = dropContext;
5233 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
5234 for (i = 0; i < CONTEXT_CACHE; i++) {
5235 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
5239 if (*context != NULL)
5242 return E_OUTOFMEMORY;
5245 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
5246 * the functionality needs splitting up so that we don't do more than we should do.
5247 * this only seems to impact performance a little.
5248 ******************************/
5249 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5250 IWineD3DSurface *RenderSurface) {
5251 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5253 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
5254 HRESULT ret = D3DERR_INVALIDCALL;
5255 IWineD3DSurface *tmp;
5257 * Currently only active for GLX >= 1.3
5258 * for others versions we'll have to use GLXPixmaps
5260 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
5261 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
5262 * so only check OpenGL version
5263 * ..........................
5264 * I don't believe that it is a problem with NVidia headers,
5265 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
5266 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
5268 * Your application will report GLX version 1.2 on glXQueryVersion.
5269 * However, it is safe to call the GLX 1.3 functions as described below.
5271 #if defined(GL_VERSION_1_3)
5273 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
5274 GLXFBConfig* cfgs = NULL;
5278 IWineD3DSwapChain *currentSwapchain;
5279 IWineD3DSwapChainImpl *swapchain;
5280 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
5281 * but switch them off if the StencilSurface is set to NULL
5282 ** *********************************************************/
5283 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
5284 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
5287 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
5288 it StencilSurface != NULL && zBufferTarget == NULL switch it on
5291 #define PUSH1(att) attribs[nAttribs++] = (att);
5292 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
5294 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
5296 /** TODO: remove the reff to Impl (context manager should fix this!) **/
5297 IWineD3DSwapChainImpl *impSwapChain;
5298 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
5299 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
5300 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
5305 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
5306 PUSH2(GLX_X_RENDERABLE, TRUE);
5307 PUSH2(GLX_DOUBLEBUFFER, TRUE);
5308 TRACE("calling makeglcfg\n");
5309 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
5312 TRACE("calling chooseFGConfig\n");
5313 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5316 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
5317 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
5318 why we failed and only show this message once! */
5319 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"); /**/
5321 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
5322 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
5323 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
5324 PUSH2(GLX_DOUBLEBUFFER, FALSE);
5325 TRACE("calling makeglcfg\n");
5326 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
5328 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5335 for (i = 0; i < nCfgs; ++i) {
5336 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
5337 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
5338 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
5341 if (NULL != This->renderTarget) {
5343 vcheckGLcall("glFlush");
5344 /** This is only useful if the old render target was a swapchain,
5345 * we need to supercede this with a function that displays
5346 * the current buffer on the screen. This is easy to do in glx1.3 but
5347 * we need to do copy-write pixels in glx 1.2.
5348 ************************************************/
5349 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
5351 printf("Hit Enter to get next frame ...\n");
5357 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain) != D3D_OK) {
5358 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
5359 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
5363 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
5364 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
5365 **********************************************************************/
5366 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == D3D_OK) {
5367 /* We also need to make sure that the lights &co are also in the context of the swapchains */
5368 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
5369 TRACE("making swapchain active\n");
5370 if (RenderSurface != This->renderTarget) {
5371 if (RenderSurface == swapchain->backBuffer) {
5373 /* This could be flagged so that some operations work directly with the front buffer */
5374 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
5376 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
5378 TRACE("Error in setting current context: context %p drawable %ld !\n",
5379 impSwapChain->glCtx, impSwapChain->win);
5382 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5384 checkGLcall("glXMakeContextCurrent");
5386 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5388 else if (pbuffer_support == TRUE && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
5390 /** ********************************************************************
5391 * This is a quickly hacked out implementation of offscreen textures.
5392 * It will work in most cases but there may be problems if the client
5393 * modifies the texture directly, or expects the contents of the rendertarget
5396 * There are some real speed vs compatibility issues here:
5397 * we should really use a new context for every texture, but that eats ram.
5398 * we should also be restoring the texture to the pbuffer but that eats CPU
5399 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
5400 * but if this means reusing the display backbuffer then we need to make sure that
5401 * states are correctly preserved.
5402 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
5403 * and gain a good performance increase at the cost of compatibility.
5404 * I would suggest that, when this is the case, a user configurable flag be made
5405 * available, allowing the user to choose the best emulated experience for them.
5406 *********************************************************************/
5408 XVisualInfo *visinfo;
5409 glContext *newContext;
5411 /* Here were using a shared context model */
5412 if (D3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
5413 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5416 /* If the context doesn't exist then create a new one */
5417 /* TODO: This should really be part of findGlContext */
5418 if (NULL == newContext->context) {
5420 TRACE("making new buffer\n");
5422 PUSH2(GLX_PBUFFER_WIDTH, newContext->Width);
5423 PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
5426 newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
5428 /** ****************************************
5429 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
5431 * In future releases, we may provide the calls glXCreateNewContext,
5432 * glXQueryDrawable and glXMakeContextCurrent.
5433 * so until then we have to use glXGetVisualFromFBConfig &co..
5434 ********************************************/
5437 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
5439 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
5441 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
5445 if (NULL == newContext || NULL == newContext->context) {
5446 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5448 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
5449 if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
5450 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
5453 /* Clean up the old context */
5454 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5455 /* Set the current context of the swapchain to the new context */
5456 impSwapChain->drawable = newContext->drawable;
5457 impSwapChain->render_ctx = newContext->context;
5461 #if 1 /* Apply the stateblock to the new context
5462 FIXME: This is a bit of a hack, each context should know it's own state,
5463 the directX current directX state should then be applied to the context */
5466 IWineD3DStateBlockImpl *oldUpdateStateBlock;
5467 oldUpdateStateBlock = This->updateStateBlock;
5468 oldRecording= This->isRecordingState;
5469 This->isRecordingState = FALSE;
5470 This->updateStateBlock = This->stateBlock;
5471 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
5473 This->isRecordingState = oldRecording;
5474 This->updateStateBlock = oldUpdateStateBlock;
5479 /* clean up the current rendertargets swapchain (if it belonged to one) */
5480 if (currentSwapchain != NULL) {
5481 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
5484 /* Were done with the opengl context management, setup the rendertargets */
5486 tmp = This->renderTarget;
5487 This->renderTarget = RenderSurface;
5488 IWineD3DSurface_AddRef(This->renderTarget);
5489 IWineD3DSurface_Release(tmp);
5495 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
5496 /* Check that the container is not a swapchain member */
5498 IWineD3DSwapChain *tmpSwapChain;
5499 if (D3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
5500 This->renderUpsideDown = TRUE;
5502 This->renderUpsideDown = FALSE;
5503 IWineD3DSwapChain_Release(tmpSwapChain);
5505 /* Force updating the cull mode */
5506 TRACE("setting render state\n");
5507 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
5508 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
5510 /* Force updating projection matrix */
5511 This->last_was_rhw = FALSE;
5512 This->proj_valid = FALSE;
5520 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
5521 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
5526 if ( NULL != impSwapChain) {
5527 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
5535 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
5536 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
5537 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5538 /* TODO: the use of Impl is deprecated. */
5539 /* some basic validation checks */
5540 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
5542 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
5544 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
5545 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
5546 return D3DERR_INVALIDCALL;
5548 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
5549 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
5550 return D3DERR_INVALIDCALL;
5552 /* TODO: make the cursor 'real' */
5554 This->xHotSpot = XHotSpot;
5555 This->yHotSpot = YHotSpot;
5560 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
5561 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5562 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
5564 This->xScreenSpace = XScreenSpace;
5565 This->yScreenSpace = YScreenSpace;
5571 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
5572 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5573 TRACE("(%p) : visible(%d)\n", This, bShow);
5575 This->bCursorVisible = bShow;
5580 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
5581 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5582 FIXME("(%p) : stub\n", This); /* No way of notifying yet! */
5587 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
5588 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5589 /** FIXME: Resource tracking needs to be done,
5590 * The closes we can do to this is set the priorities of all managed textures low
5591 * and then reset them.
5592 ***********************************************************/
5593 FIXME("(%p) : stub\n", This);
5597 HRESULT WINAPI IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
5598 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5599 /** FIXME: Resource trascking needs to be done.
5600 * in effect this pulls all non only default
5601 * textures out of video memory and deletes all glTextures (glDeleteTextures)
5602 * and should clear down the context and set it up according to pPresentationParameters
5603 ***********************************************************/
5604 FIXME("(%p) : stub\n", This);
5608 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
5609 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5610 /** FIXME: always true at the moment **/
5611 if(bEnableDialogs == FALSE) {
5612 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
5618 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
5619 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5621 FIXME("(%p) : stub\n", This);
5622 /* Setup some reasonable defaults */
5623 pParameters->AdapterOrdinal = 0; /* always for now */
5624 pParameters->DeviceType = D3DDEVTYPE_HAL; /* always for now */
5625 pParameters->hFocusWindow = 0;
5626 pParameters->BehaviorFlags =0;
5630 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
5631 IWineD3DSwapChain *swapchain;
5632 HRESULT hrc = D3D_OK;
5634 TRACE("Relaying to swapchain\n");
5636 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
5637 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (D3DGAMMARAMP *)pRamp);
5638 IWineD3DSwapChain_Release(swapchain);
5643 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
5644 IWineD3DSwapChain *swapchain;
5645 HRESULT hrc = D3D_OK;
5647 TRACE("Relaying to swapchain\n");
5649 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
5650 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
5651 IWineD3DSwapChain_Release(swapchain);
5657 /** ********************************************************
5658 * Notification functions
5659 ** ********************************************************/
5660 /** This function must be called in the release of a resource when ref == 0,
5661 * the contents of resource must still be correct,
5662 * any handels to other resource held by the caller must be closed
5663 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
5664 *****************************************************/
5665 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5666 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5667 ResourceList* resourceList;
5669 TRACE("(%p) : resource %p\n", This, resource);
5671 EnterCriticalSection(&resourceStoreCriticalSection);
5673 /* add a new texture to the frot of the linked list */
5674 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
5675 resourceList->resource = resource;
5677 /* Get the old head */
5678 resourceList->next = This->resources;
5680 This->resources = resourceList;
5681 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
5684 LeaveCriticalSection(&resourceStoreCriticalSection);
5689 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5690 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5691 ResourceList* resourceList = NULL;
5692 ResourceList* previousResourceList = NULL;
5694 TRACE("(%p) : resource %p\n", This, resource);
5697 EnterCriticalSection(&resourceStoreCriticalSection);
5699 resourceList = This->resources;
5701 while (resourceList != NULL) {
5702 if(resourceList->resource == resource) break;
5703 previousResourceList = resourceList;
5704 resourceList = resourceList->next;
5707 if (resourceList == NULL) {
5708 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
5710 LeaveCriticalSection(&resourceStoreCriticalSection);
5714 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
5716 /* make sure we don't leave a hole in the list */
5717 if (previousResourceList != NULL) {
5718 previousResourceList->next = resourceList->next;
5720 This->resources = resourceList->next;
5724 LeaveCriticalSection(&resourceStoreCriticalSection);
5730 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
5731 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5734 TRACE("(%p) : resource %p\n", This, resource);
5735 switch(IWineD3DResource_GetType(resource)){
5736 case D3DRTYPE_SURFACE:
5737 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
5739 case D3DRTYPE_TEXTURE:
5740 case D3DRTYPE_CUBETEXTURE:
5741 case D3DRTYPE_VOLUMETEXTURE:
5742 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
5743 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5744 IUnknown *textureParent;
5745 IWineD3DBaseTexture_GetParent(This->stateBlock->textures[counter], &textureParent);
5746 /* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
5747 FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter, resource, textureParent);
5748 IUnknown_Release(textureParent);
5749 This->stateBlock->textures[counter] = NULL;
5751 if (This->updateStateBlock != This->stateBlock ){
5752 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5753 IUnknown *textureParent;
5754 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[counter], &textureParent);
5755 /* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
5756 FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter, resource, textureParent);
5757 IUnknown_Release(textureParent);
5758 This->updateStateBlock->textures[counter] = NULL;
5763 case D3DRTYPE_VOLUME:
5764 /* TODO: nothing really? */
5766 case D3DRTYPE_VERTEXBUFFER:
5767 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
5770 TRACE("Cleaning up stream pointers\n");
5772 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
5773 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
5774 FINDOUT: should changes.streamSource[StreamNumber] be set ?
5776 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5777 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
5778 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
5779 This->updateStateBlock->streamSource[streamNumber] = 0;
5780 /* Set changed flag? */
5783 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) */
5784 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
5785 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
5786 This->stateBlock->streamSource[streamNumber] = 0;
5789 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
5790 else { /* This shouldn't happen */
5791 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
5798 case D3DRTYPE_INDEXBUFFER:
5799 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
5800 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5801 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5802 This->updateStateBlock->pIndexData = NULL;
5805 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
5806 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5807 This->stateBlock->pIndexData = NULL;
5813 FIXME("(%p) unknown resource type %p %u \n", This, resource, IWineD3DResource_GetType(resource));
5818 /* Remove the resoruce from the resourceStore */
5819 IWineD3DDeviceImpl_RemoveResource(iface, resource);
5821 TRACE("Resource released\n");
5826 /** This function is to be called by the swapchain when it is released and it's ref = 0
5827 *****************************************************/
5828 void WINAPI IWineD3DDeviceImpl_SwapChainReleased(IWineD3DDevice *iface, IWineD3DSwapChain *swapChain){
5829 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5830 SwapChainList **nextSwapchain;
5831 nextSwapchain = &This->swapchains;
5833 /* Check to see if the swapchian is being used as the render target */
5834 if (This->renderTarget != NULL) {
5835 IWineD3DSurface *swapchainBackBuffer;
5837 IWineD3DSwapChain_GetBackBuffer(swapChain, 0 ,( D3DBACKBUFFER_TYPE) 0, &swapchainBackBuffer);
5838 if (This->renderTarget == swapchainBackBuffer) {
5839 /* Don't know what to do, so warn and carry on as usual (which in this case leaves the renderterget in limbo) */
5840 FIXME("Atempting to release a swapchain that is currently beuing used as a render target, behaviour is undefined\n");
5844 /* Go through the swapchain list and try to find the swapchain being released */
5845 while(*nextSwapchain != NULL && (*nextSwapchain)->swapchain != swapChain) {
5846 nextSwapchain = &(*nextSwapchain)->next;
5849 /* Check to see if we found the swapchain */
5850 if (NULL != *nextSwapchain) {
5851 /* We found the swapchain so remove it from the list */
5852 TRACE("(%p) releasing swapchain(%p)\n", iface, swapChain);
5853 HeapFree(GetProcessHeap(), 0 , *nextSwapchain);
5854 *nextSwapchain = (*nextSwapchain)->next;
5856 /* We didn't find the swapchain on the list, this can only heppen because of a programming error in wined3d */
5857 FIXME("(%p) Attempting to release a swapchain (%p) that hasn't been stored\n", iface, swapChain);
5860 TRACE("swapchain (%p) released\n", swapChain);
5864 /**********************************************************
5865 * IWineD3DDevice VTbl follows
5866 **********************************************************/
5868 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
5870 /*** IUnknown methods ***/
5871 IWineD3DDeviceImpl_QueryInterface,
5872 IWineD3DDeviceImpl_AddRef,
5873 IWineD3DDeviceImpl_Release,
5874 /*** IWineD3DDevice methods ***/
5875 IWineD3DDeviceImpl_GetParent,
5876 /*** Creation methods**/
5877 IWineD3DDeviceImpl_CreateVertexBuffer,
5878 IWineD3DDeviceImpl_CreateIndexBuffer,
5879 IWineD3DDeviceImpl_CreateStateBlock,
5880 IWineD3DDeviceImpl_CreateSurface,
5881 IWineD3DDeviceImpl_CreateTexture,
5882 IWineD3DDeviceImpl_CreateVolumeTexture,
5883 IWineD3DDeviceImpl_CreateVolume,
5884 IWineD3DDeviceImpl_CreateCubeTexture,
5885 IWineD3DDeviceImpl_CreateQuery,
5886 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
5887 IWineD3DDeviceImpl_CreateVertexDeclaration,
5888 IWineD3DDeviceImpl_CreateVertexShader,
5889 IWineD3DDeviceImpl_CreatePixelShader,
5890 /*** Odd functions **/
5891 IWineD3DDeviceImpl_EvictManagedResources,
5892 IWineD3DDeviceImpl_GetAvailableTextureMem,
5893 IWineD3DDeviceImpl_GetBackBuffer,
5894 IWineD3DDeviceImpl_GetCreationParameters,
5895 IWineD3DDeviceImpl_GetDeviceCaps,
5896 IWineD3DDeviceImpl_GetDirect3D,
5897 IWineD3DDeviceImpl_GetDisplayMode,
5898 IWineD3DDeviceImpl_GetNumberOfSwapChains,
5899 IWineD3DDeviceImpl_GetRasterStatus,
5900 IWineD3DDeviceImpl_GetSwapChain,
5901 IWineD3DDeviceImpl_Reset,
5902 IWineD3DDeviceImpl_SetDialogBoxMode,
5903 IWineD3DDeviceImpl_SetCursorProperties,
5904 IWineD3DDeviceImpl_SetCursorPosition,
5905 IWineD3DDeviceImpl_ShowCursor,
5906 IWineD3DDeviceImpl_TestCooperativeLevel,
5907 /*** Getters and setters **/
5908 IWineD3DDeviceImpl_SetClipPlane,
5909 IWineD3DDeviceImpl_GetClipPlane,
5910 IWineD3DDeviceImpl_SetClipStatus,
5911 IWineD3DDeviceImpl_GetClipStatus,
5912 IWineD3DDeviceImpl_SetCurrentTexturePalette,
5913 IWineD3DDeviceImpl_GetCurrentTexturePalette,
5914 IWineD3DDeviceImpl_SetDepthStencilSurface,
5915 IWineD3DDeviceImpl_GetDepthStencilSurface,
5916 IWineD3DDeviceImpl_SetFVF,
5917 IWineD3DDeviceImpl_GetFVF,
5918 IWineD3DDeviceImpl_SetGammaRamp,
5919 IWineD3DDeviceImpl_GetGammaRamp,
5920 IWineD3DDeviceImpl_SetIndices,
5921 IWineD3DDeviceImpl_GetIndices,
5922 IWineD3DDeviceImpl_SetLight,
5923 IWineD3DDeviceImpl_GetLight,
5924 IWineD3DDeviceImpl_SetLightEnable,
5925 IWineD3DDeviceImpl_GetLightEnable,
5926 IWineD3DDeviceImpl_SetMaterial,
5927 IWineD3DDeviceImpl_GetMaterial,
5928 IWineD3DDeviceImpl_SetNPatchMode,
5929 IWineD3DDeviceImpl_GetNPatchMode,
5930 IWineD3DDeviceImpl_SetPaletteEntries,
5931 IWineD3DDeviceImpl_GetPaletteEntries,
5932 IWineD3DDeviceImpl_SetPixelShader,
5933 IWineD3DDeviceImpl_GetPixelShader,
5934 IWineD3DDeviceImpl_SetPixelShaderConstantB,
5935 IWineD3DDeviceImpl_GetPixelShaderConstantB,
5936 IWineD3DDeviceImpl_SetPixelShaderConstantI,
5937 IWineD3DDeviceImpl_GetPixelShaderConstantI,
5938 IWineD3DDeviceImpl_SetPixelShaderConstantF,
5939 IWineD3DDeviceImpl_GetPixelShaderConstantF,
5940 IWineD3DDeviceImpl_SetRenderState,
5941 IWineD3DDeviceImpl_GetRenderState,
5942 IWineD3DDeviceImpl_SetRenderTarget,
5943 IWineD3DDeviceImpl_GetRenderTarget,
5944 IWineD3DDeviceImpl_SetSamplerState,
5945 IWineD3DDeviceImpl_GetSamplerState,
5946 IWineD3DDeviceImpl_SetScissorRect,
5947 IWineD3DDeviceImpl_GetScissorRect,
5948 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
5949 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
5950 IWineD3DDeviceImpl_SetStreamSource,
5951 IWineD3DDeviceImpl_GetStreamSource,
5952 IWineD3DDeviceImpl_SetStreamSourceFreq,
5953 IWineD3DDeviceImpl_GetStreamSourceFreq,
5954 IWineD3DDeviceImpl_SetTexture,
5955 IWineD3DDeviceImpl_GetTexture,
5956 IWineD3DDeviceImpl_SetTextureStageState,
5957 IWineD3DDeviceImpl_GetTextureStageState,
5958 IWineD3DDeviceImpl_SetTransform,
5959 IWineD3DDeviceImpl_GetTransform,
5960 IWineD3DDeviceImpl_SetVertexDeclaration,
5961 IWineD3DDeviceImpl_GetVertexDeclaration,
5962 IWineD3DDeviceImpl_SetVertexShader,
5963 IWineD3DDeviceImpl_GetVertexShader,
5964 IWineD3DDeviceImpl_SetVertexShaderConstantB,
5965 IWineD3DDeviceImpl_GetVertexShaderConstantB,
5966 IWineD3DDeviceImpl_SetVertexShaderConstantI,
5967 IWineD3DDeviceImpl_GetVertexShaderConstantI,
5968 IWineD3DDeviceImpl_SetVertexShaderConstantF,
5969 IWineD3DDeviceImpl_GetVertexShaderConstantF,
5970 IWineD3DDeviceImpl_SetViewport,
5971 IWineD3DDeviceImpl_GetViewport,
5972 IWineD3DDeviceImpl_MultiplyTransform,
5973 IWineD3DDeviceImpl_ValidateDevice,
5974 IWineD3DDeviceImpl_ProcessVertices,
5975 /*** State block ***/
5976 IWineD3DDeviceImpl_BeginStateBlock,
5977 IWineD3DDeviceImpl_EndStateBlock,
5978 /*** Scene management ***/
5979 IWineD3DDeviceImpl_BeginScene,
5980 IWineD3DDeviceImpl_EndScene,
5981 IWineD3DDeviceImpl_Present,
5982 IWineD3DDeviceImpl_Clear,
5984 IWineD3DDeviceImpl_DrawPrimitive,
5985 IWineD3DDeviceImpl_DrawIndexedPrimitive,
5986 IWineD3DDeviceImpl_DrawPrimitiveUP,
5987 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
5988 IWineD3DDeviceImpl_DrawRectPatch,
5989 IWineD3DDeviceImpl_DrawTriPatch,
5990 IWineD3DDeviceImpl_DeletePatch,
5991 IWineD3DDeviceImpl_ColorFill,
5992 IWineD3DDeviceImpl_UpdateTexture,
5993 IWineD3DDeviceImpl_UpdateSurface,
5994 IWineD3DDeviceImpl_StretchRect,
5995 IWineD3DDeviceImpl_GetRenderTargetData,
5996 IWineD3DDeviceImpl_GetFrontBufferData,
5997 /*** Internal use IWineD3DDevice methods ***/
5998 IWineD3DDeviceImpl_SetupTextureStates,
5999 /*** object tracking ***/
6000 IWineD3DDeviceImpl_SwapChainReleased,
6001 IWineD3DDeviceImpl_ResourceReleased
6005 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
6006 WINED3DRS_ALPHABLENDENABLE ,
6007 WINED3DRS_ALPHAFUNC ,
6008 WINED3DRS_ALPHAREF ,
6009 WINED3DRS_ALPHATESTENABLE ,
6011 WINED3DRS_COLORWRITEENABLE ,
6012 WINED3DRS_DESTBLEND ,
6013 WINED3DRS_DITHERENABLE ,
6014 WINED3DRS_FILLMODE ,
6015 WINED3DRS_FOGDENSITY ,
6017 WINED3DRS_FOGSTART ,
6018 WINED3DRS_LASTPIXEL ,
6019 WINED3DRS_SHADEMODE ,
6020 WINED3DRS_SRCBLEND ,
6021 WINED3DRS_STENCILENABLE ,
6022 WINED3DRS_STENCILFAIL ,
6023 WINED3DRS_STENCILFUNC ,
6024 WINED3DRS_STENCILMASK ,
6025 WINED3DRS_STENCILPASS ,
6026 WINED3DRS_STENCILREF ,
6027 WINED3DRS_STENCILWRITEMASK ,
6028 WINED3DRS_STENCILZFAIL ,
6029 WINED3DRS_TEXTUREFACTOR ,
6040 WINED3DRS_ZWRITEENABLE
6043 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
6044 WINED3DTSS_ADDRESSW ,
6045 WINED3DTSS_ALPHAARG0 ,
6046 WINED3DTSS_ALPHAARG1 ,
6047 WINED3DTSS_ALPHAARG2 ,
6048 WINED3DTSS_ALPHAOP ,
6049 WINED3DTSS_BUMPENVLOFFSET ,
6050 WINED3DTSS_BUMPENVLSCALE ,
6051 WINED3DTSS_BUMPENVMAT00 ,
6052 WINED3DTSS_BUMPENVMAT01 ,
6053 WINED3DTSS_BUMPENVMAT10 ,
6054 WINED3DTSS_BUMPENVMAT11 ,
6055 WINED3DTSS_COLORARG0 ,
6056 WINED3DTSS_COLORARG1 ,
6057 WINED3DTSS_COLORARG2 ,
6058 WINED3DTSS_COLOROP ,
6059 WINED3DTSS_RESULTARG ,
6060 WINED3DTSS_TEXCOORDINDEX ,
6061 WINED3DTSS_TEXTURETRANSFORMFLAGS
6064 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
6065 WINED3DSAMP_ADDRESSU ,
6066 WINED3DSAMP_ADDRESSV ,
6067 WINED3DSAMP_ADDRESSW ,
6068 WINED3DSAMP_BORDERCOLOR ,
6069 WINED3DSAMP_MAGFILTER ,
6070 WINED3DSAMP_MINFILTER ,
6071 WINED3DSAMP_MIPFILTER ,
6072 WINED3DSAMP_MIPMAPLODBIAS ,
6073 WINED3DSAMP_MAXMIPLEVEL ,
6074 WINED3DSAMP_MAXANISOTROPY ,
6075 WINED3DSAMP_SRGBTEXTURE ,
6076 WINED3DSAMP_ELEMENTINDEX
6079 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
6081 WINED3DRS_AMBIENTMATERIALSOURCE ,
6082 WINED3DRS_CLIPPING ,
6083 WINED3DRS_CLIPPLANEENABLE ,
6084 WINED3DRS_COLORVERTEX ,
6085 WINED3DRS_DIFFUSEMATERIALSOURCE ,
6086 WINED3DRS_EMISSIVEMATERIALSOURCE ,
6087 WINED3DRS_FOGDENSITY ,
6089 WINED3DRS_FOGSTART ,
6090 WINED3DRS_FOGTABLEMODE ,
6091 WINED3DRS_FOGVERTEXMODE ,
6092 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
6093 WINED3DRS_LIGHTING ,
6094 WINED3DRS_LOCALVIEWER ,
6095 WINED3DRS_MULTISAMPLEANTIALIAS ,
6096 WINED3DRS_MULTISAMPLEMASK ,
6097 WINED3DRS_NORMALIZENORMALS ,
6098 WINED3DRS_PATCHEDGESTYLE ,
6099 WINED3DRS_POINTSCALE_A ,
6100 WINED3DRS_POINTSCALE_B ,
6101 WINED3DRS_POINTSCALE_C ,
6102 WINED3DRS_POINTSCALEENABLE ,
6103 WINED3DRS_POINTSIZE ,
6104 WINED3DRS_POINTSIZE_MAX ,
6105 WINED3DRS_POINTSIZE_MIN ,
6106 WINED3DRS_POINTSPRITEENABLE ,
6107 WINED3DRS_RANGEFOGENABLE ,
6108 WINED3DRS_SPECULARMATERIALSOURCE ,
6109 WINED3DRS_TWEENFACTOR ,
6110 WINED3DRS_VERTEXBLEND
6113 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
6114 WINED3DTSS_TEXCOORDINDEX ,
6115 WINED3DTSS_TEXTURETRANSFORMFLAGS
6118 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
6119 WINED3DSAMP_DMAPOFFSET