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 incase 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 implicite 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 it's 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 implicite 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 IWineD3DDevice_AddRef(iface);
455 /* Otherwise, might as well set the whole state block to the appropriate values */
456 if ( This->stateBlock != NULL) {
457 memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
459 memset(object->streamFreq, 1, sizeof(object->streamFreq));
462 /* Reset the ref and type after kludging it */
463 object->wineD3DDevice = This;
465 object->blockType = Type;
467 TRACE("Updating changed flags appropriate for type %d\n", Type);
469 if (Type == WINED3DSBT_ALL) {
470 TRACE("ALL => Pretend everything has changed\n");
471 memset(&object->changed, TRUE, sizeof(This->stateBlock->changed));
472 } else if (Type == WINED3DSBT_PIXELSTATE) {
474 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
475 /* TODO: Pixel Shader Constants */
476 object->changed.pixelShader = TRUE;
477 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
478 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
481 } else if (Type == WINED3DSBT_VERTEXSTATE) {
483 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
484 /* TODO: Vertex Shader Constants */
485 object->changed.vertexShader = TRUE;
486 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
487 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
490 /* Duplicate light chain */
492 PLIGHTINFOEL *src = NULL;
493 PLIGHTINFOEL *dst = NULL;
494 PLIGHTINFOEL *newEl = NULL;
495 src = This->stateBlock->lights;
496 object->lights = NULL;
500 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
501 if (newEl == NULL) return D3DERR_OUTOFVIDEOMEMORY;
502 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
504 newEl->changed = TRUE;
505 newEl->enabledChanged = TRUE;
507 object->lights = newEl;
518 FIXME("Unrecognized state block type %d\n", Type);
521 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
526 /* ************************************
528 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
531 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
533 If this flag is set, the contents of the depth stencil buffer will be invalid after calling either IDirect3DDevice9::Present or IDirect3DDevice9::SetDepthStencilSurface with a different depth surface.
535 ******************************** */
537 HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height, WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **ppSurface,D3DRESOURCETYPE Type, DWORD Usage, D3DPOOL Pool, D3DMULTISAMPLE_TYPE MultiSample ,DWORD MultisampleQuality, HANDLE* pSharedHandle, IUnknown *parent) {
538 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
539 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
540 unsigned int pow2Width, pow2Height;
541 unsigned int Size = 1;
542 TRACE("(%p) Create surface\n",This);
544 /** FIXME: Check ranges on the inputs are valid
547 * [in] Quality level. The valid range is between zero and one less than the level
548 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
549 * Passing a larger value returns the error D3DERR_INVALIDCALL. The MultisampleQuality
550 * values of paired render targets, depth stencil surfaces, and the MultiSample type
552 *******************************/
557 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
559 * If this flag is set, the contents of the depth stencil buffer will be
560 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
561 * with a different depth surface.
563 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
564 ***************************/
566 if(MultisampleQuality < 0) {
567 FIXME("Invalid multisample level %ld \n", MultisampleQuality);
568 return D3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
571 if(MultisampleQuality > 0) {
572 FIXME("MultisampleQuality set to %ld, substituting 0 \n" , MultisampleQuality);
573 MultisampleQuality=0;
576 /** FIXME: Check that the format is supported
578 *******************************/
579 /* TODO: add support for dxt2 and dxt4 formats */
580 if (Format == D3DFMT_DXT2 || Format == D3DFMT_DXT4) return D3DERR_NOTAVAILABLE;
582 /* Non-power2 support */
584 /* Find the nearest pow2 match */
585 pow2Width = pow2Height = 1;
586 while (pow2Width < Width) pow2Width <<= 1;
587 while (pow2Height < Height) pow2Height <<= 1;
589 if (pow2Width > Width || pow2Height > Height) {
590 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
591 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
592 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
593 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d) \n",
594 This, Width, Height);
595 return D3DERR_NOTAVAILABLE;
599 /** Check against the maximum texture sizes supported by the video card **/
600 if (pow2Width > GL_LIMITS(texture_size) || pow2Height > GL_LIMITS(texture_size)) {
601 /* one of three options
602 1: Do the same as we do with nonpow 2 and scale the texture, (any texture ops would require the texture to be scaled which is potentially slow)
603 2: Set the texture to the maxium size (bad idea)
604 3: WARN and return D3DERR_NOTAVAILABLE;
606 WARN("(%p) Application requested a surface w %d, h %d, but the graphics card only supports %d\n", This, Width, Height, GL_LIMITS(texture_size));
607 return D3DERR_NOTAVAILABLE;
612 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
613 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
615 *********************************/
616 if (Format == WINED3DFMT_DXT1) {
617 /* DXT1 is half byte per pixel */
618 Size = ((max(Width,4) * D3DFmtGetBpp(This, Format)) * max(Height,4)) >> 1;
620 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
621 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
622 Size = ((max(Width,4) * D3DFmtGetBpp(This, Format)) * max(Height,4));
624 Size = (Width * D3DFmtGetBpp(This, Format)) * Height;
627 /** Create the and initilise surface resource **/
628 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,D3DRTYPE_SURFACE, Size)
629 object->container = (IUnknown*) This;
631 object->currentDesc.Width = Width;
632 object->currentDesc.Height = Height;
633 object->currentDesc.MultiSampleType = MultiSample;
634 object->currentDesc.MultiSampleQuality = MultisampleQuality;
636 /* Setup some glformat defaults */
637 object->glDescription.glFormat = D3DFmt2GLFmt(This, object->resource.format);
638 object->glDescription.glFormatInternal = D3DFmt2GLIntFmt(This, object->resource.format);
639 object->glDescription.glType = D3DFmt2GLType(This, object->resource.format);
640 object->glDescription.textureName = 0;
641 object->glDescription.level = Level;
642 object->glDescription.target = GL_TEXTURE_2D;
645 object->pow2Width = pow2Width;
646 object->pow2Height = pow2Height;
647 object->nonpow2 = (pow2Width != Width || pow2Height != Height) ? TRUE : FALSE;
648 object->discard = Discard;
649 object->activeLock = FALSE;
650 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
651 object->pow2Size = (pow2Width * object->bytesPerPixel) * pow2Height;
653 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
655 /* Precalculated scaling for 'faked' non power of two texture coords */
656 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
657 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
658 TRACE(" xf(%f) yf(%f) \n", object->pow2scalingFactorX, object->pow2scalingFactorY);
660 TRACE("Pool %d %d %d %d",Pool, D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM);
662 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
663 * this function is too deap to need to care about things like this.
664 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
665 * ****************************************/
667 case D3DPOOL_SCRATCH:
668 if(Lockable == FALSE)
669 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
670 which are mutually exclusive, setting lockable to true\n");
673 case D3DPOOL_SYSTEMMEM:
674 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
675 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
676 case D3DPOOL_MANAGED:
677 if(Usage == D3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
678 Usage of DYNAMIC which are mutually exclusive, not doing \
679 anything just telling you.\n");
681 case D3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
682 if(!(Usage & D3DUSAGE_DYNAMIC) && !(Usage & D3DUSAGE_RENDERTARGET)
683 && !(Usage && D3DUSAGE_DEPTHSTENCIL ) && Lockable == TRUE)
684 FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
687 FIXME("(%p) Unknown pool %d\n", This, Pool);
691 if (Usage & D3DUSAGE_RENDERTARGET && Pool != D3DPOOL_DEFAULT) {
692 FIXME("Trying to create a render target that isn't in the default pool\n");
696 object->locked = FALSE;
697 object->lockable = (WINED3DFMT_D16_LOCKABLE == Format) ? TRUE : Lockable;
699 /* mark the texture as dirty so that it get's loaded first time around*/
700 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
701 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
702 This, Width, Height, Format, debug_d3dformat(Format),
703 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
708 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
709 DWORD Usage, WINED3DFORMAT Format, D3DPOOL Pool,
710 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
711 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
713 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
714 IWineD3DTextureImpl *object;
720 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) .... \n", This, Width, Height, Levels, Usage);
722 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, D3DRTYPE_TEXTURE, 0);
723 D3DINITILIZEBASETEXTURE(object->baseTexture);
724 object->width = Width;
725 object->height = Height;
727 /* Calculate levels for mip mapping */
729 TRACE("calculating levels %d\n", object->baseTexture.levels);
730 object->baseTexture.levels++;
733 while (tmpW > 1 && tmpH > 1) {
734 tmpW = max(1, tmpW >> 1);
735 tmpH = max(1, tmpH >> 1);
736 object->baseTexture.levels++;
738 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
741 /* Generate all the surfaces */
744 for (i = 0; i < object->baseTexture.levels; i++)
746 /* use the callback to create the texture surface */
747 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
750 FIXME("Failed to create surface %p \n",object);
752 for(j = 0 ; j < i ; j++) {
753 IWineD3DSurface_Release(object->surfaces[j]);
755 /* heap free object */
756 HeapFree(GetProcessHeap(),0,object);
762 IWineD3DSurface_SetContainer(object->surfaces[i], (IUnknown *)object);
763 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
764 /* calculate the next mipmap level */
765 tmpW = max(1, tmpW >> 1);
766 tmpH = max(1, tmpH >> 1);
769 TRACE("(%p) : Created texture %p\n", This, object);
773 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
774 UINT Width, UINT Height, UINT Depth,
775 UINT Levels, DWORD Usage,
776 WINED3DFORMAT Format, D3DPOOL Pool,
777 IWineD3DVolumeTexture** ppVolumeTexture,
778 HANDLE* pSharedHandle, IUnknown *parent,
779 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
781 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
782 IWineD3DVolumeTextureImpl *object;
788 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, D3DRTYPE_VOLUMETEXTURE, 0);
789 D3DINITILIZEBASETEXTURE(object->baseTexture);
791 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
792 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
794 object->width = Width;
795 object->height = Height;
796 object->depth = Depth;
798 /* Calculate levels for mip mapping */
800 object->baseTexture.levels++;
804 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
805 tmpW = max(1, tmpW >> 1);
806 tmpH = max(1, tmpH >> 1);
807 tmpD = max(1, tmpD >> 1);
808 object->baseTexture.levels++;
810 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
813 /* Generate all the surfaces */
818 for (i = 0; i < object->baseTexture.levels; i++)
820 /* Create the volume */
821 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
822 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
823 IWineD3DVolume_SetContainer(object->volumes[i], (IUnknown *)object);
825 tmpW = max(1, tmpW >> 1);
826 tmpH = max(1, tmpH >> 1);
827 tmpD = max(1, tmpD >> 1);
830 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
831 TRACE("(%p) : Created volume texture %p\n", This, object);
835 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
836 UINT Width, UINT Height, UINT Depth,
838 WINED3DFORMAT Format, D3DPOOL Pool,
839 IWineD3DVolume** ppVolume,
840 HANDLE* pSharedHandle, IUnknown *parent) {
842 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
843 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
845 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, D3DRTYPE_VOLUME, ((Width * D3DFmtGetBpp(This, Format)) * Height * Depth))
847 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
848 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
850 object->currentDesc.Width = Width;
851 object->currentDesc.Height = Height;
852 object->currentDesc.Depth = Depth;
853 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
855 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
856 object->lockable = TRUE;
857 object->locked = FALSE;
858 memset(&object->lockedBox, 0, sizeof(D3DBOX));
859 object->dirty = FALSE;
860 return IWineD3DVolume_CleanDirtyBox((IWineD3DVolume *) object);
863 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
864 UINT Levels, DWORD Usage,
865 WINED3DFORMAT Format, D3DPOOL Pool,
866 IWineD3DCubeTexture** ppCubeTexture,
867 HANDLE* pSharedHandle, IUnknown *parent,
868 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
870 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
871 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
876 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, D3DRTYPE_CUBETEXTURE, 0);
877 D3DINITILIZEBASETEXTURE(object->baseTexture);
879 TRACE("(%p) Create Cube Texture \n", This);
881 object->edgeLength = EdgeLength;
883 /* Calculate levels for mip mapping */
885 object->baseTexture.levels++;
888 tmpW = max(1, tmpW / 2);
889 object->baseTexture.levels++;
891 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
894 /* Generate all the surfaces */
896 for (i = 0; i < object->baseTexture.levels; i++) {
898 /* Create the 6 faces */
899 for (j = 0; j < 6; j++) {
901 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
902 i /* Level */, &object->surfaces[j][i],pSharedHandle);
909 IWineD3DSurface_Release(object->surfaces[j][i]);
913 IWineD3DSurface_Release(object->surfaces[l][j]);
917 FIXME("(%p) Failed to create surface\n",object);
918 HeapFree(GetProcessHeap(),0,object);
919 *ppCubeTexture = NULL;
922 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IUnknown *)object);
923 TRACE("Created surface level %d @ %p, \n", i, object->surfaces[j][i]);
925 tmpW = max(1, tmpW >> 1);
928 TRACE("(%p) : Created Cube Texture %p\n", This, object);
929 *ppCubeTexture = (IWineD3DCubeTexture *) object;
933 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
934 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
935 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
937 if(NULL == ppQuery) {
938 /* Just a check to see if we support this type of query */
939 HRESULT hr = D3DERR_NOTAVAILABLE;
940 /* Lie and say everything is good (we can return ok fake data from a stub) */
942 case WINED3DQUERYTYPE_VCACHE:
943 case WINED3DQUERYTYPE_RESOURCEMANAGER:
944 case WINED3DQUERYTYPE_VERTEXSTATS:
945 case WINED3DQUERYTYPE_EVENT:
946 case WINED3DQUERYTYPE_OCCLUSION:
947 case WINED3DQUERYTYPE_TIMESTAMP:
948 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
949 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
950 case WINED3DQUERYTYPE_PIPELINETIMINGS:
951 case WINED3DQUERYTYPE_INTERFACETIMINGS:
952 case WINED3DQUERYTYPE_VERTEXTIMINGS:
953 case WINED3DQUERYTYPE_PIXELTIMINGS:
954 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
955 case WINED3DQUERYTYPE_CACHEUTILIZATION:
959 FIXME("(%p) Unhandled query type %d\n",This , Type);
961 FIXME("(%p) : Stub request for query type %d returned %ld\n", This, Type, hr);
965 D3DCREATEOBJECTINSTANCE(object, Query)
967 object->extendedData = 0;
968 TRACE("(%p) : Created Query %p\n", This, object);
972 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
973 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
975 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
976 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
977 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
980 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
982 XVisualInfo template;
983 GLXContext oldContext;
984 Drawable oldDrawable;
987 TRACE("(%p) : Created Aditional Swap Chain\n", This);
989 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
990 * does a device hold a reference to a swap chain giving them a lifetime of the device
991 * or does the swap chain notify the device of it'd destruction.
992 *******************************/
994 D3DCREATEOBJECTINSTANCE(object, SwapChain)
996 /* Initialize other useful values */
997 object->presentParms.BackBufferCount = 1; /* TODO:? support for gl_aux buffers */
999 /*********************
1000 * Lookup the window Handle and the relating X window handle
1001 ********************/
1003 /* Setup hwnd we are using, plus which display this equates to */
1004 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1005 if (!object->win_handle) {
1006 object->win_handle = This->createParms.hFocusWindow;
1009 object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window" );
1010 hDc = GetDC(object->win_handle);
1011 object->display = get_display(hDc);
1012 ReleaseDC(object->win_handle, hDc);
1013 TRACE("Using a display of %p %p \n", object->display, hDc);
1015 if (NULL == object->display || NULL == hDc) {
1016 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1017 return D3DERR_NOTAVAILABLE;
1020 if (object->win == 0) {
1021 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1022 return D3DERR_NOTAVAILABLE;
1025 * Create an opengl context for the display visual
1026 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1027 * use different properties after that point in time. FIXME: How to handle when requested format
1028 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1029 * it chooses is identical to the one already being used!
1030 **********************************/
1032 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1035 /* Create a new context for this swapchain */
1036 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1037 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1038 (or the best possible if none is requested) */
1039 TRACE("Found x visual ID : %ld\n", template.visualid);
1041 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1042 if (NULL == object->visInfo) {
1043 ERR("cannot really get XVisual\n");
1045 return D3DERR_NOTAVAILABLE;
1048 /* Write out some debug info about the visual/s */
1049 TRACE("Using x visual ID : %ld\n", template.visualid);
1050 TRACE(" visual info: %p\n", object->visInfo);
1051 TRACE(" num items : %d\n", num);
1052 for(n = 0;n < num; n++) {
1053 TRACE("=====item=====: %d\n", n + 1);
1054 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1055 TRACE(" screen : %d\n", object->visInfo[n].screen);
1056 TRACE(" depth : %u\n", object->visInfo[n].depth);
1057 TRACE(" class : %d\n", object->visInfo[n].class);
1058 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1059 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1060 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1061 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1062 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1063 /* log some extra glx info */
1064 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1065 TRACE(" gl_aux_buffers : %d\n", value);
1066 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1067 TRACE(" gl_buffer_size : %d\n", value);
1068 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1069 TRACE(" gl_red_size : %d\n", value);
1070 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1071 TRACE(" gl_green_size : %d\n", value);
1072 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1073 TRACE(" gl_blue_size : %d\n", value);
1074 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1075 TRACE(" gl_alpha_size : %d\n", value);
1076 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1077 TRACE(" gl_depth_size : %d\n", value);
1078 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1079 TRACE(" gl_stencil_size : %d\n", value);
1081 /* Now choose a simila visual ID*/
1083 #ifdef USE_CONTEXT_MANAGER
1085 /** TODO: use a context mamager **/
1089 IWineD3DSwapChain *implSwapChain;
1090 if (D3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1091 /* The first time around we create the context that is shared with all other swapchains and render targets */
1092 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1093 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1096 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1097 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1098 /* and create a new context with the implicit swapchains context as the shared context */
1099 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1100 IWineD3DSwapChain_Release(implSwapChain);
1105 XFree(object->visInfo);
1106 object->visInfo = NULL;
1108 if (NULL == object->glCtx) {
1109 ERR("cannot create glxContext\n");
1111 return D3DERR_NOTAVAILABLE;
1115 if (object->glCtx == NULL) {
1116 ERR("Error in context creation !\n");
1117 return D3DERR_INVALIDCALL;
1119 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1120 object->win_handle, object->glCtx, object->win, object->visInfo);
1123 /*********************
1124 * Windowed / Fullscreen
1125 *******************/
1128 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1129 * so we should really check to see if their is a fullscreen swapchain already
1130 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1131 **************************************/
1133 if (!*(pPresentationParameters->Windowed)) {
1139 /* Get info on the current display setup */
1140 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1141 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1144 /* Change the display settings */
1145 memset(&devmode, 0, sizeof(DEVMODEW));
1146 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1147 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1148 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1149 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1150 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1151 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1153 /* Make popup window */
1154 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1155 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1156 *(pPresentationParameters->BackBufferWidth),
1157 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1163 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1164 * then the corresponding dimension of the client area of the hDeviceWindow
1165 * (or the focus window, if hDeviceWindow is NULL) is taken.
1166 **********************/
1168 if (*(pPresentationParameters->Windowed) &&
1169 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1170 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1173 GetClientRect(object->win_handle, &Rect);
1175 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1176 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1177 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1179 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1180 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1181 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1185 /*********************
1186 * finish off parameter initialization
1187 *******************/
1189 /* Put the correct figures in the presentation parameters */
1190 TRACE("Coppying accross presentaion paraneters\n");
1191 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1192 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1193 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1194 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1195 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1196 object->presentParms.MultiSampleQuality = *(pPresentationParameters->MultiSampleQuality);
1197 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1198 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1199 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1200 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1201 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1202 object->presentParms.Flags = *(pPresentationParameters->Flags);
1203 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1204 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1207 /*********************
1208 * Create the back, front and stencil buffers
1209 *******************/
1210 TRACE("calling rendertarget CB\n");
1211 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1212 object->presentParms.BackBufferWidth,
1213 object->presentParms.BackBufferHeight,
1214 object->presentParms.BackBufferFormat,
1215 object->presentParms.MultiSampleType,
1216 object->presentParms.MultiSampleQuality,
1217 TRUE /* Lockable */,
1218 &object->frontBuffer,
1219 NULL /* pShared (always null)*/);
1220 if (object->frontBuffer != NULL)
1221 IWineD3DSurface_SetContainer(object->frontBuffer, (IUnknown *)object);
1222 TRACE("calling rendertarget CB\n");
1223 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1224 object->presentParms.BackBufferWidth,
1225 object->presentParms.BackBufferHeight,
1226 object->presentParms.BackBufferFormat,
1227 object->presentParms.MultiSampleType,
1228 object->presentParms.MultiSampleQuality,
1229 TRUE /* Lockable */,
1230 &object->backBuffer,
1231 NULL /* pShared (always null)*/);
1232 if (object->backBuffer != NULL)
1233 IWineD3DSurface_SetContainer(object->backBuffer, (IUnknown *)object);
1235 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1236 if (pPresentationParameters->EnableAutoDepthStencil) {
1237 TRACE("Creating depth stencil buffer\n");
1238 if (This->depthStencilBuffer == NULL ) {
1239 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1240 object->presentParms.BackBufferWidth,
1241 object->presentParms.BackBufferHeight,
1242 object->presentParms.AutoDepthStencilFormat,
1243 object->presentParms.MultiSampleType,
1244 object->presentParms.MultiSampleQuality,
1245 FALSE /* FIXME: Discard */,
1246 &This->depthStencilBuffer,
1247 NULL /* pShared (always null)*/ );
1248 if (This->depthStencilBuffer != NULL)
1249 IWineD3DSurface_SetContainer(This->depthStencilBuffer, (IUnknown *)iface);
1252 /** TODO: A check on width, height and multisample types
1253 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1254 ****************************/
1255 object->wantsDepthStencilBuffer = TRUE;
1257 object->wantsDepthStencilBuffer = FALSE;
1260 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1263 /*********************
1264 * init the default renderTarget management
1265 *******************/
1266 object->drawable = object->win;
1267 object->render_ctx = object->glCtx;
1270 /*********************
1271 * Setup some defaults and clear down the buffers
1272 *******************/
1274 /** save current context and drawable **/
1275 oldContext = glXGetCurrentContext();
1276 oldDrawable = glXGetCurrentDrawable();
1278 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1279 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1280 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1282 checkGLcall("glXMakeCurrent");
1284 TRACE("Setting up the screen\n");
1285 /* Clear the screen */
1286 glClearColor(0.0, 0.0, 0.0, 0.0);
1287 checkGLcall("glClearColor");
1290 glClearStencil(0xffff);
1292 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1293 checkGLcall("glClear");
1295 glColor3f(1.0, 1.0, 1.0);
1296 checkGLcall("glColor3f");
1298 glEnable(GL_LIGHTING);
1299 checkGLcall("glEnable");
1301 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1302 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1304 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1305 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1307 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1308 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1310 /* switch back to the original context (unless it was zero)*/
1311 if (This->swapchains != NULL) {
1312 /** TODO: restore the context and drawable **/
1313 glXMakeCurrent(object->display, oldDrawable, oldContext);
1318 { /* Finally add the swapchain to the end of the devices' swapchain list */
1319 SwapChainList **nextSwapchain;
1320 nextSwapchain = &This->swapchains;
1321 while(*nextSwapchain != NULL) {
1322 nextSwapchain = &((*nextSwapchain)->next);
1324 (*nextSwapchain) = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->swapchains));
1325 (*nextSwapchain)->swapchain = (IWineD3DSwapChain *)object;
1327 TRACE("Set swapchain to %p\n", object);
1328 } else { /* something went wrong so clean up */
1329 IUnknown* bufferParent;
1330 if (object->frontBuffer) {
1331 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1332 IUnknown_Release(bufferParent); /* once for the get parent */
1333 if(IUnknown_Release(bufferParent) > 0) {
1334 FIXME("(%p) Something's still holding the front buffer\n",This);
1337 if (object->backBuffer) {
1338 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1339 IUnknown_Release(bufferParent); /* once for the get parent */
1340 if(IUnknown_Release(bufferParent) > 0) {
1341 FIXME("(%p) Something's still holding the back buffer\n",This);
1344 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1345 /* Clean up the context */
1346 /* check that we are the current context first (we shouldn't be though!) */
1347 if (object->glCtx != 0) {
1348 if(glXGetCurrentContext() == object->glCtx) {
1349 glXMakeCurrent(object->display, None, NULL);
1351 glXDestroyContext(object->display, object->glCtx);
1353 HeapFree(GetProcessHeap(), 0, object);
1359 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1360 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1361 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1362 unsigned int numberOfSwapChains = 0;
1363 SwapChainList *swapchain;
1365 swapchain = This->swapchains;
1366 /* itterate through the list to get a count */
1367 while (swapchain != NULL) {
1368 swapchain = swapchain->next;
1369 numberOfSwapChains++;
1372 TRACE("(%p) returning %d\n", This, numberOfSwapChains);
1373 return numberOfSwapChains;
1376 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1377 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1378 SwapChainList *swapchain;
1379 HRESULT hr = D3DERR_INVALIDCALL;
1380 swapchain = This->swapchains;
1381 TRACE("(%p) : swapchain %d \n", This, iSwapChain);
1384 TRACE("(%p) Finding swapchain %d\n", This, iSwapChain);
1385 while (iSwapChain > 0 && swapchain != NULL) {
1386 swapchain = swapchain->next;
1390 if (iSwapChain > 0 || swapchain == NULL) {
1391 FIXME("(%p) Unable to find swapchain %d\n", This, iSwapChain);
1394 /** TODO: move off to a linkesList implementation **/
1395 *pSwapChain = swapchain->swapchain;
1396 IWineD3DSwapChain_AddRef(*pSwapChain);
1400 TRACE("(%p) returning %p\n", This, *pSwapChain);
1404 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
1405 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1407 FIXME("(%p) : Stub\n",This);
1413 * Vertex Declaration
1415 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1416 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1417 IWineD3DVertexDeclarationImpl *object = NULL;
1418 HRESULT hr = D3D_OK;
1419 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1420 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1423 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1428 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1429 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DVertexShader** ppVertexShader, IUnknown *parent) {
1430 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1431 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1432 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1433 object->function = pFunction;
1434 FIXME("(%p) : STUB: Created Vertex shader %p\n", This, ppVertexShader);
1439 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DPixelShader** ppPixelShader, IUnknown *parent) {
1440 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1441 FIXME("(%p) : Stub\n", This);
1445 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice* iface, IWineD3D** ppD3D) {
1446 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1447 *ppD3D= This->wineD3D;
1448 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1449 IWineD3D_AddRef(*ppD3D);
1454 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1455 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1456 * Into the video ram as possible and seeing how many fit
1457 * you can also get the correct initial value from via X and ATI's driver
1458 *******************/
1459 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1460 static BOOL showfixmes = TRUE;
1462 FIXME("(%p) : stub, emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1463 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1466 TRACE("(%p) : emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1467 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1468 /* videomemory is simulated videomemory + AGP memory left */
1469 return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1477 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1478 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1480 /* Update the current state block */
1481 This->updateStateBlock->fvf = fvf;
1482 This->updateStateBlock->changed.fvf = TRUE;
1483 This->updateStateBlock->set.fvf = TRUE;
1485 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1486 /* clear down the vertex declaration
1487 NOTE: Axis and Allies doesn't work properly otherwise
1488 (may be a stateblock problem though!)
1490 /* No difference if recording or not */
1491 return IWineD3DDevice_SetVertexDeclaration(iface, NULL);
1496 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1497 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1498 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1499 *pfvf = This->stateBlock->fvf;
1504 * Get / Set Stream Source
1506 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1507 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1508 IWineD3DVertexBuffer *oldSrc;
1510 oldSrc = This->stateBlock->streamSource[StreamNumber];
1511 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1513 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
1514 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
1515 This->updateStateBlock->streamStride[StreamNumber] = Stride;
1516 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
1517 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
1519 /* Handle recording of state blocks */
1520 if (This->isRecordingState) {
1521 TRACE("Recording... not performing anything\n");
1525 /* Not recording... */
1526 if (pStreamData != NULL) {
1527 IUnknown *newVertexBufferParent;
1528 /* GetParent will add a ref, so leave it hanging until the vertex buffer is cleared */
1529 IWineD3DVertexBuffer_GetParent(pStreamData, &newVertexBufferParent);
1531 if (oldSrc != NULL) {
1532 IUnknown *oldVertexBufferParent;
1533 IWineD3DVertexBuffer_GetParent(oldSrc, &oldVertexBufferParent);
1534 IUnknown_Release(oldVertexBufferParent);
1535 IUnknown_Release(oldVertexBufferParent);
1541 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
1542 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1544 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
1545 *pStream = This->stateBlock->streamSource[StreamNumber];
1546 *pStride = This->stateBlock->streamStride[StreamNumber];
1547 *pOffset = This->stateBlock->streamOffset[StreamNumber];
1548 if (*pStream != NULL) IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
1552 /*Should be quite easy, just an extension of vertexdata
1554 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1556 The divider is a bit odd though
1558 VertexOffset = StartVertex / Divider * StreamStride +
1559 VertexIndex / Divider * StreamStride + StreamOffset
1562 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
1563 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1565 FIXME("(%p) : stub\n", This);
1569 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
1570 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1572 FIXME("(%p) : stub\n", This);
1577 * Get / Set & Multiply Transform
1579 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1580 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1582 /* Most of this routine, comments included copied from ddraw tree initially: */
1583 TRACE("(%p) : Transform State=%d\n", This, d3dts);
1585 /* Handle recording of state blocks */
1586 if (This->isRecordingState) {
1587 TRACE("Recording... not performing anything\n");
1588 This->updateStateBlock->changed.transform[d3dts] = TRUE;
1589 This->updateStateBlock->set.transform[d3dts] = TRUE;
1590 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1595 * If the new matrix is the same as the current one,
1596 * we cut off any further processing. this seems to be a reasonable
1597 * optimization because as was noticed, some apps (warcraft3 for example)
1598 * tend towards setting the same matrix repeatedly for some reason.
1600 * From here on we assume that the new matrix is different, wherever it matters.
1602 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1603 TRACE("The app is setting the same matrix over again\n");
1606 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1610 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1611 where ViewMat = Camera space, WorldMat = world space.
1613 In OpenGL, camera and world space is combined into GL_MODELVIEW
1614 matrix. The Projection matrix stay projection matrix.
1617 /* Capture the times we can just ignore the change for now */
1618 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1619 This->modelview_valid = FALSE;
1622 } else if (d3dts == D3DTS_PROJECTION) {
1623 This->proj_valid = FALSE;
1626 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1627 /* Indexed Vertex Blending Matrices 256 -> 511 */
1628 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1629 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1633 /* Now we really are going to have to change a matrix */
1636 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1637 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
1638 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1641 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1642 * NOTE: We have to reset the positions even if the light/plane is not currently
1643 * enabled, since the call to enable it will not reset the position.
1644 * NOTE2: Apparently texture transforms do NOT need reapplying
1647 PLIGHTINFOEL *lightChain = NULL;
1648 This->modelview_valid = FALSE;
1649 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
1651 glMatrixMode(GL_MODELVIEW);
1652 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1654 glLoadMatrixf((float *)lpmatrix);
1655 checkGLcall("glLoadMatrixf(...)");
1658 lightChain = This->stateBlock->lights;
1659 while (lightChain && lightChain->glIndex != -1) {
1660 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1661 checkGLcall("glLightfv posn");
1662 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1663 checkGLcall("glLightfv dirn");
1664 lightChain = lightChain->next;
1667 /* Reset Clipping Planes if clipping is enabled */
1668 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1669 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1670 checkGLcall("glClipPlane");
1674 } else { /* What was requested!?? */
1675 WARN("invalid matrix specified: %i\n", d3dts);
1678 /* Release lock, all done */
1683 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1684 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1685 TRACE("(%p) : for Transform State %d\n", This, State);
1686 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1690 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1691 D3DMATRIX *mat = NULL;
1694 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1695 * below means it will be recorded in a state block change, but it
1696 * works regardless where it is recorded.
1697 * If this is found to be wrong, change to StateBlock.
1699 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1700 TRACE("(%p) : For state %u\n", This, State);
1702 if (State < HIGHEST_TRANSFORMSTATE)
1704 mat = &This->updateStateBlock->transforms[State];
1706 FIXME("Unhandled transform state!!\n");
1709 /* Copied from ddraw code: */
1710 temp.u.s._11 = (mat->u.s._11 * pMatrix->u.s._11) + (mat->u.s._21 * pMatrix->u.s._12) + (mat->u.s._31 * pMatrix->u.s._13) + (mat->u.s._41 * pMatrix->u.s._14);
1711 temp.u.s._21 = (mat->u.s._11 * pMatrix->u.s._21) + (mat->u.s._21 * pMatrix->u.s._22) + (mat->u.s._31 * pMatrix->u.s._23) + (mat->u.s._41 * pMatrix->u.s._24);
1712 temp.u.s._31 = (mat->u.s._11 * pMatrix->u.s._31) + (mat->u.s._21 * pMatrix->u.s._32) + (mat->u.s._31 * pMatrix->u.s._33) + (mat->u.s._41 * pMatrix->u.s._34);
1713 temp.u.s._41 = (mat->u.s._11 * pMatrix->u.s._41) + (mat->u.s._21 * pMatrix->u.s._42) + (mat->u.s._31 * pMatrix->u.s._43) + (mat->u.s._41 * pMatrix->u.s._44);
1715 temp.u.s._12 = (mat->u.s._12 * pMatrix->u.s._11) + (mat->u.s._22 * pMatrix->u.s._12) + (mat->u.s._32 * pMatrix->u.s._13) + (mat->u.s._42 * pMatrix->u.s._14);
1716 temp.u.s._22 = (mat->u.s._12 * pMatrix->u.s._21) + (mat->u.s._22 * pMatrix->u.s._22) + (mat->u.s._32 * pMatrix->u.s._23) + (mat->u.s._42 * pMatrix->u.s._24);
1717 temp.u.s._32 = (mat->u.s._12 * pMatrix->u.s._31) + (mat->u.s._22 * pMatrix->u.s._32) + (mat->u.s._32 * pMatrix->u.s._33) + (mat->u.s._42 * pMatrix->u.s._34);
1718 temp.u.s._42 = (mat->u.s._12 * pMatrix->u.s._41) + (mat->u.s._22 * pMatrix->u.s._42) + (mat->u.s._32 * pMatrix->u.s._43) + (mat->u.s._42 * pMatrix->u.s._44);
1720 temp.u.s._13 = (mat->u.s._13 * pMatrix->u.s._11) + (mat->u.s._23 * pMatrix->u.s._12) + (mat->u.s._33 * pMatrix->u.s._13) + (mat->u.s._43 * pMatrix->u.s._14);
1721 temp.u.s._23 = (mat->u.s._13 * pMatrix->u.s._21) + (mat->u.s._23 * pMatrix->u.s._22) + (mat->u.s._33 * pMatrix->u.s._23) + (mat->u.s._43 * pMatrix->u.s._24);
1722 temp.u.s._33 = (mat->u.s._13 * pMatrix->u.s._31) + (mat->u.s._23 * pMatrix->u.s._32) + (mat->u.s._33 * pMatrix->u.s._33) + (mat->u.s._43 * pMatrix->u.s._34);
1723 temp.u.s._43 = (mat->u.s._13 * pMatrix->u.s._41) + (mat->u.s._23 * pMatrix->u.s._42) + (mat->u.s._33 * pMatrix->u.s._43) + (mat->u.s._43 * pMatrix->u.s._44);
1725 temp.u.s._14 = (mat->u.s._14 * pMatrix->u.s._11) + (mat->u.s._24 * pMatrix->u.s._12) + (mat->u.s._34 * pMatrix->u.s._13) + (mat->u.s._44 * pMatrix->u.s._14);
1726 temp.u.s._24 = (mat->u.s._14 * pMatrix->u.s._21) + (mat->u.s._24 * pMatrix->u.s._22) + (mat->u.s._34 * pMatrix->u.s._23) + (mat->u.s._44 * pMatrix->u.s._24);
1727 temp.u.s._34 = (mat->u.s._14 * pMatrix->u.s._31) + (mat->u.s._24 * pMatrix->u.s._32) + (mat->u.s._34 * pMatrix->u.s._33) + (mat->u.s._44 * pMatrix->u.s._34);
1728 temp.u.s._44 = (mat->u.s._14 * pMatrix->u.s._41) + (mat->u.s._24 * pMatrix->u.s._42) + (mat->u.s._34 * pMatrix->u.s._43) + (mat->u.s._44 * pMatrix->u.s._44);
1730 /* Apply change via set transform - will reapply to eg. lights this way */
1731 IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
1737 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
1739 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1740 you can reference any indexes you want as long as that number max are enabled at any
1741 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1742 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1743 but when recording, just build a chain pretty much of commands to be replayed. */
1745 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
1747 PLIGHTINFOEL *object, *temp;
1749 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1750 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1752 /* If recording state block, just add to end of lights chain */
1753 if (This->isRecordingState) {
1754 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1755 if (NULL == object) {
1756 return D3DERR_OUTOFVIDEOMEMORY;
1758 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1759 object->OriginalIndex = Index;
1760 object->glIndex = -1;
1761 object->changed = TRUE;
1763 /* Add to the END of the chain of lights changes to be replayed */
1764 if (This->updateStateBlock->lights == NULL) {
1765 This->updateStateBlock->lights = object;
1767 temp = This->updateStateBlock->lights;
1768 while (temp->next != NULL) temp=temp->next;
1769 temp->next = object;
1771 TRACE("Recording... not performing anything more\n");
1775 /* Ok, not recording any longer so do real work */
1776 object = This->stateBlock->lights;
1777 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1779 /* If we didn't find it in the list of lights, time to add it */
1780 if (object == NULL) {
1781 PLIGHTINFOEL *insertAt,*prevPos;
1783 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1784 if (NULL == object) {
1785 return D3DERR_OUTOFVIDEOMEMORY;
1787 object->OriginalIndex = Index;
1788 object->glIndex = -1;
1790 /* Add it to the front of list with the idea that lights will be changed as needed
1791 BUT after any lights currently assigned GL indexes */
1792 insertAt = This->stateBlock->lights;
1794 while (insertAt != NULL && insertAt->glIndex != -1) {
1796 insertAt = insertAt->next;
1799 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1800 This->stateBlock->lights = object;
1801 } else if (insertAt == NULL) { /* End of list */
1802 prevPos->next = object;
1803 object->prev = prevPos;
1804 } else { /* Middle of chain */
1805 if (prevPos == NULL) {
1806 This->stateBlock->lights = object;
1808 prevPos->next = object;
1810 object->prev = prevPos;
1811 object->next = insertAt;
1812 insertAt->prev = object;
1816 /* Initialze the object */
1817 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,
1818 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1819 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1820 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1821 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1822 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1823 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1825 /* Save away the information */
1826 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1828 switch (pLight->Type) {
1829 case D3DLIGHT_POINT:
1831 object->lightPosn[0] = pLight->Position.x;
1832 object->lightPosn[1] = pLight->Position.y;
1833 object->lightPosn[2] = pLight->Position.z;
1834 object->lightPosn[3] = 1.0f;
1835 object->cutoff = 180.0f;
1839 case D3DLIGHT_DIRECTIONAL:
1841 object->lightPosn[0] = -pLight->Direction.x;
1842 object->lightPosn[1] = -pLight->Direction.y;
1843 object->lightPosn[2] = -pLight->Direction.z;
1844 object->lightPosn[3] = 0.0;
1845 object->exponent = 0.0f;
1846 object->cutoff = 180.0f;
1851 object->lightPosn[0] = pLight->Position.x;
1852 object->lightPosn[1] = pLight->Position.y;
1853 object->lightPosn[2] = pLight->Position.z;
1854 object->lightPosn[3] = 1.0;
1857 object->lightDirn[0] = pLight->Direction.x;
1858 object->lightDirn[1] = pLight->Direction.y;
1859 object->lightDirn[2] = pLight->Direction.z;
1860 object->lightDirn[3] = 1.0;
1863 * opengl-ish and d3d-ish spot lights use too different models for the
1864 * light "intensity" as a function of the angle towards the main light direction,
1865 * so we only can approximate very roughly.
1866 * however spot lights are rather rarely used in games (if ever used at all).
1867 * furthermore if still used, probably nobody pays attention to such details.
1869 if (pLight->Falloff == 0) {
1872 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1874 if (rho < 0.0001) rho = 0.0001f;
1875 object->exponent = -0.3/log(cos(rho/2));
1876 object->cutoff = pLight->Phi*90/M_PI;
1882 FIXME("Unrecognized light type %d\n", pLight->Type);
1885 /* Update the live definitions if the light is currently assigned a glIndex */
1886 if (object->glIndex != -1) {
1887 setup_light(iface, object->glIndex, object);
1892 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
1893 PLIGHTINFOEL *lightInfo = NULL;
1894 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1895 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1897 /* Locate the light in the live lights */
1898 lightInfo = This->stateBlock->lights;
1899 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1901 if (lightInfo == NULL) {
1902 TRACE("Light information requested but light not defined\n");
1903 return D3DERR_INVALIDCALL;
1906 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
1911 * Get / Set Light Enable
1912 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
1914 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
1915 PLIGHTINFOEL *lightInfo = NULL;
1916 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1917 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1919 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1920 if (This->isRecordingState) {
1921 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1922 if (NULL == lightInfo) {
1923 return D3DERR_OUTOFVIDEOMEMORY;
1925 lightInfo->OriginalIndex = Index;
1926 lightInfo->glIndex = -1;
1927 lightInfo->enabledChanged = TRUE;
1929 /* Add to the END of the chain of lights changes to be replayed */
1930 if (This->updateStateBlock->lights == NULL) {
1931 This->updateStateBlock->lights = lightInfo;
1933 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
1934 while (temp->next != NULL) temp=temp->next;
1935 temp->next = lightInfo;
1937 TRACE("Recording... not performing anything more\n");
1941 /* Not recording... So, locate the light in the live lights */
1942 lightInfo = This->stateBlock->lights;
1943 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1945 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1946 if (lightInfo == NULL) {
1947 D3DLIGHT9 lightParms;
1948 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1949 wait until someone confirms it seems to work! */
1950 TRACE("Light enabled requested but light not defined, so defining one!\n");
1951 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1952 lightParms.Diffuse.r = 1.0;
1953 lightParms.Diffuse.g = 1.0;
1954 lightParms.Diffuse.b = 1.0;
1955 lightParms.Diffuse.a = 0.0;
1956 lightParms.Specular.r = 0.0;
1957 lightParms.Specular.g = 0.0;
1958 lightParms.Specular.b = 0.0;
1959 lightParms.Specular.a = 0.0;
1960 lightParms.Ambient.r = 0.0;
1961 lightParms.Ambient.g = 0.0;
1962 lightParms.Ambient.b = 0.0;
1963 lightParms.Ambient.a = 0.0;
1964 lightParms.Position.x = 0.0;
1965 lightParms.Position.y = 0.0;
1966 lightParms.Position.z = 0.0;
1967 lightParms.Direction.x = 0.0;
1968 lightParms.Direction.y = 0.0;
1969 lightParms.Direction.z = 1.0;
1970 lightParms.Range = 0.0;
1971 lightParms.Falloff = 0.0;
1972 lightParms.Attenuation0 = 0.0;
1973 lightParms.Attenuation1 = 0.0;
1974 lightParms.Attenuation2 = 0.0;
1975 lightParms.Theta = 0.0;
1976 lightParms.Phi = 0.0;
1977 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
1979 /* Search for it again! Should be fairly quick as near head of list */
1980 lightInfo = This->stateBlock->lights;
1981 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1982 if (lightInfo == NULL) {
1983 FIXME("Adding default lights has failed dismally\n");
1984 return D3DERR_INVALIDCALL;
1988 /* OK, we now have a light... */
1989 if (Enable == FALSE) {
1991 /* If we are disabling it, check it was enabled, and
1992 still only do something if it has assigned a glIndex (which it should have!) */
1993 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
1994 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1996 glDisable(GL_LIGHT0 + lightInfo->glIndex);
1997 checkGLcall("glDisable GL_LIGHT0+Index");
2000 TRACE("Nothing to do as light was not enabled\n");
2002 lightInfo->lightEnabled = FALSE;
2005 /* We are enabling it. If it is enabled, it's really simple */
2006 if (lightInfo->lightEnabled) {
2008 TRACE("Nothing to do as light was enabled\n");
2010 /* If it already has a glIndex, it's still simple */
2011 } else if (lightInfo->glIndex != -1) {
2012 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2013 lightInfo->lightEnabled = TRUE;
2015 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2016 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2019 /* Otherwise got to find space - lights are ordered gl indexes first */
2021 PLIGHTINFOEL *bsf = NULL;
2022 PLIGHTINFOEL *pos = This->stateBlock->lights;
2023 PLIGHTINFOEL *prev = NULL;
2027 /* Try to minimize changes as much as possible */
2028 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2030 /* Try to remember which index can be replaced if necessary */
2031 if (bsf==NULL && pos->lightEnabled == FALSE) {
2032 /* Found a light we can replace, save as best replacement */
2036 /* Step to next space */
2042 /* If we have too many active lights, fail the call */
2043 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2044 FIXME("Program requests too many concurrent lights\n");
2045 return D3DERR_INVALIDCALL;
2047 /* If we have allocated all lights, but not all are enabled,
2048 reuse one which is not enabled */
2049 } else if (Index == This->maxConcurrentLights) {
2050 /* use bsf - Simply swap the new light and the BSF one */
2051 PLIGHTINFOEL *bsfNext = bsf->next;
2052 PLIGHTINFOEL *bsfPrev = bsf->prev;
2055 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2056 if (bsf->prev != NULL) {
2057 bsf->prev->next = lightInfo;
2059 This->stateBlock->lights = lightInfo;
2062 /* If not side by side, lots of chains to update */
2063 if (bsf->next != lightInfo) {
2064 lightInfo->prev->next = bsf;
2065 bsf->next->prev = lightInfo;
2066 bsf->next = lightInfo->next;
2067 bsf->prev = lightInfo->prev;
2068 lightInfo->next = bsfNext;
2069 lightInfo->prev = bsfPrev;
2073 bsf->prev = lightInfo;
2074 bsf->next = lightInfo->next;
2075 lightInfo->next = bsf;
2076 lightInfo->prev = bsfPrev;
2081 glIndex = bsf->glIndex;
2083 lightInfo->glIndex = glIndex;
2084 lightInfo->lightEnabled = TRUE;
2086 /* Finally set up the light in gl itself */
2087 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2089 setup_light(iface, glIndex, lightInfo);
2090 glEnable(GL_LIGHT0 + glIndex);
2091 checkGLcall("glEnable GL_LIGHT0 new setup");
2094 /* If we reached the end of the allocated lights, with space in the
2095 gl lights, setup a new light */
2096 } else if (pos->glIndex == -1) {
2098 /* We reached the end of the allocated gl lights, so already
2099 know the index of the next one! */
2101 lightInfo->glIndex = glIndex;
2102 lightInfo->lightEnabled = TRUE;
2104 /* In an ideal world, it's already in the right place */
2105 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2106 /* No need to move it */
2108 /* Remove this light from the list */
2109 lightInfo->prev->next = lightInfo->next;
2110 if (lightInfo->next != NULL) {
2111 lightInfo->next->prev = lightInfo->prev;
2114 /* Add in at appropriate place (inbetween prev and pos) */
2115 lightInfo->prev = prev;
2116 lightInfo->next = pos;
2118 This->stateBlock->lights = lightInfo;
2120 prev->next = lightInfo;
2123 pos->prev = lightInfo;
2127 /* Finally set up the light in gl itself */
2128 TRACE("Defining new light 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");
2141 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2143 PLIGHTINFOEL *lightInfo = NULL;
2144 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2145 TRACE("(%p) : for idx(%ld)\n", This, Index);
2147 /* Locate the light in the live lights */
2148 lightInfo = This->stateBlock->lights;
2149 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2151 if (lightInfo == NULL) {
2152 TRACE("Light enabled state requested but light not defined\n");
2153 return D3DERR_INVALIDCALL;
2155 *pEnable = lightInfo->lightEnabled;
2160 * Get / Set Clip Planes
2162 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2163 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2164 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2166 /* Validate Index */
2167 if (Index >= GL_LIMITS(clipplanes)) {
2168 TRACE("Application has requested clipplane this device doesn't support\n");
2169 return D3DERR_INVALIDCALL;
2172 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2173 This->updateStateBlock->set.clipplane[Index] = TRUE;
2174 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2175 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2176 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2177 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2179 /* Handle recording of state blocks */
2180 if (This->isRecordingState) {
2181 TRACE("Recording... not performing anything\n");
2189 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2190 glMatrixMode(GL_MODELVIEW);
2192 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2194 TRACE("Clipplane [%f,%f,%f,%f]\n",
2195 This->updateStateBlock->clipplane[Index][0],
2196 This->updateStateBlock->clipplane[Index][1],
2197 This->updateStateBlock->clipplane[Index][2],
2198 This->updateStateBlock->clipplane[Index][3]);
2199 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2200 checkGLcall("glClipPlane");
2208 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2209 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2210 TRACE("(%p) : for idx %ld\n", This, Index);
2212 /* Validate Index */
2213 if (Index >= GL_LIMITS(clipplanes)) {
2214 TRACE("Application has requested clipplane this device doesn't support\n");
2215 return D3DERR_INVALIDCALL;
2218 pPlane[0] = This->stateBlock->clipplane[Index][0];
2219 pPlane[1] = This->stateBlock->clipplane[Index][1];
2220 pPlane[2] = This->stateBlock->clipplane[Index][2];
2221 pPlane[3] = This->stateBlock->clipplane[Index][3];
2226 * Get / Set Clip Plane Status
2227 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2229 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2230 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2231 FIXME("(%p) : stub\n", This);
2232 if (NULL == pClipStatus) {
2233 return D3DERR_INVALIDCALL;
2235 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2236 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2240 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2241 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2242 FIXME("(%p) : stub\n", This);
2243 if (NULL == pClipStatus) {
2244 return D3DERR_INVALIDCALL;
2246 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2247 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2252 * Get / Set Material
2253 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2255 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2256 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2258 This->updateStateBlock->changed.material = TRUE;
2259 This->updateStateBlock->set.material = TRUE;
2260 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2262 /* Handle recording of state blocks */
2263 if (This->isRecordingState) {
2264 TRACE("Recording... not performing anything\n");
2269 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2270 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2271 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2272 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2273 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2275 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2276 checkGLcall("glMaterialfv");
2277 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2278 checkGLcall("glMaterialfv");
2280 /* Only change material color if specular is enabled, otherwise it is set to black */
2281 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2282 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2283 checkGLcall("glMaterialfv");
2285 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2286 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2287 checkGLcall("glMaterialfv");
2289 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2290 checkGLcall("glMaterialfv");
2291 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2292 checkGLcall("glMaterialf");
2298 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2299 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2300 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2301 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2302 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2303 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2304 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2305 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2312 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2313 UINT BaseVertexIndex) {
2314 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2315 IWineD3DIndexBuffer *oldIdxs;
2317 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2318 oldIdxs = This->updateStateBlock->pIndexData;
2320 This->updateStateBlock->changed.indices = TRUE;
2321 This->updateStateBlock->set.indices = TRUE;
2322 This->updateStateBlock->pIndexData = pIndexData;
2323 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2325 /* Handle recording of state blocks */
2326 if (This->isRecordingState) {
2327 TRACE("Recording... not performing anything\n");
2332 IUnknown *indexBufferParent;
2333 /* Getting the parent causes a addRef... it gets released when the indicies are clear */
2334 IWineD3DIndexBuffer_GetParent(pIndexData, &indexBufferParent);
2337 IUnknown *indexBufferParent;
2338 IWineD3DIndexBuffer_GetParent(oldIdxs, &indexBufferParent);
2339 IUnknown_Release(indexBufferParent);
2340 IUnknown_Release(indexBufferParent);
2345 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2346 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2348 *ppIndexData = This->stateBlock->pIndexData;
2350 /* up ref count on ppindexdata */
2351 if (*ppIndexData) IWineD3DIndexBuffer_AddRef(*ppIndexData);
2352 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2358 * Get / Set Viewports
2360 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2361 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2363 TRACE("(%p)\n", This);
2364 This->updateStateBlock->changed.viewport = TRUE;
2365 This->updateStateBlock->set.viewport = TRUE;
2366 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2368 /* Handle recording of state blocks */
2369 if (This->isRecordingState) {
2370 TRACE("Recording... not performing anything\n");
2376 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2377 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2379 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2380 checkGLcall("glDepthRange");
2381 /* Note: GL requires lower left, DirectX supplies upper left */
2382 /* TODO: replace usage of renderTarget with context management */
2383 glViewport(pViewport->X,
2384 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2385 pViewport->Width, pViewport->Height);
2387 checkGLcall("glViewport");
2395 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2396 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2397 TRACE("(%p)\n", This);
2398 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2403 * Get / Set Render States
2404 * TODO: Verify against dx9 definitions
2406 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2408 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2409 DWORD OldValue = This->stateBlock->renderState[State];
2411 /* Simple way of referring to either a DWORD or a 4 byte float */
2417 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2418 This->updateStateBlock->changed.renderState[State] = TRUE;
2419 This->updateStateBlock->set.renderState[State] = TRUE;
2420 This->updateStateBlock->renderState[State] = Value;
2422 /* Handle recording of state blocks */
2423 if (This->isRecordingState) {
2424 TRACE("Recording... not performing anything\n");
2431 case WINED3DRS_FILLMODE :
2432 switch ((D3DFILLMODE) Value) {
2433 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2434 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2435 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2437 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
2439 checkGLcall("glPolygonMode (fillmode)");
2442 case WINED3DRS_LIGHTING :
2444 glEnable(GL_LIGHTING);
2445 checkGLcall("glEnable GL_LIGHTING");
2447 glDisable(GL_LIGHTING);
2448 checkGLcall("glDisable GL_LIGHTING");
2452 case WINED3DRS_ZENABLE :
2453 switch ((D3DZBUFFERTYPE) Value) {
2455 glDisable(GL_DEPTH_TEST);
2456 checkGLcall("glDisable GL_DEPTH_TEST");
2459 glEnable(GL_DEPTH_TEST);
2460 checkGLcall("glEnable GL_DEPTH_TEST");
2463 glEnable(GL_DEPTH_TEST);
2464 checkGLcall("glEnable GL_DEPTH_TEST");
2465 FIXME("W buffer is not well handled\n");
2468 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2472 case WINED3DRS_CULLMODE :
2474 /* If we are culling "back faces with clockwise vertices" then
2475 set front faces to be counter clockwise and enable culling
2477 switch ((D3DCULL) Value) {
2479 glDisable(GL_CULL_FACE);
2480 checkGLcall("glDisable GL_CULL_FACE");
2483 glEnable(GL_CULL_FACE);
2484 checkGLcall("glEnable GL_CULL_FACE");
2485 if (This->renderUpsideDown) {
2487 checkGLcall("glFrontFace GL_CW");
2489 glFrontFace(GL_CCW);
2490 checkGLcall("glFrontFace GL_CCW");
2492 glCullFace(GL_BACK);
2495 glEnable(GL_CULL_FACE);
2496 checkGLcall("glEnable GL_CULL_FACE");
2497 if (This->renderUpsideDown) {
2498 glFrontFace(GL_CCW);
2499 checkGLcall("glFrontFace GL_CCW");
2502 checkGLcall("glFrontFace GL_CW");
2504 glCullFace(GL_BACK);
2507 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2511 case WINED3DRS_SHADEMODE :
2512 switch ((D3DSHADEMODE) Value) {
2514 glShadeModel(GL_FLAT);
2515 checkGLcall("glShadeModel");
2517 case D3DSHADE_GOURAUD:
2518 glShadeModel(GL_SMOOTH);
2519 checkGLcall("glShadeModel");
2521 case D3DSHADE_PHONG:
2522 FIXME("D3DSHADE_PHONG isn't supported?\n");
2525 return D3DERR_INVALIDCALL;
2527 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2531 case WINED3DRS_DITHERENABLE :
2533 glEnable(GL_DITHER);
2534 checkGLcall("glEnable GL_DITHER");
2536 glDisable(GL_DITHER);
2537 checkGLcall("glDisable GL_DITHER");
2541 case WINED3DRS_ZWRITEENABLE :
2544 checkGLcall("glDepthMask");
2547 checkGLcall("glDepthMask");
2551 case WINED3DRS_ZFUNC :
2553 int glParm = GL_LESS;
2555 switch ((D3DCMPFUNC) Value) {
2556 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2557 case D3DCMP_LESS: glParm=GL_LESS; break;
2558 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2559 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2560 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2561 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2562 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2563 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2565 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2567 glDepthFunc(glParm);
2568 checkGLcall("glDepthFunc");
2572 case WINED3DRS_AMBIENT :
2575 D3DCOLORTOGLFLOAT4(Value, col);
2576 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2577 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2578 checkGLcall("glLightModel for MODEL_AMBIENT");
2583 case WINED3DRS_ALPHABLENDENABLE :
2586 checkGLcall("glEnable GL_BLEND");
2588 glDisable(GL_BLEND);
2589 checkGLcall("glDisable GL_BLEND");
2593 case WINED3DRS_SRCBLEND :
2594 case WINED3DRS_DESTBLEND :
2596 int newVal = GL_ZERO;
2598 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2599 case D3DBLEND_ONE : newVal = GL_ONE; break;
2600 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2601 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2602 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2603 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2604 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2605 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2606 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2607 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2608 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2610 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2611 This->srcBlend = newVal;
2612 This->dstBlend = newVal;
2615 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2616 This->srcBlend = newVal;
2617 This->dstBlend = newVal;
2620 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2623 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2624 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2625 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2626 glBlendFunc(This->srcBlend, This->dstBlend);
2628 checkGLcall("glBlendFunc");
2632 case WINED3DRS_ALPHATESTENABLE :
2634 glEnable(GL_ALPHA_TEST);
2635 checkGLcall("glEnable GL_ALPHA_TEST");
2637 glDisable(GL_ALPHA_TEST);
2638 checkGLcall("glDisable GL_ALPHA_TEST");
2642 case WINED3DRS_ALPHAFUNC :
2644 int glParm = GL_LESS;
2645 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2647 switch ((D3DCMPFUNC) Value) {
2648 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2649 case D3DCMP_LESS: glParm = GL_LESS; break;
2650 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2651 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2652 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2653 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2654 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2655 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2657 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2659 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2660 glAlphaFunc(glParm, ref);
2661 This->alphafunc = glParm;
2662 checkGLcall("glAlphaFunc");
2666 case WINED3DRS_ALPHAREF :
2668 int glParm = This->alphafunc;
2671 ref = ((float) Value) / 255.0f;
2672 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2673 glAlphaFunc(glParm, ref);
2674 checkGLcall("glAlphaFunc");
2678 case WINED3DRS_CLIPPLANEENABLE :
2679 case WINED3DRS_CLIPPING :
2681 /* Ensure we only do the changed clip planes */
2682 DWORD enable = 0xFFFFFFFF;
2683 DWORD disable = 0x00000000;
2685 /* If enabling / disabling all */
2686 if (State == WINED3DRS_CLIPPING) {
2688 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2691 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2695 enable = Value & ~OldValue;
2696 disable = ~Value & OldValue;
2699 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2700 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2701 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2702 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2703 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2704 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2706 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2707 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2708 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2709 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2710 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2711 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2713 /** update clipping status */
2715 This->stateBlock->clip_status.ClipUnion = 0;
2716 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
2718 This->stateBlock->clip_status.ClipUnion = 0;
2719 This->stateBlock->clip_status.ClipIntersection = 0;
2724 case WINED3DRS_BLENDOP :
2726 int glParm = GL_FUNC_ADD;
2728 switch ((D3DBLENDOP) Value) {
2729 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2730 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2731 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2732 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2733 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2735 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2737 TRACE("glBlendEquation(%x)\n", glParm);
2738 glBlendEquation(glParm);
2739 checkGLcall("glBlendEquation");
2743 case WINED3DRS_TEXTUREFACTOR :
2747 /* Note the texture color applies to all textures whereas
2748 GL_TEXTURE_ENV_COLOR applies to active only */
2750 D3DCOLORTOGLFLOAT4(Value, col);
2751 /* Set the default alpha blend color */
2752 glBlendColor(col[0], col[1], col[2], col[3]);
2753 checkGLcall("glBlendColor");
2755 /* And now the default texture color as well */
2756 for (i = 0; i < GL_LIMITS(textures); i++) {
2758 /* Note the D3DRS value applies to all textures, but GL has one
2759 per texture, so apply it now ready to be used! */
2760 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2763 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2766 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2767 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2772 case WINED3DRS_SPECULARENABLE :
2774 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2775 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2776 specular color. This is wrong:
2777 Separate specular color means the specular colour is maintained separately, whereas
2778 single color means it is merged in. However in both cases they are being used to
2780 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2781 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2785 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2786 checkGLcall("glMaterialfv");
2787 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2788 glEnable(GL_COLOR_SUM_EXT);
2790 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2792 checkGLcall("glEnable(GL_COLOR_SUM)");
2794 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2796 /* for the case of enabled lighting: */
2797 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2798 checkGLcall("glMaterialfv");
2800 /* for the case of disabled lighting: */
2801 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2802 glDisable(GL_COLOR_SUM_EXT);
2804 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2806 checkGLcall("glDisable(GL_COLOR_SUM)");
2811 case WINED3DRS_STENCILENABLE :
2813 glEnable(GL_STENCIL_TEST);
2814 checkGLcall("glEnable GL_STENCIL_TEST");
2816 glDisable(GL_STENCIL_TEST);
2817 checkGLcall("glDisable GL_STENCIL_TEST");
2821 case WINED3DRS_STENCILFUNC :
2823 int glParm = GL_ALWAYS;
2824 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2825 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2827 switch ((D3DCMPFUNC) Value) {
2828 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2829 case D3DCMP_LESS: glParm=GL_LESS; break;
2830 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2831 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2832 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2833 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2834 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2835 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2837 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2839 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2840 This->stencilfunc = glParm;
2841 glStencilFunc(glParm, ref, mask);
2842 checkGLcall("glStencilFunc");
2846 case WINED3DRS_STENCILREF :
2848 int glParm = This->stencilfunc;
2850 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2853 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2854 glStencilFunc(glParm, ref, mask);
2855 checkGLcall("glStencilFunc");
2859 case WINED3DRS_STENCILMASK :
2861 int glParm = This->stencilfunc;
2862 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2863 GLuint mask = Value;
2865 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2866 glStencilFunc(glParm, ref, mask);
2867 checkGLcall("glStencilFunc");
2871 case WINED3DRS_STENCILFAIL :
2877 fail = StencilOp(Value);
2878 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2879 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2880 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2881 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2883 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2884 glStencilOp(fail, zfail, zpass);
2885 checkGLcall("glStencilOp(fail, zfail, zpass);");
2888 case WINED3DRS_STENCILZFAIL :
2894 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2895 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2896 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2897 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2898 zfail = StencilOp(Value);
2900 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2901 glStencilOp(fail, zfail, zpass);
2902 checkGLcall("glStencilOp(fail, zfail, zpass);");
2905 case WINED3DRS_STENCILPASS :
2911 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2912 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2913 zpass = StencilOp(Value);
2914 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2915 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2917 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2918 glStencilOp(fail, zfail, zpass);
2919 checkGLcall("glStencilOp(fail, zfail, zpass);");
2923 case WINED3DRS_STENCILWRITEMASK :
2925 glStencilMask(Value);
2926 TRACE("glStencilMask(%lu)\n", Value);
2927 checkGLcall("glStencilMask");
2931 case WINED3DRS_FOGENABLE :
2933 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2935 checkGLcall("glEnable GL_FOG");
2938 checkGLcall("glDisable GL_FOG");
2943 case WINED3DRS_RANGEFOGENABLE :
2946 TRACE("Enabled RANGEFOG");
2948 TRACE("Disabled RANGEFOG");
2953 case WINED3DRS_FOGCOLOR :
2956 D3DCOLORTOGLFLOAT4(Value, col);
2957 /* Set the default alpha blend color */
2958 glFogfv(GL_FOG_COLOR, &col[0]);
2959 checkGLcall("glFog GL_FOG_COLOR");
2963 case WINED3DRS_FOGTABLEMODE :
2965 glHint(GL_FOG_HINT, GL_NICEST);
2967 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2968 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2969 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2970 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2972 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
2974 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2975 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
2980 case WINED3DRS_FOGVERTEXMODE :
2982 glHint(GL_FOG_HINT, GL_FASTEST);
2984 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2985 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2986 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2987 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2989 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
2991 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2992 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
2997 case WINED3DRS_FOGSTART :
3000 glFogfv(GL_FOG_START, &tmpvalue.f);
3001 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3002 TRACE("Fog Start == %f\n", tmpvalue.f);
3006 case WINED3DRS_FOGEND :
3009 glFogfv(GL_FOG_END, &tmpvalue.f);
3010 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3011 TRACE("Fog End == %f\n", tmpvalue.f);
3015 case WINED3DRS_FOGDENSITY :
3018 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3019 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3023 case WINED3DRS_VERTEXBLEND :
3025 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3026 TRACE("Vertex Blending state to %ld\n", Value);
3030 case WINED3DRS_TWEENFACTOR :
3033 This->updateStateBlock->tween_factor = tmpvalue.f;
3034 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3038 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
3040 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3044 case WINED3DRS_COLORVERTEX :
3045 case WINED3DRS_DIFFUSEMATERIALSOURCE :
3046 case WINED3DRS_SPECULARMATERIALSOURCE :
3047 case WINED3DRS_AMBIENTMATERIALSOURCE :
3048 case WINED3DRS_EMISSIVEMATERIALSOURCE :
3050 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3052 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3053 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3054 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3055 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3056 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3057 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3059 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3060 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3061 Parm = GL_AMBIENT_AND_DIFFUSE;
3065 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3067 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3069 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3076 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3078 This->tracking_color = NEEDS_TRACKING;
3079 This->tracking_parm = Parm;
3083 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3088 case WINED3DRS_LINEPATTERN :
3094 tmppattern.d = Value;
3096 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3098 if (tmppattern.lp.wRepeatFactor) {
3099 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3100 checkGLcall("glLineStipple(repeat, linepattern)");
3101 glEnable(GL_LINE_STIPPLE);
3102 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3104 glDisable(GL_LINE_STIPPLE);
3105 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3110 case WINED3DRS_ZBIAS :
3114 TRACE("ZBias value %f\n", tmpvalue.f);
3115 glPolygonOffset(0, -tmpvalue.f);
3116 checkGLcall("glPolygonOffset(0, -Value)");
3117 glEnable(GL_POLYGON_OFFSET_FILL);
3118 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3119 glEnable(GL_POLYGON_OFFSET_LINE);
3120 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3121 glEnable(GL_POLYGON_OFFSET_POINT);
3122 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3124 glDisable(GL_POLYGON_OFFSET_FILL);
3125 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3126 glDisable(GL_POLYGON_OFFSET_LINE);
3127 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3128 glDisable(GL_POLYGON_OFFSET_POINT);
3129 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3134 case WINED3DRS_NORMALIZENORMALS :
3136 glEnable(GL_NORMALIZE);
3137 checkGLcall("glEnable(GL_NORMALIZE);");
3139 glDisable(GL_NORMALIZE);
3140 checkGLcall("glDisable(GL_NORMALIZE);");
3144 case WINED3DRS_POINTSIZE :
3146 TRACE("Set point size to %f\n", tmpvalue.f);
3147 glPointSize(tmpvalue.f);
3148 checkGLcall("glPointSize(...);");
3151 case WINED3DRS_POINTSIZE_MIN :
3152 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3154 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3155 checkGLcall("glPointParameterfEXT(...);");
3157 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3161 case WINED3DRS_POINTSIZE_MAX :
3162 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3164 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3165 checkGLcall("glPointParameterfEXT(...);");
3167 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3171 case WINED3DRS_POINTSCALE_A :
3172 case WINED3DRS_POINTSCALE_B :
3173 case WINED3DRS_POINTSCALE_C :
3174 case WINED3DRS_POINTSCALEENABLE :
3176 /* If enabled, supply the parameters, otherwise fall back to defaults */
3177 if (This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3178 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3179 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]);
3180 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]);
3181 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]);
3183 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3184 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3185 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3187 TRACE("WINED3DRS_POINTSCALEENABLE not supported on this opengl\n");
3190 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3191 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3192 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3193 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3195 TRACE("WINED3DRS_POINTSCALEENABLE not supported, but not on either\n");
3201 case WINED3DRS_COLORWRITEENABLE :
3203 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3204 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3205 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3206 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3207 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3208 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3209 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3210 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3211 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3212 checkGLcall("glColorMask(...)");
3216 case WINED3DRS_LOCALVIEWER :
3218 GLint state = (Value) ? 1 : 0;
3219 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3220 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3224 case WINED3DRS_LASTPIXEL :
3227 TRACE("Last Pixel Drawing Enabled\n");
3229 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3234 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3237 TRACE("Software Processing Enabled\n");
3239 TRACE("Software Processing Disabled\n");
3244 /** not supported */
3245 case WINED3DRS_ZVISIBLE :
3248 return D3DERR_INVALIDCALL;
3251 /* Unhandled yet...! */
3252 case WINED3DRS_EDGEANTIALIAS :
3253 case WINED3DRS_WRAP0 :
3254 case WINED3DRS_WRAP1 :
3255 case WINED3DRS_WRAP2 :
3256 case WINED3DRS_WRAP3 :
3257 case WINED3DRS_WRAP4 :
3258 case WINED3DRS_WRAP5 :
3259 case WINED3DRS_WRAP6 :
3260 case WINED3DRS_WRAP7 :
3261 case WINED3DRS_POINTSPRITEENABLE :
3262 case WINED3DRS_MULTISAMPLEANTIALIAS :
3263 case WINED3DRS_MULTISAMPLEMASK :
3264 case WINED3DRS_PATCHEDGESTYLE :
3265 case WINED3DRS_PATCHSEGMENTS :
3266 case WINED3DRS_DEBUGMONITORTOKEN :
3267 case WINED3DRS_POSITIONORDER :
3268 case WINED3DRS_NORMALORDER :
3269 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3270 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3273 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3281 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3282 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3283 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3284 *pValue = This->stateBlock->renderState[State];
3289 * Get / Set Sampler States
3290 * TODO: Verify against dx9 definitions
3293 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3294 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3296 * SetSampler is designed to allow for more than the standard up to 8 textures
3297 * and Geforce has stopped supporting more than 6 standard textures in openGL.
3298 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3300 * http://developer.nvidia.com/object/General_FAQ.html#t6
3302 * There are two new settings for GForce
3304 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3305 * and the texture one:
3306 * GL_MAX_TEXTURE_COORDS_ARB.
3307 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3309 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
3310 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
3312 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
3313 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE, Sampler, Type);
3314 return D3DERR_INVALIDCALL;
3316 TRACE("Setting sampler %ld %d to %ld \n", Sampler, Type, Value);
3317 This->updateStateBlock->samplerState[Sampler][Type] = Value;
3319 /* Handle recording of state blocks */
3320 if (This->isRecordingState) {
3321 TRACE("Recording... not performing anything\n");
3328 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3329 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3330 /** TODO: check that sampler is in range **/
3331 *Value = This->updateStateBlock->samplerState[Sampler][Type];
3332 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
3337 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3338 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3341 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3342 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3343 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3349 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3350 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3351 GLint scissorBox[4];
3354 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3355 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
3356 pRect->left = scissorBox[1];
3357 pRect->top = scissorBox[2];
3358 pRect->right = scissorBox[1] + scissorBox[3];
3359 pRect->bottom = scissorBox[2] + scissorBox[4];
3360 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3365 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3366 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3368 TRACE("(%p) : pDecl=%p\n", This, pDecl);
3370 /* TODO: what about recording stateblocks? */
3371 if (NULL != pDecl) {
3372 IWineD3DVertexDeclaration_AddRef(pDecl);
3374 if (NULL != This->updateStateBlock->vertexDecl) {
3375 IWineD3DVertexDeclaration_Release(This->updateStateBlock->vertexDecl);
3377 This->updateStateBlock->vertexDecl = pDecl;
3378 This->updateStateBlock->changed.vertexDecl = TRUE;
3379 This->updateStateBlock->set.vertexDecl = TRUE;
3383 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3384 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3386 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3388 *ppDecl = This->updateStateBlock->vertexDecl;
3389 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3393 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
3394 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3396 static BOOL showFixmes = TRUE;
3398 This->updateStateBlock->vertexShader = pShader;
3399 This->updateStateBlock->changed.vertexShader = TRUE;
3400 This->updateStateBlock->set.vertexShader = TRUE;
3402 if(pShader == NULL) {
3403 /* clear down the shader */
3404 TRACE("Clear down the shader\n");
3407 FIXME("(%p) : stub pShader(%p)\n", This, pShader);
3414 /** FIXME: refernece counting? **/
3415 if (pShader == NULL) { /* only valid with non FVF shaders */
3416 TRACE_(d3d_shader)("(%p) : FVF Shader, pShader=%p\n", This, pShader);
3417 This->updateStateBlock->vertexShader = NULL;
3419 TRACE_(d3d_shader)("(%p) : Created shader, pShader=%p\n", This, pShader);
3420 This->updateStateBlock->vertexShader = pShader;
3423 This->updateStateBlock->changed.vertexShader = TRUE;
3424 This->updateStateBlock->set.vertexShader = TRUE;
3426 /* Handle recording of state blocks */
3427 if (This->isRecordingState) {
3428 TRACE("Recording... not performing anything\n");
3432 * TODO: merge HAL shaders context switching from prototype
3438 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
3439 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3440 *ppShader = This->stateBlock->vertexShader;
3441 if(*ppShader != NULL)
3442 IWineD3DVertexShader_AddRef(*ppShader);
3443 TRACE("(%p) : returning %p\n", This, *ppShader);
3447 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
3448 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3450 TRACE("(%p) : stub\n", This);
3454 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
3455 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3456 TRACE("(%p) : stub\n", This);
3460 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
3461 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3462 TRACE("(%p) : stub\n", This);
3466 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
3467 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3468 TRACE("(%p) : stub\n", This);
3472 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
3473 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3474 TRACE("(%p) : stub\n", This);
3478 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
3479 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3480 TRACE("(%p) : stub\n", This);
3484 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
3485 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3486 TRACE("(%p) : stub\n", This);
3490 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3491 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3492 TRACE("(%p) : stub\n", This);
3497 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
3498 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3499 TRACE("(%p) : stub\n", This);
3503 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
3504 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3505 TRACE("(%p) : stub\n", This);
3509 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
3510 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3511 TRACE("(%p) : stub\n", This);
3515 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
3516 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3517 TRACE("(%p) : stub\n", This);
3521 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
3522 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3523 TRACE("(%p) : stub\n", This);
3527 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
3528 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3529 TRACE("(%p) : stub\n", This);
3533 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
3534 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3535 FIXME("(%p) : stub\n", This);
3540 * Apply / Get / Set Texture Stage States
3541 * TODO: Verify against dx9 definitions
3544 /* 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 */
3545 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
3546 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3547 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
3548 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3550 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3552 /* Check that the stage is within limits */
3553 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
3554 TRACE("Attempt to access invalid texture rejected\n");
3561 case WINED3DTSS_ALPHAOP :
3562 case WINED3DTSS_COLOROP :
3565 if ((Value == D3DTOP_DISABLE) && (Type == WINED3DTSS_COLOROP)) {
3566 /* TODO: Disable by making this and all later levels disabled */
3567 glDisable(GL_TEXTURE_1D);
3568 checkGLcall("Disable GL_TEXTURE_1D");
3569 glDisable(GL_TEXTURE_2D);
3570 checkGLcall("Disable GL_TEXTURE_2D");
3571 glDisable(GL_TEXTURE_3D);
3572 checkGLcall("Disable GL_TEXTURE_3D");
3573 break; /* Don't bother setting the texture operations */
3575 /* Enable only the appropriate texture dimension */
3576 if (Type == WINED3DTSS_COLOROP) {
3577 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3578 glEnable(GL_TEXTURE_1D);
3579 checkGLcall("Enable GL_TEXTURE_1D");
3581 glDisable(GL_TEXTURE_1D);
3582 checkGLcall("Disable GL_TEXTURE_1D");
3584 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3585 if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
3586 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
3587 checkGLcall("Enable GL_TEXTURE_2D");
3589 glEnable(GL_TEXTURE_2D);
3590 checkGLcall("Enable GL_TEXTURE_2D");
3593 glDisable(GL_TEXTURE_2D);
3594 checkGLcall("Disable GL_TEXTURE_2D");
3596 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3597 glEnable(GL_TEXTURE_3D);
3598 checkGLcall("Enable GL_TEXTURE_3D");
3600 glDisable(GL_TEXTURE_3D);
3601 checkGLcall("Disable GL_TEXTURE_3D");
3603 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3604 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3605 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3607 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3608 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3612 /* Drop through... (Except disable case) */
3613 case WINED3DTSS_COLORARG0 :
3614 case WINED3DTSS_COLORARG1 :
3615 case WINED3DTSS_COLORARG2 :
3616 case WINED3DTSS_ALPHAARG0 :
3617 case WINED3DTSS_ALPHAARG1 :
3618 case WINED3DTSS_ALPHAARG2 :
3620 BOOL isAlphaArg = (Type == WINED3DTSS_ALPHAOP || Type == WINED3DTSS_ALPHAARG1 ||
3621 Type == WINED3DTSS_ALPHAARG2 || Type == WINED3DTSS_ALPHAARG0);
3623 set_tex_op(iface, TRUE, Stage, This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAOP],
3624 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG1],
3625 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG2],
3626 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG0]);
3628 set_tex_op(iface, FALSE, Stage, This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP],
3629 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG1],
3630 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG2],
3631 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG0]);
3637 case WINED3DTSS_ADDRESSW :
3639 GLint wrapParm = GL_REPEAT;
3642 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3643 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3644 case D3DTADDRESS_BORDER:
3646 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3647 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3649 /* FIXME: Not right, but better */
3650 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3651 wrapParm = GL_REPEAT;
3655 case D3DTADDRESS_MIRROR:
3657 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3658 wrapParm = GL_MIRRORED_REPEAT_ARB;
3660 /* Unsupported in OpenGL pre-1.4 */
3661 FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3662 wrapParm = GL_REPEAT;
3666 case D3DTADDRESS_MIRRORONCE:
3668 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3669 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3671 FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3672 wrapParm = GL_REPEAT;
3678 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3679 wrapParm = GL_REPEAT;
3682 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
3683 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3684 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3688 case WINED3DTSS_TEXCOORDINDEX :
3690 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3692 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
3693 one flag, you can still specify an index value, which the system uses to
3694 determine the texture wrapping mode.
3695 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3696 means use the vertex position (camera-space) as the input texture coordinates
3697 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
3698 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3699 to the TEXCOORDINDEX value */
3702 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3704 switch (Value & 0xFFFF0000) {
3705 case D3DTSS_TCI_PASSTHRU:
3706 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3707 glDisable(GL_TEXTURE_GEN_S);
3708 glDisable(GL_TEXTURE_GEN_T);
3709 glDisable(GL_TEXTURE_GEN_R);
3710 glDisable(GL_TEXTURE_GEN_Q);
3711 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3714 case D3DTSS_TCI_CAMERASPACEPOSITION:
3715 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3716 as the input texture coordinates for this stage's texture transformation. This
3717 equates roughly to EYE_LINEAR */
3719 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3720 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3721 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3722 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3723 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3725 glMatrixMode(GL_MODELVIEW);
3728 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3729 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3730 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3731 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3734 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3735 glEnable(GL_TEXTURE_GEN_S);
3736 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3737 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3738 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3739 glEnable(GL_TEXTURE_GEN_T);
3740 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3741 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3742 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3743 glEnable(GL_TEXTURE_GEN_R);
3744 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3745 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3746 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3750 case D3DTSS_TCI_CAMERASPACENORMAL:
3752 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3753 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3754 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3755 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3756 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3757 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3759 glMatrixMode(GL_MODELVIEW);
3762 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3763 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3764 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3765 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3768 glEnable(GL_TEXTURE_GEN_S);
3769 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3770 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3771 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3772 glEnable(GL_TEXTURE_GEN_T);
3773 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3774 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3775 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3776 glEnable(GL_TEXTURE_GEN_R);
3777 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3778 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3779 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3784 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3786 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3787 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3788 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3789 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3790 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3791 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3793 glMatrixMode(GL_MODELVIEW);
3796 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3797 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3798 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3799 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3802 glEnable(GL_TEXTURE_GEN_S);
3803 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3804 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3805 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3806 glEnable(GL_TEXTURE_GEN_T);
3807 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3808 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3809 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3810 glEnable(GL_TEXTURE_GEN_R);
3811 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3812 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3813 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3818 /* Unhandled types: */
3821 /* ? disable GL_TEXTURE_GEN_n ? */
3822 glDisable(GL_TEXTURE_GEN_S);
3823 glDisable(GL_TEXTURE_GEN_T);
3824 glDisable(GL_TEXTURE_GEN_R);
3825 glDisable(GL_TEXTURE_GEN_Q);
3826 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
3833 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
3834 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);
3837 case WINED3DTSS_BUMPENVMAT00 :
3838 case WINED3DTSS_BUMPENVMAT01 :
3839 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
3841 case WINED3DTSS_BUMPENVMAT10 :
3842 case WINED3DTSS_BUMPENVMAT11 :
3843 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
3846 case WINED3DTSS_BUMPENVLSCALE :
3847 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3850 case WINED3DTSS_BUMPENVLOFFSET :
3851 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3854 case WINED3DTSS_RESULTARG :
3855 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3859 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3860 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3868 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3869 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3871 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3873 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3875 /* Reject invalid texture units */
3876 if (Stage >= GL_LIMITS(textures)) {
3877 TRACE("Attempt to access invalid texture rejected\n");
3878 return D3DERR_INVALIDCALL;
3881 This->updateStateBlock->textureState[Stage][Type] = Value;
3886 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
3887 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3888 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
3889 *pValue = This->updateStateBlock->textureState[Stage][Type];
3896 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
3898 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3899 IWineD3DBaseTexture *oldTexture;
3901 oldTexture = This->updateStateBlock->textures[Stage];
3902 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3904 #if 0 /* TODO: check so vertex textures */
3905 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
3906 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
3911 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
3912 WARN("Attempt to access invalid texture rejected\n");
3913 return D3DERR_INVALIDCALL;
3916 oldTexture = This->updateStateBlock->textures[Stage];
3917 TRACE("GL_LIMITS %d\n",GL_LIMITS(textures));
3918 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
3920 This->updateStateBlock->set.textures[Stage] = TRUE;
3921 This->updateStateBlock->changed.textures[Stage] = TRUE;
3922 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
3923 This->updateStateBlock->textures[Stage] = pTexture;
3925 /* Handle recording of state blocks */
3926 if (This->isRecordingState) {
3927 TRACE("Recording... not performing anything\n");
3931 /** NOTE: MSDN says that setTexture increases the reference count,
3932 * and the the application nust set the texture back to null (or have a leaky application),
3933 * This means we should pass the refcount upto the parent
3934 *******************************/
3935 if (NULL != This->updateStateBlock->textures[Stage]) {
3936 IUnknown *textureParent;
3937 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[Stage], (IUnknown **)&textureParent);
3938 /** NOTE: GetParent will increase the ref count for me, I won't clean up until the texture is set to NULL **/
3941 if (NULL != oldTexture) {
3942 IUnknown *textureParent;
3943 IWineD3DBaseTexture_GetParent(oldTexture, (IUnknown **)&textureParent);
3944 IUnknown_Release(textureParent);
3945 IUnknown_Release(textureParent); /** NOTE: Twice because GetParent adds a ref **/
3952 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
3953 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3954 TRACE("(%p) : returning %p for stage %ld\n", This, This->updateStateBlock->textures[Stage], Stage);
3955 *ppTexture = (IWineD3DBaseTexture *) This->updateStateBlock->textures[Stage];
3957 IWineD3DBaseTexture_AddRef(*ppTexture);
3964 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type,
3965 IWineD3DSurface** ppBackBuffer) {
3966 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3967 IWineD3DSwapChain *swapChain;
3970 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
3972 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
3974 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
3975 IWineD3DSwapChain_Release(swapChain);
3977 *ppBackBuffer = NULL;
3982 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
3983 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3984 WARN("(%p) : stub, calling idirect3d for now\n", This);
3985 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
3988 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
3989 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3990 IWineD3DSwapChain *swapChain;
3993 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
3995 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
3996 IWineD3DSwapChain_Release(swapChain);
3998 FIXME("(%p) Error getting display mode\n", This);
4003 * Stateblock related functions
4006 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4007 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4008 IWineD3DStateBlockImpl *object;
4009 TRACE("(%p)", This);
4010 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4011 if(NULL == object ) {
4012 FIXME("(%p)Error allocating memory for stateblock\n", This);
4013 return E_OUTOFMEMORY;
4015 TRACE("(%p) creted object %p\n", This, object);
4016 object->wineD3DDevice= This;
4017 /** FIXME: object->parent = parent; **/
4018 object->parent = NULL;
4019 object->blockType = WINED3DSBT_ALL;
4021 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
4023 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4024 This->updateStateBlock = object;
4025 This->isRecordingState = TRUE;
4027 TRACE("(%p) recording stateblock %p\n",This , object);
4031 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4032 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4034 if (!This->isRecordingState) {
4035 FIXME("(%p) not recording! returning error\n", This);
4036 *ppStateBlock = NULL;
4037 return D3DERR_INVALIDCALL;
4040 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4041 This->isRecordingState = FALSE;
4042 This->updateStateBlock = This->stateBlock;
4043 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4044 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4045 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4050 * Scene related functions
4052 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4053 /* At the moment we have no need for any functionality at the beginning
4055 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4056 TRACE("(%p) : stub\n", This);
4060 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4061 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4062 TRACE("(%p)\n", This);
4064 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4066 checkGLcall("glFlush");
4068 TRACE("End Scene\n");
4069 if(This->renderTarget != NULL) {
4071 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4072 IUnknown *targetContainer = NULL;
4073 if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
4074 || D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
4075 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
4076 /** always dirtify for now. we must find a better way to see that surface have been modified
4077 (Modifications should will only occur via draw-primitive, but we do need better locking
4078 switching to render-to-texture should remove the overhead though.
4080 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4081 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
4082 IWineD3DSurface_PreLoad(This->renderTarget);
4083 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4084 IUnknown_Release(targetContainer);
4087 This->sceneEnded = TRUE;
4092 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4093 CONST RECT* pSourceRect, CONST RECT* pDestRect,
4094 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4095 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4096 IWineD3DSwapChain *swapChain = NULL;
4098 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4100 TRACE("(%p) Presenting the frame\n", This);
4102 for(i = 0 ; i < swapchains ; i ++) {
4104 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4105 TRACE("presentinng chain %d, %p\n", i, swapChain);
4106 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4107 IWineD3DSwapChain_Release(swapChain);
4113 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4114 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4115 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4117 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4118 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4119 when the depth-buffer format does not contain stencil buffer information, this method fails. */
4120 GLbitfield glMask = 0;
4121 GLboolean old_ztest;
4122 GLfloat old_z_clear_value;
4123 GLint old_stencil_clear_value;
4124 GLfloat old_color_clear_value[4];
4126 CONST D3DRECT* curRect;
4128 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4129 Count, pRects, Flags, Z, Stencil);
4133 glEnable(GL_SCISSOR_TEST);
4134 checkGLcall("glEnable GL_SCISSOR_TEST");
4136 if (Count > 0 && pRects) {
4142 /* Only set the values up once, as they are not changing */
4143 if (Flags & D3DCLEAR_STENCIL) {
4144 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4145 glClearStencil(Stencil);
4146 checkGLcall("glClearStencil");
4147 glMask = glMask | GL_STENCIL_BUFFER_BIT;
4148 glStencilMask(0xFFFFFFFF);
4151 if (Flags & D3DCLEAR_ZBUFFER) {
4152 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4153 glDepthMask(GL_TRUE);
4154 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4156 checkGLcall("glClearDepth");
4157 glMask = glMask | GL_DEPTH_BUFFER_BIT;
4160 if (Flags & D3DCLEAR_TARGET) {
4161 TRACE("Clearing screen with glClear to color %lx\n", Color);
4162 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4163 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
4164 ((Color >> 8) & 0xFF) / 255.0f,
4165 ((Color >> 0) & 0xFF) / 255.0f,
4166 ((Color >> 24) & 0xFF) / 255.0f);
4167 checkGLcall("glClearColor");
4169 /* Clear ALL colors! */
4170 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4171 glMask = glMask | GL_COLOR_BUFFER_BIT;
4174 /* Now process each rect in turn */
4175 for (i = 0; i < Count || i == 0; i++) {
4178 /* Note gl uses lower left, width/height */
4179 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4180 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4181 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4182 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4183 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4184 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4185 checkGLcall("glScissor");
4187 glScissor(This->stateBlock->viewport.X,
4188 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4189 This->stateBlock->viewport.Width,
4190 This->stateBlock->viewport.Height);
4191 checkGLcall("glScissor");
4194 /* Clear the selected rectangle (or full screen) */
4196 checkGLcall("glClear");
4198 /* Step to the next rectangle */
4199 if (curRect) curRect = curRect + sizeof(D3DRECT);
4202 /* Restore the old values (why..?) */
4203 if (Flags & D3DCLEAR_STENCIL) {
4204 glClearStencil(old_stencil_clear_value);
4205 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4207 if (Flags & D3DCLEAR_ZBUFFER) {
4208 glDepthMask(old_ztest);
4209 glClearDepth(old_z_clear_value);
4211 if (Flags & D3DCLEAR_TARGET) {
4212 glClearColor(old_color_clear_value[0],
4213 old_color_clear_value[1],
4214 old_color_clear_value[2],
4215 old_color_clear_value[3]);
4216 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4217 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4218 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4219 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4222 glDisable(GL_SCISSOR_TEST);
4223 checkGLcall("glDisable");
4232 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4233 UINT PrimitiveCount) {
4235 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4236 This->stateBlock->streamIsUP = FALSE;
4238 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4239 debug_d3dprimitivetype(PrimitiveType),
4240 StartVertex, PrimitiveCount);
4241 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
4246 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4247 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4248 D3DPRIMITIVETYPE PrimitiveType,
4249 INT baseVIndex, UINT minIndex,
4250 UINT NumVertices,UINT startIndex,UINT primCount) {
4252 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4254 IWineD3DIndexBuffer *pIB;
4255 D3DINDEXBUFFER_DESC IdxBufDsc;
4257 pIB = This->stateBlock->pIndexData;
4258 This->stateBlock->streamIsUP = FALSE;
4260 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d \n", This,
4261 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4262 minIndex, NumVertices, startIndex, baseVIndex, primCount);
4264 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4265 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4271 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex,
4272 startIndex, idxStride,
4273 ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory,
4279 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4280 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4281 UINT VertexStreamZeroStride) {
4282 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4284 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4285 debug_d3dprimitivetype(PrimitiveType),
4286 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4288 if (This->stateBlock->streamSource[0] != NULL) {
4289 IUnknown *vertexBufferParent;
4290 IWineD3DVertexBuffer_GetParent(This->stateBlock->streamSource[0], &vertexBufferParent);
4291 IUnknown_Release(vertexBufferParent);
4292 IUnknown_Release(vertexBufferParent);
4295 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4296 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4297 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4298 This->stateBlock->streamIsUP = TRUE;
4299 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
4300 This->stateBlock->streamStride[0] = 0;
4301 This->stateBlock->streamSource[0] = NULL;
4303 /*stream zero settings set to null at end, as per the msdn */
4307 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4308 UINT MinVertexIndex,
4309 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
4310 WINED3DFORMAT IndexDataFormat, CONST void* pVertexStreamZeroData,
4311 UINT VertexStreamZeroStride) {
4313 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4315 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4316 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4317 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData,
4318 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4320 if (IndexDataFormat == WINED3DFMT_INDEX16) {
4326 if (This->stateBlock->streamSource[0] != NULL) {
4327 IUnknown *vertexBufferParent;
4328 IWineD3DVertexBuffer_GetParent(This->stateBlock->streamSource[0], &vertexBufferParent);
4329 This->stateBlock->streamSource[0] = NULL;
4330 IUnknown_Release(vertexBufferParent);
4331 IUnknown_Release(vertexBufferParent);
4334 if (This->stateBlock->pIndexData) {
4335 IUnknown *indexBufferParent;
4336 IWineD3DIndexBuffer_GetParent(This->stateBlock->pIndexData, &indexBufferParent);
4337 This->stateBlock->pIndexData = NULL;
4338 IUnknown_Release(indexBufferParent);
4339 IUnknown_Release(indexBufferParent);
4342 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4343 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4344 This->stateBlock->streamIsUP = TRUE;
4345 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4347 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, idxStride, pIndexData, MinVertexIndex);
4349 /* stream zero settings set to null at end as per the msdn */
4350 This->stateBlock->streamSource[0] = NULL;
4351 This->stateBlock->streamStride[0] = 0;
4356 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4357 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
4358 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4359 D3DRESOURCETYPE sourceType;
4360 D3DRESOURCETYPE destinationType;
4361 IWineD3DTextureImpl *pDestTexture = (IWineD3DTextureImpl *)pDestinationTexture;
4362 IWineD3DTextureImpl *pSrcTexture = (IWineD3DTextureImpl *)pSourceTexture;
4365 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
4366 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
4367 if(sourceType != D3DRTYPE_TEXTURE && destinationType != D3DRTYPE_TEXTURE){
4368 FIXME("(%p) Only D3DRTYPE_TEXTURE to D3DRTYPE_TEXTURE supported\n", This);
4369 return D3DERR_INVALIDCALL;
4371 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
4373 /** TODO: Get rid of the casts to IWineD3DBaseTextureImpl
4374 repalce surfaces[x] with GetSurfaceLevel, or GetCubeMapSurface etc..
4375 think about moving the code into texture, and adding a member to base texture to occomplish this **/
4377 /* Make sure that the destination texture is loaded */
4378 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
4379 TRACE("Loading source texture\n");
4381 if(pSrcTexture->surfaces[0] == NULL || pDestTexture->surfaces[0] == NULL){
4382 FIXME("(%p) Texture src %p or dest %p has not surface %p %p\n", This, pSrcTexture, pDestTexture,
4383 pSrcTexture->surfaces[0], pDestTexture->surfaces[0]);
4386 if(((IWineD3DSurfaceImpl *)pSrcTexture->surfaces[0])->resource.pool != D3DPOOL_SYSTEMMEM ||
4387 ((IWineD3DSurfaceImpl *)pDestTexture->surfaces[0])->resource.pool != D3DPOOL_DEFAULT){
4389 FIXME("(%p) source %p must be SYSTEMMEM and dest %p must be DEFAULT\n",This, pSrcTexture, pDestTexture);
4390 return D3DERR_INVALIDCALL;
4392 /** TODO: check that both textures have the same number of levels **/
4394 if(IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) !=IWineD3DBaseTexture_GetLevelCount(pSourceTexture))
4395 return D3DERR_INVALIDCALL;
4397 /** TODO: move this code into baseTexture? device should never touch impl*'s **/
4398 for(i = 0 ; i < IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) ; i++){
4399 IWineD3DDevice_UpdateSurface(iface, pSrcTexture->surfaces[i], NULL, pDestTexture->surfaces[i], NULL);
4405 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
4406 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
4407 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
4408 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4410 TRACE("(%p) : stub\n", This);
4413 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
4414 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4416 TRACE("(%p) : stub\n", This);
4420 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
4421 IWineD3DSwapChain *swapChain;
4423 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4425 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
4426 IWineD3DSwapChain_Release(swapChain);
4431 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4432 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4433 /* return a sensible default */
4435 FIXME("(%p) : stub\n", This);
4439 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4440 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4441 FIXME("(%p) : stub\n", This);
4445 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4446 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4447 FIXME("(%p) : stub\n", This);
4451 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4452 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4453 FIXME("(%p) : stub\n", This);
4457 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4458 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4459 FIXME("(%p) : stub\n", This);
4463 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4464 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4465 FIXME("(%p) : stub\n", This);
4470 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4471 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4472 FIXME("(%p) : stub\n", This);
4477 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
4478 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4480 pRasterStatus->InVBlank = TRUE;
4481 pRasterStatus->ScanLine = 0;
4482 FIXME("(%p) : stub\n", This);
4487 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4488 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4489 static BOOL showfixmes = TRUE;
4490 if(nSegments != 0.0f) {
4492 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4499 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4500 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4501 static BOOL showfixmes = TRUE;
4503 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4510 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4511 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4512 /** TODO: remove casts to IWineD3DSurfaceImpl
4513 * NOTE: move code to surface to accomplish this
4514 ****************************************/
4515 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
4516 int srcWidth, srcHeight;
4517 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
4518 WINED3DFORMAT destFormat, srcFormat;
4520 int destLeft, destTop;
4521 D3DPOOL srcPool, destPool;
4523 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
4524 glDescriptor *glDescription = NULL;
4525 GLenum textureDimensions = GL_TEXTURE_2D;
4526 IWineD3DBaseTexture *baseTexture;
4528 WINED3DSURFACE_DESC winedesc;
4530 memset(&winedesc, 0, sizeof(winedesc));
4531 winedesc.Width = &srcSurfaceWidth;
4532 winedesc.Height = &srcSurfaceHeight;
4533 winedesc.Pool = &srcPool;
4534 winedesc.Format = &srcFormat;
4536 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
4538 winedesc.Width = &destSurfaceWidth;
4539 winedesc.Height = &destSurfaceHeight;
4540 winedesc.Pool = &destPool;
4541 winedesc.Format = &destFormat;
4542 winedesc.Size = &destSize;
4544 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
4546 if(srcPool != D3DPOOL_SYSTEMMEM || destPool != D3DPOOL_DEFAULT){
4547 FIXME("source %p must be SYSTEMMEM and dest %p must be DEFAULT\n", pSourceSurface, pDestinationSurface);
4548 return D3DERR_INVALIDCALL;
4550 /* TODO: change this to use bindTexture */
4551 /* Make sure the surface is loaded and upto date */
4552 IWineD3DSurface_PreLoad(pDestinationSurface);
4554 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
4558 /* this needs to be done in lines if the sourceRect != the sourceWidth */
4559 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
4560 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
4561 destLeft = pDestPoint ? pDestPoint->x : 0;
4562 destTop = pDestPoint ? pDestPoint->y : 0;
4565 /* This function doesn't support compressed textures
4566 the pitch is just bytesPerPixel * width */
4568 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
4569 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
4570 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
4571 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
4573 /* TODO DXT formats */
4575 if(pSourceRect != NULL && pSourceRect->top != 0){
4576 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
4578 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
4580 ,glDescription->level
4585 ,glDescription->glFormat
4586 ,glDescription->glType
4587 ,IWineD3DSurface_GetData(pSourceSurface)
4591 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
4592 /* need to lock the surface to get the data */
4593 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
4595 /* TODO: Cube and volume support */
4597 /* not a whole row so we have to do it a line at a time */
4599 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
4600 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
4602 for(j = destTop ; j < (srcHeight + destTop) ; j++){
4604 glTexSubImage2D(glDescription->target
4605 ,glDescription->level
4610 ,glDescription->glFormat
4611 ,glDescription->glType
4612 ,data/* could be quicker using */
4617 } else { /* Full width, so just write out the whole texture */
4619 if (WINED3DFMT_DXT1 == destFormat ||
4620 WINED3DFMT_DXT3 == destFormat ||
4621 WINED3DFMT_DXT5 == destFormat) {
4622 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
4623 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
4624 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
4625 FIXME("Updating part of a compressed texture is not supported at the moment\n");
4626 } if (destFormat != srcFormat) {
4627 FIXME("Updating mixed format compressed texture is not curretly support\n");
4629 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
4630 glDescription->level,
4631 glDescription->glFormatInternal,
4636 IWineD3DSurface_GetData(pSourceSurface));
4639 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
4644 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
4645 to repack the data from pow2Width/Height to expected Width,Height, this makes the
4646 data returned by GetData non-power2 width/height with hardware non-power2
4647 pow2Width/height are set to surface width height, repacking isn't needed so it
4648 doesn't matter which function gets called. */
4649 glTexSubImage2D(glDescription->target
4650 ,glDescription->level
4655 ,glDescription->glFormat
4656 ,glDescription->glType
4657 ,IWineD3DSurface_GetData(pSourceSurface)
4662 checkGLcall("glTexSubImage2D");
4663 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
4664 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
4665 * surface bigger than it needs to be hmm.. */
4666 if (D3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
4667 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
4668 IWineD3DBaseTexture_Release(baseTexture);
4671 glDisable(textureDimensions); /* This needs to be managed better.... */
4677 /* Implementation details at http://developer.nvidia.com/attach/6494
4679 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
4680 hmm.. no longer supported use
4681 OpenGL evaluators or tessellate surfaces within your application.
4684 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
4685 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4686 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4687 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p) \n", This, Handle, pNumSegs, pRectPatchInfo);
4688 FIXME("(%p) : Stub\n", This);
4693 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
4694 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4695 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4696 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p) \n", This, Handle, pNumSegs, pTriPatchInfo);
4697 FIXME("(%p) : Stub\n", This);
4701 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
4702 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4703 TRACE("(%p) Handle(%d)\n", This, Handle);
4704 FIXME("(%p) : Stub\n", This);
4708 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
4709 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
4710 fill a surface with a block of color! */
4711 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4712 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
4713 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
4714 IWineD3DSwapChainImpl *container = NULL;
4715 BOOL isRenderTarget = FALSE;
4716 unsigned int width, height;
4717 unsigned int top, left;
4720 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
4721 if (surface->resource.pool != D3DPOOL_DEFAULT) {
4722 FIXME("call to colorfill with non D3DPOOL_DEFAULT surface\n");
4723 return D3DERR_INVALIDCALL;
4726 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
4727 if (D3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
4728 if (D3DUSAGE_RENDERTARGET & surface->resource.usage) {
4729 /* TODO: make sure we set everything back to the way it was, and context management!
4730 glGetIntegerv(GL_READ_BUFFER, &prev_read);
4731 vcheckGLcall("glIntegerv");
4732 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
4733 vcheckGLcall("glIntegerv");
4735 TRACE("Color fill to render targets may cause some graphics issues\n");
4736 if (pSurface == container->frontBuffer) {
4737 glDrawBuffer(GL_FRONT);
4739 glDrawBuffer(GL_BACK);
4742 if (D3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
4743 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld \n", surface, surface->resource.usage);
4745 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
4747 if (container != NULL) {
4748 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
4750 /* we can use GL_STENCIL_INDEX etc...*/
4753 if (container != NULL) {
4754 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
4756 isRenderTarget = TRUE;
4758 /* TODO: drawing to GL_FRONT and GL_BACK */
4759 /* TODO: see if things can be speeded up by using the correct
4760 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
4761 if (pRect == NULL) {
4764 width = surface->currentDesc.Width;
4765 height = surface->currentDesc.Height;
4769 width = pRect->x2 - left;
4770 height = pRect->y2 - top;
4773 data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
4774 /* Create a 'line' of color color, in the correct format for the surface */
4775 for (u = 0 ; u < width ; u ++) {
4780 if (isRenderTarget == FALSE) {
4781 glDescriptor *glDesc;
4782 IWineD3DSurface_PreLoad(pSurface);
4784 /* draw a block of the coloured line on the sufrace */
4785 IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
4786 for (v = 0 ; v< height;v++) {
4787 glTexSubImage2D(glDesc->target
4788 ,glDesc->level /* level */
4798 checkGLcall("glTexSubImage2D");
4800 glDisable(glDesc->target);
4802 /** FIXME: Using GLClear may be faster **/
4803 glRasterPos2i(left, top);
4804 glPixelZoom((float)width ,(float)height);
4805 glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
4806 checkGLcall("glDrawPixels");
4808 HeapFree(GetProcessHeap(), 0, data);
4814 /* rendertarget and deptth stencil functions */
4815 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
4816 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4818 /* FIXME: Implelent RenderTargetIndex >0 */
4819 if(RenderTargetIndex > 0)
4820 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
4822 *ppRenderTarget = This->renderTarget;
4823 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
4824 /* Note inc ref on returned surface */
4825 if(*ppRenderTarget != NULL)
4826 IWineD3DSurface_AddRef(*ppRenderTarget);
4830 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
4831 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4832 *ppZStencilSurface = This->depthStencilBuffer;
4833 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
4835 if(*ppZStencilSurface != NULL) {
4836 /* Note inc ref on returned surface */
4837 IWineD3DSurface_AddRef(*ppZStencilSurface);
4842 /* internal static helper functions */
4843 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
4844 IWineD3DSurface *RenderSurface);
4846 HRESULT WINAPI static IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain);
4848 HRESULT WINAPI static IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context);
4850 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
4851 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4852 HRESULT hr = D3D_OK;
4853 WINED3DVIEWPORT viewport;
4855 TRACE("(%p) Swapping rendertarget\n",This);
4856 if (RenderTargetIndex > 0) {
4857 FIXME("(%p) Render targets other than the first are not supported\n",This);
4858 RenderTargetIndex = 0;
4861 /* MSDN says that null disables the render target
4862 but a device must always be associated with a render target
4863 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
4865 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
4868 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
4869 FIXME("Trying to set render target 0 to NULL\n");
4870 return D3DERR_INVALIDCALL;
4872 /* TODO: replace Impl* usage with interface usage */
4873 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & D3DUSAGE_RENDERTARGET) {
4874 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);
4875 return D3DERR_INVALIDCALL;
4877 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
4878 * builds, but I think wine counts as a 'debug' build for now.
4879 ******************************/
4880 /* If we are trying to set what we already have, don't bother */
4881 if (pRenderTarget == This->renderTarget) {
4882 TRACE("Trying to do a NOP SetRenderTarget operation\n");
4884 /* Otherwise, set the render target up */
4886 if (FALSE == This->sceneEnded) {
4887 IWineD3DDevice_EndScene(iface);
4889 TRACE("clearing renderer\n");
4890 /* IWineD3DDeviceImpl_CleanRender(iface); */
4891 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
4892 depending on the renter target implementation being used.
4893 A shared context implementation will share all buffers between all rendertargets (including swapchains),
4894 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
4895 stencil buffer and incure an extra memory overhead */
4896 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
4899 if (SUCCEEDED(hr)) {
4900 /* Finally, reset the viewport as the MSDN states. */
4901 /* TODO: Replace impl usage */
4902 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
4903 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
4906 viewport.MaxZ = 1.0f;
4907 viewport.MinZ = 0.0f;
4908 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
4910 FIXME("Unknown error setting the render target\n");
4912 This->sceneEnded = FALSE;
4916 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
4917 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4918 HRESULT hr = D3D_OK;
4919 IWineD3DSurface *tmp;
4921 TRACE("(%p) Swapping z-buffer\n",This);
4923 if (pNewZStencil == This->stencilBufferTarget) {
4924 TRACE("Trying to do a NOP SetRenderTarget operation\n");
4926 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
4927 * depending on the renter target implementation being used.
4928 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
4929 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
4930 * stencil buffer and incure an extra memory overhead
4931 ******************************************************/
4934 tmp = This->stencilBufferTarget;
4935 This->stencilBufferTarget = pNewZStencil;
4936 /* should we be calling the parent or the wined3d surface? */
4937 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
4938 if (NULL != tmp) IWineD3DSurface_Release(tmp);
4940 /** TODO: glEnable/glDisable on depth/stencil depending on
4941 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
4942 **********************************************************/
4949 /* Internal functions not in DirectX */
4950 /** TODO: move this off to the opengl context manager
4951 *(the swapchain doesn't need to know anything about offscreen rendering!)
4952 ****************************************************/
4954 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
4956 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4958 TRACE("(%p), %p\n", This, swapchain);
4960 if (swapchain->win != swapchain->drawable) {
4961 /* Set everything back the way it ws */
4962 swapchain->render_ctx = swapchain->glCtx;
4963 swapchain->drawable = swapchain->win;
4967 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
4968 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
4969 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4972 unsigned int height;
4973 WINED3DFORMAT format;
4974 WINED3DSURFACE_DESC surfaceDesc;
4975 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
4976 surfaceDesc.Width = &width;
4977 surfaceDesc.Height = &height;
4978 surfaceDesc.Format = &format;
4979 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
4981 /* I need a get width/height function (and should do something with the format) */
4982 for (i = 0; i < CONTEXT_CACHE; ++i) {
4983 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
4984 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
4985 the pSurface can be set to 0 allowing it to be reused from cache **/
4986 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
4987 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
4988 *context = &This->contextCache[i];
4991 if (This->contextCache[i].Width == 0) {
4992 This->contextCache[i].pSurface = pSurface;
4993 This->contextCache[i].Width = width;
4994 This->contextCache[i].Height = height;
4995 *context = &This->contextCache[i];
4999 if (i == CONTEXT_CACHE) {
5000 int minUsage = 0x7FFFFFFF; /* MAX_INT */
5001 glContext *dropContext = 0;
5002 for (i = 0; i < CONTEXT_CACHE; i++) {
5003 if (This->contextCache[i].usedcount < minUsage) {
5004 dropContext = &This->contextCache[i];
5005 minUsage = This->contextCache[i].usedcount;
5008 /* clean up the context (this doesn't work for ATI at the moment */
5010 glXDestroyContext(swapchain->display, dropContext->context);
5011 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
5014 dropContext->Width = 0;
5015 dropContext->pSurface = pSurface;
5016 *context = dropContext;
5018 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
5019 for (i = 0; i < CONTEXT_CACHE; i++) {
5020 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
5024 if (*context != NULL)
5027 return E_OUTOFMEMORY;
5030 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
5031 * the functionality needs splitting up so that we don't do more than we should do.
5032 * this only seems to impact performance a little.
5033 ******************************/
5034 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5035 IWineD3DSurface *RenderSurface) {
5036 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5038 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
5039 HRESULT ret = D3DERR_INVALIDCALL;
5040 IWineD3DSurface *tmp;
5042 * Currently only active for GLX >= 1.3
5043 * for others versions we'll have to use GLXPixmaps
5045 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
5046 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
5047 * so only check OpenGL version
5048 * ..........................
5049 * I don't believe that it is a problem with NVidia headers,
5050 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
5051 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
5053 * Your application will report GLX version 1.2 on glXQueryVersion.
5054 * However, it is safe to call the GLX 1.3 functions as described below.
5056 #if defined(GL_VERSION_1_3)
5058 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
5059 GLXFBConfig* cfgs = NULL;
5063 IWineD3DSwapChain *currentSwapchain;
5064 IWineD3DSwapChainImpl *swapchain;
5065 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
5066 * but switch them off if the StencilSurface is set to NULL
5067 ** *********************************************************/
5068 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
5069 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
5072 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
5073 it StencilSurface != NULL && zBufferTarget == NULL switch it on
5076 #define PUSH1(att) attribs[nAttribs++] = (att);
5077 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
5079 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
5081 /** TODO: remove the reff to Impl (context manager should fix this!) **/
5082 IWineD3DSwapChainImpl *impSwapChain;
5083 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
5084 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
5085 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
5090 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
5091 PUSH2(GLX_X_RENDERABLE, TRUE);
5092 PUSH2(GLX_DOUBLEBUFFER, TRUE);
5093 TRACE("calling makeglcfg\n");
5094 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
5097 TRACE("calling chooseFGConfig\n");
5098 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5101 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
5102 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
5103 why we failed and only show this message once! */
5104 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"); /**/
5106 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
5107 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
5108 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
5109 PUSH2(GLX_DOUBLEBUFFER, FALSE);
5110 TRACE("calling makeglcfg\n");
5111 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
5113 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5120 for (i = 0; i < nCfgs; ++i) {
5121 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
5122 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
5123 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
5126 if (NULL != This->renderTarget) {
5128 vcheckGLcall("glFlush");
5129 /** This is only useful if the old render target was a swapchain,
5130 * we need to supercede this with a function that displays
5131 * the current buffer on the screen. This is easy to do in glx1.3 but
5132 * we need to do copy-write pixels in glx 1.2.
5133 ************************************************/
5134 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
5136 printf("Hit Enter to get next frame ...\n");
5142 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain) != D3D_OK) {
5143 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
5144 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
5148 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
5149 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
5150 **********************************************************************/
5151 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == D3D_OK) {
5152 /* We also need to make sure that the lights &co are also in the context of the swapchains */
5153 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
5154 TRACE("making swapchain active\n");
5155 if (RenderSurface != This->renderTarget) {
5156 if (RenderSurface == swapchain->backBuffer) {
5158 /* This could be flagged so that some operations work directly with the front buffer */
5159 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
5161 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
5163 TRACE("Error in setting current context: context %p drawable %ld !\n",
5164 impSwapChain->glCtx, impSwapChain->win);
5167 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5169 checkGLcall("glXMakeContextCurrent");
5171 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5173 else if (pbuffer_support == TRUE && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
5175 /** ********************************************************************
5176 * This is a quickly hacked out implementation of offscreen textures.
5177 * It will work in most cases but there may be problems if the client
5178 * modifies the texture directly, or expects the contents of the rendertarget
5181 * There are some real speed vs compatibility issues here:
5182 * we should really use a new context for every texture, but that eats ram.
5183 * we should also be restoring the texture to the pbuffer but that eats CPU
5184 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
5185 * but if this means reusing the display backbuffer then we need to make sure that
5186 * states are correctly preserved.
5187 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
5188 * and gain a good performance increase at the cost of compatibility.
5189 * I would suggest that, when this is the case, a user configurable flag be made
5190 * available, allowing the user to choose the best emmulated experience for them.
5191 *********************************************************************/
5193 XVisualInfo *visinfo;
5194 glContext *newContext;
5196 /* Here were using a shared context model */
5197 if (D3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
5198 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5201 /* If the context doesn't exist then create a new one */
5202 /* TODO: This should really be part of findGlContext */
5203 if (NULL == newContext->context) {
5205 TRACE("making new buffer\n");
5207 PUSH2(GLX_PBUFFER_WIDTH, newContext->Width);
5208 PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
5211 newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
5213 /** ****************************************
5214 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
5216 * In future releases, we may provide the calls glXCreateNewContext,
5217 * glXQueryDrawable and glXMakeContextCurrent.
5218 * so until then we have to use glXGetVisualFromFBConfig &co..
5219 ********************************************/
5222 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
5224 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
5226 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
5230 if (NULL == newContext || NULL == newContext->context) {
5231 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5233 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
5234 if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
5235 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
5238 /* Clean up the old context */
5239 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5240 /* Set the current context of the swapchain to the new context */
5241 impSwapChain->drawable = newContext->drawable;
5242 impSwapChain->render_ctx = newContext->context;
5246 #if 1 /* Apply the stateblock to the new context
5247 FIXME: This is a bit of a hack, each context should know it's own state,
5248 the directX current directX state should then be applied to the context */
5251 IWineD3DStateBlockImpl *oldUpdateStateBlock;
5252 oldUpdateStateBlock = This->updateStateBlock;
5253 oldRecording= This->isRecordingState;
5254 This->isRecordingState = FALSE;
5255 This->updateStateBlock = This->stateBlock;
5256 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
5258 This->isRecordingState = oldRecording;
5259 This->updateStateBlock = oldUpdateStateBlock;
5264 /* clean up the current rendertargets swapchain (if it belonged to one) */
5265 if (currentSwapchain != NULL) {
5266 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
5269 /* Were done with the opengl context management, setup the rendertargets */
5271 tmp = This->renderTarget;
5272 This->renderTarget = RenderSurface;
5273 IWineD3DSurface_AddRef(This->renderTarget);
5274 IWineD3DSurface_Release(tmp);
5280 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
5281 /* Check that the container is not a swapchain member */
5283 IWineD3DSwapChain *tmpSwapChain;
5284 if (D3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
5285 This->renderUpsideDown = TRUE;
5287 This->renderUpsideDown = FALSE;
5288 IWineD3DSwapChain_Release(tmpSwapChain);
5290 /* Force updating the cull mode */
5291 TRACE("setting render state\n");
5292 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
5293 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
5295 /* Force updating projection matrix */
5296 This->last_was_rhw = FALSE;
5297 This->proj_valid = FALSE;
5305 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
5306 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
5311 if ( NULL != impSwapChain) {
5312 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
5320 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
5321 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
5322 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5323 /* TODO: the use of Impl is deprecated. */
5324 /* some basic validation checks */
5325 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
5327 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
5329 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
5330 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
5331 return D3DERR_INVALIDCALL;
5333 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
5334 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
5335 return D3DERR_INVALIDCALL;
5337 /* TODO: make the cursor 'real' */
5339 This->xHotSpot = XHotSpot;
5340 This->yHotSpot = YHotSpot;
5345 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
5346 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5347 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
5349 This->xScreenSpace = XScreenSpace;
5350 This->yScreenSpace = YScreenSpace;
5356 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
5357 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5358 TRACE("(%p) : visible(%d)\n", This, bShow);
5360 This->bCursorVisible = bShow;
5365 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
5366 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5367 FIXME("(%p) : stub\n", This); /* No way of notifying yet! */
5372 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
5373 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5374 /** FIXME: Resource tracking needs to be done,
5375 * The closes we can do to this is set the priorities of all managed textures low
5376 * and then reset them.
5377 ***********************************************************/
5378 FIXME("(%p) : stub\n", This);
5382 HRESULT WINAPI IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
5383 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5384 /** FIXME: Resource trascking needs to be done.
5385 * in effect this pulls all non only default
5386 * textures out of video memory and deletes all glTextures (glDeleteTextures)
5387 * and should clear down the context and set it up according to pPresentationParameters
5388 ***********************************************************/
5389 FIXME("(%p) : stub\n", This);
5393 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
5394 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5395 /** FIXME: always true at the moment **/
5396 if(bEnableDialogs == FALSE) {
5397 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
5403 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
5404 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5406 FIXME("(%p) : stub\n", This);
5407 /* Setup some reasonable defaults */
5408 pParameters->AdapterOrdinal = 0; /* always for now */
5409 pParameters->DeviceType = D3DDEVTYPE_HAL; /* always for now */
5410 pParameters->hFocusWindow = 0;
5411 pParameters->BehaviorFlags =0;
5415 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
5416 IWineD3DSwapChain *swapchain;
5417 HRESULT hrc = D3D_OK;
5419 TRACE("Relaying to swapchain\n");
5421 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
5422 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (D3DGAMMARAMP *)pRamp);
5423 IWineD3DSwapChain_Release(swapchain);
5428 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
5429 IWineD3DSwapChain *swapchain;
5430 HRESULT hrc = D3D_OK;
5432 TRACE("Relaying to swapchain\n");
5434 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
5435 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
5436 IWineD3DSwapChain_Release(swapchain);
5442 /** ********************************************************
5443 * Notification functions
5444 ** ********************************************************/
5445 /** This function must be called in the release of a resource when ref == 0,
5446 * the contents of resource must still be correct,
5447 * any handels to other resource held by the caller must be closed
5448 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
5449 *****************************************************/
5450 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5451 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5452 ResourceList* resourceList;
5454 TRACE("(%p) : resource %p\n", This, resource);
5456 EnterCriticalSection(&resourceStoreCriticalSection);
5458 /* add a new texture to the frot of the linked list */
5459 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
5460 resourceList->resource = resource;
5462 /* Get the old head */
5463 resourceList->next = This->resources;
5465 This->resources = resourceList;
5466 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
5469 LeaveCriticalSection(&resourceStoreCriticalSection);
5474 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5475 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5476 ResourceList* resourceList = NULL;
5477 ResourceList* previousResourceList = NULL;
5479 TRACE("(%p) : resource %p\n", This, resource);
5482 EnterCriticalSection(&resourceStoreCriticalSection);
5484 resourceList = This->resources;
5486 while (resourceList != NULL) {
5487 if(resourceList->resource == resource) break;
5488 previousResourceList = resourceList;
5489 resourceList = resourceList->next;
5492 if (resourceList == NULL) {
5493 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
5495 LeaveCriticalSection(&resourceStoreCriticalSection);
5499 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
5501 /* make sure we don't leave a hole in the list */
5502 if (previousResourceList != NULL) {
5503 previousResourceList->next = resourceList->next;
5505 This->resources = resourceList->next;
5509 LeaveCriticalSection(&resourceStoreCriticalSection);
5515 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
5516 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5519 TRACE("(%p) : resource %p\n", This, resource);
5520 switch(IWineD3DResource_GetType(resource)){
5521 case D3DRTYPE_SURFACE:
5522 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
5524 case D3DRTYPE_TEXTURE:
5525 case D3DRTYPE_CUBETEXTURE:
5526 case D3DRTYPE_VOLUMETEXTURE:
5527 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
5528 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5529 IUnknown *textureParent;
5530 IWineD3DBaseTexture_GetParent(This->stateBlock->textures[counter], &textureParent);
5531 /* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
5532 FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter, resource, textureParent);
5533 IUnknown_Release(textureParent);
5534 This->stateBlock->textures[counter] = NULL;
5536 if (This->updateStateBlock != This->stateBlock ){
5537 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5538 IUnknown *textureParent;
5539 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[counter], &textureParent);
5540 /* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
5541 FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter, resource, textureParent);
5542 IUnknown_Release(textureParent);
5543 This->updateStateBlock->textures[counter] = NULL;
5548 case D3DRTYPE_VOLUME:
5549 /* TODO: nothing really? */
5551 case D3DRTYPE_VERTEXBUFFER:
5552 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
5555 TRACE("Cleaning up stream pointers\n");
5557 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
5558 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
5559 FINDOUT: should changes.streamSource[StreamNumber] be set ?
5561 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5562 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
5563 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
5564 This->updateStateBlock->streamSource[streamNumber] = 0;
5565 /* Set changed flag? */
5568 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) */
5569 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
5570 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
5571 This->stateBlock->streamSource[streamNumber] = 0;
5574 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
5575 else { /* This shouldn't happen */
5576 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
5583 case D3DRTYPE_INDEXBUFFER:
5584 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
5585 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5586 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5587 This->updateStateBlock->pIndexData = NULL;
5590 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
5591 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5592 This->stateBlock->pIndexData = NULL;
5598 FIXME("(%p) unknown resource type %p %u \n", This, resource, IWineD3DResource_GetType(resource));
5603 /* Remove the resoruce from the resourceStore */
5604 IWineD3DDeviceImpl_RemoveResource(iface, resource);
5606 TRACE("Resource released\n");
5611 /** This function is to be called by the swapchain when it is released and it's ref = 0
5612 *****************************************************/
5613 void WINAPI IWineD3DDeviceImpl_SwapChainReleased(IWineD3DDevice *iface, IWineD3DSwapChain *swapChain){
5614 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5615 SwapChainList **nextSwapchain;
5616 nextSwapchain = &This->swapchains;
5618 /* Check to see if the swapchian is being used as the render target */
5619 if (This->renderTarget != NULL) {
5620 IWineD3DSurface *swapchainBackBuffer;
5622 IWineD3DSwapChain_GetBackBuffer(swapChain, 0 ,( D3DBACKBUFFER_TYPE) 0, &swapchainBackBuffer);
5623 if (This->renderTarget == swapchainBackBuffer) {
5624 /* Don't know what to do, so warn and carry on as usual (which in this case leaves the renderterget in limbo) */
5625 FIXME("Atempting to release a swapchain that is currently beuing used as a render target, behaviour is undefined\n");
5629 /* Go through the swapchain list and try to find the swapchain being released */
5630 while(*nextSwapchain != NULL && (*nextSwapchain)->swapchain != swapChain) {
5631 nextSwapchain = &(*nextSwapchain)->next;
5634 /* Check to see if we found the swapchain */
5635 if (NULL != *nextSwapchain) {
5636 /* We found the swapchain so remove it from the list */
5637 TRACE("(%p) releasing swapchain(%p)\n", iface, swapChain);
5638 HeapFree(GetProcessHeap(), 0 , *nextSwapchain);
5639 *nextSwapchain = (*nextSwapchain)->next;
5641 /* We didn't find the swapchain on the list, this can only heppen because of a programming error in wined3d */
5642 FIXME("(%p) Attempting to release a swapchain (%p) that hasn't been stored\n", iface, swapChain);
5645 TRACE("swapchain (%p) released\n", swapChain);
5649 /**********************************************************
5650 * IWineD3DDevice VTbl follows
5651 **********************************************************/
5653 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
5655 /*** IUnknown methods ***/
5656 IWineD3DDeviceImpl_QueryInterface,
5657 IWineD3DDeviceImpl_AddRef,
5658 IWineD3DDeviceImpl_Release,
5659 /*** IWineD3DDevice methods ***/
5660 IWineD3DDeviceImpl_GetParent,
5661 /*** Creation methods**/
5662 IWineD3DDeviceImpl_CreateVertexBuffer,
5663 IWineD3DDeviceImpl_CreateIndexBuffer,
5664 IWineD3DDeviceImpl_CreateStateBlock,
5665 IWineD3DDeviceImpl_CreateSurface,
5666 IWineD3DDeviceImpl_CreateTexture,
5667 IWineD3DDeviceImpl_CreateVolumeTexture,
5668 IWineD3DDeviceImpl_CreateVolume,
5669 IWineD3DDeviceImpl_CreateCubeTexture,
5670 IWineD3DDeviceImpl_CreateQuery,
5671 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
5672 IWineD3DDeviceImpl_CreateVertexDeclaration,
5673 IWineD3DDeviceImpl_CreateVertexShader,
5674 IWineD3DDeviceImpl_CreatePixelShader,
5676 /*** Odd functions **/
5677 IWineD3DDeviceImpl_EvictManagedResources,
5678 IWineD3DDeviceImpl_GetAvailableTextureMem,
5679 IWineD3DDeviceImpl_GetBackBuffer,
5680 IWineD3DDeviceImpl_GetCreationParameters,
5681 IWineD3DDeviceImpl_GetDeviceCaps,
5682 IWineD3DDeviceImpl_GetDirect3D,
5683 IWineD3DDeviceImpl_GetDisplayMode,
5684 IWineD3DDeviceImpl_GetNumberOfSwapChains,
5685 IWineD3DDeviceImpl_GetRasterStatus,
5686 IWineD3DDeviceImpl_GetSwapChain,
5687 IWineD3DDeviceImpl_Reset,
5688 IWineD3DDeviceImpl_SetDialogBoxMode,
5689 IWineD3DDeviceImpl_SetCursorProperties,
5690 IWineD3DDeviceImpl_SetCursorPosition,
5691 IWineD3DDeviceImpl_ShowCursor,
5692 IWineD3DDeviceImpl_TestCooperativeLevel,
5693 /*** Getters and setters **/
5694 IWineD3DDeviceImpl_SetClipPlane,
5695 IWineD3DDeviceImpl_GetClipPlane,
5696 IWineD3DDeviceImpl_SetClipStatus,
5697 IWineD3DDeviceImpl_GetClipStatus,
5698 IWineD3DDeviceImpl_SetCurrentTexturePalette,
5699 IWineD3DDeviceImpl_GetCurrentTexturePalette,
5700 IWineD3DDeviceImpl_SetDepthStencilSurface,
5701 IWineD3DDeviceImpl_GetDepthStencilSurface,
5702 IWineD3DDeviceImpl_SetFVF,
5703 IWineD3DDeviceImpl_GetFVF,
5704 IWineD3DDeviceImpl_SetGammaRamp,
5705 IWineD3DDeviceImpl_GetGammaRamp,
5706 IWineD3DDeviceImpl_SetIndices,
5707 IWineD3DDeviceImpl_GetIndices,
5708 IWineD3DDeviceImpl_SetLight,
5709 IWineD3DDeviceImpl_GetLight,
5710 IWineD3DDeviceImpl_SetLightEnable,
5711 IWineD3DDeviceImpl_GetLightEnable,
5712 IWineD3DDeviceImpl_SetMaterial,
5713 IWineD3DDeviceImpl_GetMaterial,
5714 IWineD3DDeviceImpl_SetNPatchMode,
5715 IWineD3DDeviceImpl_GetNPatchMode,
5716 IWineD3DDeviceImpl_SetPaletteEntries,
5717 IWineD3DDeviceImpl_GetPaletteEntries,
5718 IWineD3DDeviceImpl_SetPixelShader,
5719 IWineD3DDeviceImpl_GetPixelShader,
5720 IWineD3DDeviceImpl_SetPixelShaderConstantB,
5721 IWineD3DDeviceImpl_GetPixelShaderConstantB,
5722 IWineD3DDeviceImpl_SetPixelShaderConstantI,
5723 IWineD3DDeviceImpl_GetPixelShaderConstantI,
5724 IWineD3DDeviceImpl_SetPixelShaderConstantF,
5725 IWineD3DDeviceImpl_GetPixelShaderConstantF,
5726 IWineD3DDeviceImpl_SetRenderState,
5727 IWineD3DDeviceImpl_GetRenderState,
5728 IWineD3DDeviceImpl_SetRenderTarget,
5729 IWineD3DDeviceImpl_GetRenderTarget,
5730 IWineD3DDeviceImpl_SetSamplerState,
5731 IWineD3DDeviceImpl_GetSamplerState,
5732 IWineD3DDeviceImpl_SetScissorRect,
5733 IWineD3DDeviceImpl_GetScissorRect,
5734 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
5735 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
5736 IWineD3DDeviceImpl_SetStreamSource,
5737 IWineD3DDeviceImpl_GetStreamSource,
5738 IWineD3DDeviceImpl_SetStreamSourceFreq,
5739 IWineD3DDeviceImpl_GetStreamSourceFreq,
5740 IWineD3DDeviceImpl_SetTexture,
5741 IWineD3DDeviceImpl_GetTexture,
5742 IWineD3DDeviceImpl_SetTextureStageState,
5743 IWineD3DDeviceImpl_GetTextureStageState,
5744 IWineD3DDeviceImpl_SetTransform,
5745 IWineD3DDeviceImpl_GetTransform,
5746 IWineD3DDeviceImpl_SetVertexDeclaration,
5747 IWineD3DDeviceImpl_GetVertexDeclaration,
5748 IWineD3DDeviceImpl_SetVertexShader,
5749 IWineD3DDeviceImpl_GetVertexShader,
5750 IWineD3DDeviceImpl_SetVertexShaderConstantB,
5751 IWineD3DDeviceImpl_GetVertexShaderConstantB,
5752 IWineD3DDeviceImpl_SetVertexShaderConstantI,
5753 IWineD3DDeviceImpl_GetVertexShaderConstantI,
5754 IWineD3DDeviceImpl_SetVertexShaderConstantF,
5755 IWineD3DDeviceImpl_GetVertexShaderConstantF,
5756 IWineD3DDeviceImpl_SetViewport,
5757 IWineD3DDeviceImpl_GetViewport,
5758 IWineD3DDeviceImpl_MultiplyTransform,
5759 IWineD3DDeviceImpl_ValidateDevice,
5760 IWineD3DDeviceImpl_ProcessVertices,
5761 /*** State block ***/
5762 IWineD3DDeviceImpl_BeginStateBlock,
5763 IWineD3DDeviceImpl_EndStateBlock,
5764 /*** Scene management ***/
5765 IWineD3DDeviceImpl_BeginScene,
5766 IWineD3DDeviceImpl_EndScene,
5767 IWineD3DDeviceImpl_Present,
5768 IWineD3DDeviceImpl_Clear,
5770 IWineD3DDeviceImpl_DrawPrimitive,
5771 IWineD3DDeviceImpl_DrawIndexedPrimitive,
5772 IWineD3DDeviceImpl_DrawPrimitiveUP,
5773 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
5774 IWineD3DDeviceImpl_DrawRectPatch,
5775 IWineD3DDeviceImpl_DrawTriPatch,
5776 IWineD3DDeviceImpl_DeletePatch,
5777 IWineD3DDeviceImpl_ColorFill,
5778 IWineD3DDeviceImpl_UpdateTexture,
5779 IWineD3DDeviceImpl_UpdateSurface,
5780 IWineD3DDeviceImpl_StretchRect,
5781 IWineD3DDeviceImpl_GetRenderTargetData,
5782 IWineD3DDeviceImpl_GetFrontBufferData,
5783 /*** Internal use IWineD3DDevice methods ***/
5784 IWineD3DDeviceImpl_SetupTextureStates,
5785 IWineD3DDeviceImpl_SwapChainReleased,
5786 /*** object tracking ***/
5787 IWineD3DDeviceImpl_ResourceReleased
5791 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
5792 WINED3DRS_ALPHABLENDENABLE ,
5793 WINED3DRS_ALPHAFUNC ,
5794 WINED3DRS_ALPHAREF ,
5795 WINED3DRS_ALPHATESTENABLE ,
5797 WINED3DRS_COLORWRITEENABLE ,
5798 WINED3DRS_DESTBLEND ,
5799 WINED3DRS_DITHERENABLE ,
5800 WINED3DRS_FILLMODE ,
5801 WINED3DRS_FOGDENSITY ,
5803 WINED3DRS_FOGSTART ,
5804 WINED3DRS_LASTPIXEL ,
5805 WINED3DRS_SHADEMODE ,
5806 WINED3DRS_SRCBLEND ,
5807 WINED3DRS_STENCILENABLE ,
5808 WINED3DRS_STENCILFAIL ,
5809 WINED3DRS_STENCILFUNC ,
5810 WINED3DRS_STENCILMASK ,
5811 WINED3DRS_STENCILPASS ,
5812 WINED3DRS_STENCILREF ,
5813 WINED3DRS_STENCILWRITEMASK ,
5814 WINED3DRS_STENCILZFAIL ,
5815 WINED3DRS_TEXTUREFACTOR ,
5826 WINED3DRS_ZWRITEENABLE
5829 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
5830 WINED3DTSS_ADDRESSW ,
5831 WINED3DTSS_ALPHAARG0 ,
5832 WINED3DTSS_ALPHAARG1 ,
5833 WINED3DTSS_ALPHAARG2 ,
5834 WINED3DTSS_ALPHAOP ,
5835 WINED3DTSS_BUMPENVLOFFSET ,
5836 WINED3DTSS_BUMPENVLSCALE ,
5837 WINED3DTSS_BUMPENVMAT00 ,
5838 WINED3DTSS_BUMPENVMAT01 ,
5839 WINED3DTSS_BUMPENVMAT10 ,
5840 WINED3DTSS_BUMPENVMAT11 ,
5841 WINED3DTSS_COLORARG0 ,
5842 WINED3DTSS_COLORARG1 ,
5843 WINED3DTSS_COLORARG2 ,
5844 WINED3DTSS_COLOROP ,
5845 WINED3DTSS_RESULTARG ,
5846 WINED3DTSS_TEXCOORDINDEX ,
5847 WINED3DTSS_TEXTURETRANSFORMFLAGS
5850 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
5851 WINED3DSAMP_ADDRESSU ,
5852 WINED3DSAMP_ADDRESSV ,
5853 WINED3DSAMP_ADDRESSW ,
5854 WINED3DSAMP_BORDERCOLOR ,
5855 WINED3DSAMP_MAGFILTER ,
5856 WINED3DSAMP_MINFILTER ,
5857 WINED3DSAMP_MIPFILTER ,
5858 WINED3DSAMP_MIPMAPLODBIAS ,
5859 WINED3DSAMP_MAXMIPLEVEL ,
5860 WINED3DSAMP_MAXANISOTROPY ,
5861 WINED3DSAMP_SRGBTEXTURE ,
5862 WINED3DSAMP_ELEMENTINDEX
5865 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
5867 WINED3DRS_AMBIENTMATERIALSOURCE ,
5868 WINED3DRS_CLIPPING ,
5869 WINED3DRS_CLIPPLANEENABLE ,
5870 WINED3DRS_COLORVERTEX ,
5871 WINED3DRS_DIFFUSEMATERIALSOURCE ,
5872 WINED3DRS_EMISSIVEMATERIALSOURCE ,
5873 WINED3DRS_FOGDENSITY ,
5875 WINED3DRS_FOGSTART ,
5876 WINED3DRS_FOGTABLEMODE ,
5877 WINED3DRS_FOGVERTEXMODE ,
5878 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
5879 WINED3DRS_LIGHTING ,
5880 WINED3DRS_LOCALVIEWER ,
5881 WINED3DRS_MULTISAMPLEANTIALIAS ,
5882 WINED3DRS_MULTISAMPLEMASK ,
5883 WINED3DRS_NORMALIZENORMALS ,
5884 WINED3DRS_PATCHEDGESTYLE ,
5885 WINED3DRS_POINTSCALE_A ,
5886 WINED3DRS_POINTSCALE_B ,
5887 WINED3DRS_POINTSCALE_C ,
5888 WINED3DRS_POINTSCALEENABLE ,
5889 WINED3DRS_POINTSIZE ,
5890 WINED3DRS_POINTSIZE_MAX ,
5891 WINED3DRS_POINTSIZE_MIN ,
5892 WINED3DRS_POINTSPRITEENABLE ,
5893 WINED3DRS_RANGEFOGENABLE ,
5894 WINED3DRS_SPECULARMATERIALSOURCE ,
5895 WINED3DRS_TWEENFACTOR ,
5896 WINED3DRS_VERTEXBLEND
5899 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
5900 WINED3DTSS_TEXCOORDINDEX ,
5901 WINED3DTSS_TEXTURETRANSFORMFLAGS
5904 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
5905 WINED3DSAMP_DMAPOFFSET