2 * IWineD3DDevice implementation
4 * Copyright 2002-2005 Jason Edmeades
5 * Copyright 2003-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "wined3d_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
28 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
29 WINE_DECLARE_DEBUG_CHANNEL(d3d_fps);
30 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
31 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
33 /* x11drv GDI escapes */
34 #define X11DRV_ESCAPE 6789
35 enum x11drv_escape_codes
37 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
38 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
39 X11DRV_GET_FONT, /* get current X font for a DC */
42 /* retrieve the X display to use on a given DC */
43 inline static Display *get_display( HDC hdc )
46 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
48 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
49 sizeof(display), (LPSTR)&display )) display = NULL;
53 /* Memory tracking and object counting */
54 static unsigned int emulated_textureram = 64*1024*1024;
56 /* TODO: setup some flags in the regestry to enable, disable pbuffer support */
57 /* enable pbuffer support for offscreen textures */
58 BOOL pbuffer_support = FALSE;
59 /* allocate one pbuffer per surface */
60 BOOL pbuffer_per_surface = FALSE;
62 /* static function declarations */
63 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
65 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type);
68 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return D3DERR_OUTOFVIDEOMEMORY;}
70 #define D3DCREATEOBJECTINSTANCE(object, type) { \
71 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
72 D3DMEMCHECK(object, pp##type); \
73 object->lpVtbl = &IWineD3D##type##_Vtbl; \
74 object->wineD3DDevice = This; \
75 object->parent = parent; \
77 *pp##type = (IWineD3D##type *) object; \
80 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
81 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
82 D3DMEMCHECK(object, pp##type); \
83 object->lpVtbl = &IWineD3D##type##_Vtbl; \
84 object->resource.wineD3DDevice = This; \
85 object->resource.parent = parent; \
86 object->resource.resourceType = d3dtype; \
87 object->resource.ref = 1; \
88 object->resource.pool = Pool; \
89 object->resource.format = Format; \
90 object->resource.usage = Usage; \
91 object->resource.size = _size; \
92 /* Check that we have enough video ram left */ \
93 if (Pool == D3DPOOL_DEFAULT) { \
94 if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
95 WARN("Out of 'bogus' video memory\n"); \
96 HeapFree(GetProcessHeap(), 0, object); \
98 return D3DERR_OUTOFVIDEOMEMORY; \
100 globalChangeGlRam(_size); \
102 object->resource.allocatedMemory = (0 == _size ? NULL : Pool == D3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
103 if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != D3DPOOL_DEFAULT) { \
104 FIXME("Out of memory!\n"); \
105 HeapFree(GetProcessHeap(), 0, object); \
107 return D3DERR_OUTOFVIDEOMEMORY; \
109 *pp##type = (IWineD3D##type *) object; \
110 IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
111 TRACE("(%p) : Created resource %p\n", This, object); \
114 #define D3DINITILIZEBASETEXTURE(_basetexture) { \
115 _basetexture.levels = Levels; \
116 _basetexture.filterType = (Usage & D3DUSAGE_AUTOGENMIPMAP) ? D3DTEXF_LINEAR : D3DTEXF_NONE; \
117 _basetexture.LOD = 0; \
118 _basetexture.dirty = TRUE; \
121 /**********************************************************
122 * Global variable / Constants follow
123 **********************************************************/
124 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
126 /**********************************************************
127 * Utility functions follow
128 **********************************************************/
129 /* Convert the D3DLIGHT properties into equivalent gl lights */
130 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
133 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
134 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
136 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
137 glMatrixMode(GL_MODELVIEW);
139 glLoadMatrixf((float *)&This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
142 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
143 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
144 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
145 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
146 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
147 checkGLcall("glLightfv");
150 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
151 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
152 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
153 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
154 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
155 checkGLcall("glLightfv");
158 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
159 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
160 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
161 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
162 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
163 checkGLcall("glLightfv");
165 /* Attenuation - Are these right? guessing... */
166 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
167 checkGLcall("glLightf");
168 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
169 checkGLcall("glLightf");
171 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) != 0) {
172 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
174 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
177 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
178 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
179 checkGLcall("glLightf");
181 switch (lightInfo->OriginalParms.Type) {
184 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
185 checkGLcall("glLightfv");
186 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
187 checkGLcall("glLightf");
193 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
194 checkGLcall("glLightfv");
196 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
197 checkGLcall("glLightfv");
198 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
199 checkGLcall("glLightf");
200 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
201 checkGLcall("glLightf");
205 case D3DLIGHT_DIRECTIONAL:
207 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
208 checkGLcall("glLightfv");
209 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
210 checkGLcall("glLightf");
211 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
212 checkGLcall("glLightf");
216 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
219 /* Restore the modelview matrix */
223 /* Apply the current values to the specified texture stage */
224 void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Sampler, DWORD Flags) {
225 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
233 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
234 clamping, MIPLOD, etc. This will work for up to 16 samplers.
237 if (Sampler >= GL_LIMITS(samplers)) {
238 FIXME("Trying to set the state of more samplers %ld than are supported %d by this openGL implementation\n", Sampler, GL_LIMITS(samplers));
241 VTRACE(("Activating appropriate texture state %ld\n", Sampler));
242 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
244 GLACTIVETEXTURE(Sampler);
246 /* Could we use bindTexture and then apply the states instead of GLACTIVETEXTURE */
247 } else if (Sampler > 0) {
248 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
252 /* TODO: change this to a lookup table
253 LOOKUP_TEXTURE_STATES lists all texture states that should be applied.
254 LOOKUP_CONTEXT_SATES list all context applicable states that can be applied
255 etc.... it's a lot cleaner, quicker and possibly easier to maintain than running a switch and setting a skip flag...
256 especially when there are a number of groups of states. */
258 TRACE("-----------------------> Updating the texture at Sampler %ld to have new texture state information\n", Sampler);
260 /* The list of states not to apply is a big as the list of states to apply, so it makes sense to produce an inclusive list */
261 #define APPLY_STATE(_state) IWineD3DDeviceImpl_ApplyTextureUnitState(iface, Sampler, _state)
262 /* these are the only two supported states that need to be applied */
263 APPLY_STATE(WINED3DTSS_TEXCOORDINDEX);
264 APPLY_STATE(WINED3DTSS_TEXTURETRANSFORMFLAGS);
265 #if 0 /* not supported at the moment */
266 APPLY_STATE(WINED3DTSS_BUMPENVMAT00);
267 APPLY_STATE(WINED3DTSS_BUMPENVMAT01);
268 APPLY_STATE(WINED3DTSS_BUMPENVMAT10);
269 APPLY_STATE(WINED3DTSS_BUMPENVMAT11);
270 APPLY_STATE(WINED3DTSS_BUMPENVLSCALE);
271 APPLY_STATE(WINED3DTSS_BUMPENVLOFFSET);
272 APPLY_STATE(WINED3DTSS_RESULTARG);
273 APPLY_STATE(WINED3DTSS_CONSTANT);
275 /* a quick sanity check in case someone forgot to update this function */
276 if (WINED3D_HIGHEST_TEXTURE_STATE > WINED3DTSS_CONSTANT) {
277 FIXME("(%p) : There are more texture states than expected, update device.c to match\n", This);
281 /* apply any sampler states that always need applying */
282 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
283 tmpvalue.d = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPMAPLODBIAS];
284 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
285 GL_TEXTURE_LOD_BIAS_EXT,
287 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
290 /* Note the D3DRS value applies to all textures, but GL has one
291 * per texture, so apply it now ready to be used!
293 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
294 /* Set the default alpha blend color */
295 glBlendColor(col[0], col[1], col[2], col[3]);
296 checkGLcall("glBlendColor");
298 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
299 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
300 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
302 TRACE("-----------------------> Updated the texture at Sampler %ld to have new texture state information\n", Sampler);
305 /**********************************************************
306 * IUnknown parts follows
307 **********************************************************/
309 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
311 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
312 /* FIXME: This needs to extend an IWineD3DBaseObject */
314 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
315 if (IsEqualGUID(riid, &IID_IUnknown)
316 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
317 IUnknown_AddRef(iface);
322 return E_NOINTERFACE;
325 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
326 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
327 ULONG refCount = InterlockedIncrement(&This->ref);
329 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
333 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
334 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
335 ULONG refCount = InterlockedDecrement(&This->ref);
337 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
340 /* TODO: Clean up all the surfaces and textures! */
341 /* FIXME: Create targets and state blocks in d3d8 */
342 if (((IWineD3DImpl *)This->wineD3D)->dxVersion > 8) { /*We don't create a state block in d3d8 yet*/
343 /* NOTE: You must release the parent if the object was created via a callback
344 ** ***************************/
345 IUnknown* swapChainParent;
347 /* NOTE: Don't release swapchain 0 here, it's 'special' */
348 SwapChainList *nextSwapchain = This->swapchains;
349 if (nextSwapchain != NULL) {
350 nextSwapchain = nextSwapchain->next;
352 WARN("Expected to find the implicit swapchain\n");
355 /* release all the other swapchains */
356 while (nextSwapchain != NULL) {
357 SwapChainList *prevSwapchain = nextSwapchain;
358 nextSwapchain = nextSwapchain->next;
359 IWineD3DSwapChain_Release(prevSwapchain->swapchain);
360 /* NOTE: no need to free the list element, it will be done by the release callback
361 HeapFree(GetProcessHeap(), 0, prevSwapchain); */
364 if (This->stateBlock != NULL) {
365 IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->stateBlock);
368 if (This->swapchains != NULL) {
369 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
370 IWineD3DSwapChain_GetParent(This->swapchains->swapchain, &swapChainParent);
371 IUnknown_Release(swapChainParent); /* once for the get parent */
372 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
373 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
378 IWineD3D_Release(This->wineD3D);
379 HeapFree(GetProcessHeap(), 0, This);
384 /**********************************************************
385 * IWineD3DDevice implementation follows
386 **********************************************************/
387 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
388 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
389 *pParent = This->parent;
390 IUnknown_AddRef(This->parent);
394 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
395 DWORD FVF, D3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
397 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
398 IWineD3DVertexBufferImpl *object;
399 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
400 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, D3DRTYPE_VERTEXBUFFER, Size)
403 if (Pool == D3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
404 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
408 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
409 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
414 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
415 WINED3DFORMAT Format, D3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
416 HANDLE *sharedHandle, IUnknown *parent) {
417 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
418 IWineD3DIndexBufferImpl *object;
419 TRACE("(%p) Creating index buffer\n", This);
421 /* Allocate the storage for the device */
422 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,D3DRTYPE_INDEXBUFFER, Length)
425 if (Pool == D3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
426 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
429 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
430 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
431 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
436 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
438 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
439 IWineD3DStateBlockImpl *object;
442 D3DCREATEOBJECTINSTANCE(object, StateBlock)
443 object->blockType = Type;
445 /* Special case - Used during initialization to produce a placeholder stateblock
446 so other functions called can update a state block */
447 if (Type == WINED3DSBT_INIT) {
448 /* Don't bother increasing the reference count otherwise a device will never
449 be freed due to circular dependencies */
453 /* Otherwise, might as well set the whole state block to the appropriate values */
454 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(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4)) >> 1;
620 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
621 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
622 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4));
624 Size = (pow2Width * D3DFmtGetBpp(This, Format)) * pow2Height;
627 /** Create the and initilise surface resource **/
628 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,D3DRTYPE_SURFACE, Size)
629 object->container = (IUnknown*) This;
631 object->currentDesc.Width = Width;
632 object->currentDesc.Height = Height;
633 object->currentDesc.MultiSampleType = MultiSample;
634 object->currentDesc.MultiSampleQuality = MultisampleQuality;
636 /* Setup some glformat defaults */
637 object->glDescription.glFormat = D3DFmt2GLFmt(This, object->resource.format);
638 object->glDescription.glFormatInternal = D3DFmt2GLIntFmt(This, object->resource.format);
639 object->glDescription.glType = D3DFmt2GLType(This, object->resource.format);
640 object->glDescription.textureName = 0;
641 object->glDescription.level = Level;
642 object->glDescription.target = GL_TEXTURE_2D;
645 object->pow2Width = pow2Width;
646 object->pow2Height = pow2Height;
647 object->nonpow2 = (pow2Width != Width || pow2Height != Height) ? TRUE : FALSE;
648 object->discard = Discard;
649 object->activeLock = FALSE;
650 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
651 object->pow2Size = (pow2Width * object->bytesPerPixel) * pow2Height;
653 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
655 TRACE("Pool %d %d %d %d",Pool, D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM);
657 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
658 * this function is too deap to need to care about things like this.
659 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
660 * ****************************************/
662 case D3DPOOL_SCRATCH:
663 if(Lockable == FALSE)
664 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
665 which are mutually exclusive, setting lockable to true\n");
668 case D3DPOOL_SYSTEMMEM:
669 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
670 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
671 case D3DPOOL_MANAGED:
672 if(Usage == D3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
673 Usage of DYNAMIC which are mutually exclusive, not doing \
674 anything just telling you.\n");
676 case D3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
677 if(!(Usage & D3DUSAGE_DYNAMIC) && !(Usage & D3DUSAGE_RENDERTARGET)
678 && !(Usage && D3DUSAGE_DEPTHSTENCIL ) && Lockable == TRUE)
679 FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
682 FIXME("(%p) Unknown pool %d\n", This, Pool);
686 if (Usage & D3DUSAGE_RENDERTARGET && Pool != D3DPOOL_DEFAULT) {
687 FIXME("Trying to create a render target that isn't in the default pool\n");
691 object->locked = FALSE;
692 object->lockable = (WINED3DFMT_D16_LOCKABLE == Format) ? TRUE : Lockable;
694 /* mark the texture as dirty so that it get's loaded first time around*/
695 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
696 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
697 This, Width, Height, Format, debug_d3dformat(Format),
698 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
703 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
704 DWORD Usage, WINED3DFORMAT Format, D3DPOOL Pool,
705 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
706 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
708 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
709 IWineD3DTextureImpl *object;
714 unsigned int pow2Width = Width;
715 unsigned int pow2Height = Height;
718 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) .... \n", This, Width, Height, Levels, Usage);
720 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, D3DRTYPE_TEXTURE, 0);
721 D3DINITILIZEBASETEXTURE(object->baseTexture);
722 object->width = Width;
723 object->height = Height;
725 /** Non-power2 support **/
726 /* Find the nearest pow2 match */
727 pow2Width = pow2Height = 1;
728 while (pow2Width < Width) pow2Width <<= 1;
729 while (pow2Height < Height) pow2Height <<= 1;
731 /** FIXME: add support for real non-power-two if it's provided by the video card **/
732 /* Precalculated scaling for 'faked' non power of two texture coords */
733 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
734 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
735 TRACE(" xf(%f) yf(%f) \n", object->pow2scalingFactorX, object->pow2scalingFactorY);
737 /* Calculate levels for mip mapping */
739 TRACE("calculating levels %d\n", object->baseTexture.levels);
740 object->baseTexture.levels++;
743 while (tmpW > 1 && tmpH > 1) {
744 tmpW = max(1, tmpW >> 1);
745 tmpH = max(1, tmpH >> 1);
746 object->baseTexture.levels++;
748 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
751 /* Generate all the surfaces */
754 for (i = 0; i < object->baseTexture.levels; i++)
756 /* use the callback to create the texture surface */
757 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
760 FIXME("Failed to create surface %p \n",object);
762 for(j = 0 ; j < i ; j++) {
763 IWineD3DSurface_Release(object->surfaces[j]);
765 /* heap free object */
766 HeapFree(GetProcessHeap(),0,object);
772 IWineD3DSurface_SetContainer(object->surfaces[i], (IUnknown *)object);
773 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
774 /* calculate the next mipmap level */
775 tmpW = max(1, tmpW >> 1);
776 tmpH = max(1, tmpH >> 1);
779 TRACE("(%p) : Created texture %p\n", This, object);
783 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
784 UINT Width, UINT Height, UINT Depth,
785 UINT Levels, DWORD Usage,
786 WINED3DFORMAT Format, D3DPOOL Pool,
787 IWineD3DVolumeTexture** ppVolumeTexture,
788 HANDLE* pSharedHandle, IUnknown *parent,
789 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
791 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
792 IWineD3DVolumeTextureImpl *object;
798 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, D3DRTYPE_VOLUMETEXTURE, 0);
799 D3DINITILIZEBASETEXTURE(object->baseTexture);
801 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
802 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
804 object->width = Width;
805 object->height = Height;
806 object->depth = Depth;
808 /* Calculate levels for mip mapping */
810 object->baseTexture.levels++;
814 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
815 tmpW = max(1, tmpW >> 1);
816 tmpH = max(1, tmpH >> 1);
817 tmpD = max(1, tmpD >> 1);
818 object->baseTexture.levels++;
820 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
823 /* Generate all the surfaces */
828 for (i = 0; i < object->baseTexture.levels; i++)
830 /* Create the volume */
831 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
832 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
834 /* Set it's container to this object */
835 IWineD3DVolume_SetContainer(object->volumes[i], (IUnknown *)object);
837 /* calcualte the next mipmap level */
838 tmpW = max(1, tmpW >> 1);
839 tmpH = max(1, tmpH >> 1);
840 tmpD = max(1, tmpD >> 1);
843 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
844 TRACE("(%p) : Created volume texture %p\n", This, object);
848 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
849 UINT Width, UINT Height, UINT Depth,
851 WINED3DFORMAT Format, D3DPOOL Pool,
852 IWineD3DVolume** ppVolume,
853 HANDLE* pSharedHandle, IUnknown *parent) {
855 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
856 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
858 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, D3DRTYPE_VOLUME, ((Width * D3DFmtGetBpp(This, Format)) * Height * Depth))
860 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
861 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
863 object->currentDesc.Width = Width;
864 object->currentDesc.Height = Height;
865 object->currentDesc.Depth = Depth;
866 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
868 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
869 object->lockable = TRUE;
870 object->locked = FALSE;
871 memset(&object->lockedBox, 0, sizeof(D3DBOX));
872 object->dirty = TRUE;
874 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
877 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
878 UINT Levels, DWORD Usage,
879 WINED3DFORMAT Format, D3DPOOL Pool,
880 IWineD3DCubeTexture** ppCubeTexture,
881 HANDLE* pSharedHandle, IUnknown *parent,
882 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
884 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
885 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
889 unsigned int pow2EdgeLength = EdgeLength;
891 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, D3DRTYPE_CUBETEXTURE, 0);
892 D3DINITILIZEBASETEXTURE(object->baseTexture);
894 TRACE("(%p) Create Cube Texture \n", This);
896 object->edgeLength = EdgeLength;
898 /** Non-power2 support **/
900 /* Find the nearest pow2 match */
902 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
904 /* TODO: support for native non-power 2 */
905 /* Precalculated scaling for 'faked' non power of two texture coords */
906 object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
908 /* Calculate levels for mip mapping */
910 object->baseTexture.levels++;
913 tmpW = max(1, tmpW / 2);
914 object->baseTexture.levels++;
916 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
919 /* Generate all the surfaces */
921 for (i = 0; i < object->baseTexture.levels; i++) {
923 /* Create the 6 faces */
924 for (j = 0; j < 6; j++) {
926 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
927 i /* Level */, &object->surfaces[j][i],pSharedHandle);
934 IWineD3DSurface_Release(object->surfaces[j][i]);
938 IWineD3DSurface_Release(object->surfaces[l][j]);
942 FIXME("(%p) Failed to create surface\n",object);
943 HeapFree(GetProcessHeap(),0,object);
944 *ppCubeTexture = NULL;
947 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IUnknown *)object);
948 TRACE("Created surface level %d @ %p, \n", i, object->surfaces[j][i]);
950 tmpW = max(1, tmpW >> 1);
953 TRACE("(%p) : Created Cube Texture %p\n", This, object);
954 *ppCubeTexture = (IWineD3DCubeTexture *) object;
958 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
959 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
960 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
962 if(NULL == ppQuery) {
963 /* Just a check to see if we support this type of query */
964 HRESULT hr = D3DERR_NOTAVAILABLE;
965 /* Lie and say everything is good (we can return ok fake data from a stub) */
967 case WINED3DQUERYTYPE_VCACHE:
968 case WINED3DQUERYTYPE_RESOURCEMANAGER:
969 case WINED3DQUERYTYPE_VERTEXSTATS:
970 case WINED3DQUERYTYPE_EVENT:
971 case WINED3DQUERYTYPE_OCCLUSION:
972 case WINED3DQUERYTYPE_TIMESTAMP:
973 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
974 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
975 case WINED3DQUERYTYPE_PIPELINETIMINGS:
976 case WINED3DQUERYTYPE_INTERFACETIMINGS:
977 case WINED3DQUERYTYPE_VERTEXTIMINGS:
978 case WINED3DQUERYTYPE_PIXELTIMINGS:
979 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
980 case WINED3DQUERYTYPE_CACHEUTILIZATION:
984 FIXME("(%p) Unhandled query type %d\n",This , Type);
986 FIXME("(%p) : Stub request for query type %d returned %ld\n", This, Type, hr);
990 D3DCREATEOBJECTINSTANCE(object, Query)
992 object->extendedData = 0;
993 TRACE("(%p) : Created Query %p\n", This, object);
997 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
998 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1000 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1001 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1002 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1005 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1007 XVisualInfo template;
1008 GLXContext oldContext;
1009 Drawable oldDrawable;
1010 HRESULT hr = D3D_OK;
1012 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1014 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1015 * does a device hold a reference to a swap chain giving them a lifetime of the device
1016 * or does the swap chain notify the device of it'd destruction.
1017 *******************************/
1019 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1021 /* Initialize other useful values */
1022 object->presentParms.BackBufferCount = 1; /* TODO:? support for gl_aux buffers */
1024 /*********************
1025 * Lookup the window Handle and the relating X window handle
1026 ********************/
1028 /* Setup hwnd we are using, plus which display this equates to */
1029 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1030 if (!object->win_handle) {
1031 object->win_handle = This->createParms.hFocusWindow;
1034 object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window" );
1035 hDc = GetDC(object->win_handle);
1036 object->display = get_display(hDc);
1037 ReleaseDC(object->win_handle, hDc);
1038 TRACE("Using a display of %p %p \n", object->display, hDc);
1040 if (NULL == object->display || NULL == hDc) {
1041 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1042 return D3DERR_NOTAVAILABLE;
1045 if (object->win == 0) {
1046 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1047 return D3DERR_NOTAVAILABLE;
1050 * Create an opengl context for the display visual
1051 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1052 * use different properties after that point in time. FIXME: How to handle when requested format
1053 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1054 * it chooses is identical to the one already being used!
1055 **********************************/
1057 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1060 /* Create a new context for this swapchain */
1061 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1062 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1063 (or the best possible if none is requested) */
1064 TRACE("Found x visual ID : %ld\n", template.visualid);
1066 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1067 if (NULL == object->visInfo) {
1068 ERR("cannot really get XVisual\n");
1070 return D3DERR_NOTAVAILABLE;
1073 /* Write out some debug info about the visual/s */
1074 TRACE("Using x visual ID : %ld\n", template.visualid);
1075 TRACE(" visual info: %p\n", object->visInfo);
1076 TRACE(" num items : %d\n", num);
1077 for(n = 0;n < num; n++) {
1078 TRACE("=====item=====: %d\n", n + 1);
1079 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1080 TRACE(" screen : %d\n", object->visInfo[n].screen);
1081 TRACE(" depth : %u\n", object->visInfo[n].depth);
1082 TRACE(" class : %d\n", object->visInfo[n].class);
1083 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1084 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1085 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1086 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1087 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1088 /* log some extra glx info */
1089 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1090 TRACE(" gl_aux_buffers : %d\n", value);
1091 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1092 TRACE(" gl_buffer_size : %d\n", value);
1093 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1094 TRACE(" gl_red_size : %d\n", value);
1095 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1096 TRACE(" gl_green_size : %d\n", value);
1097 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1098 TRACE(" gl_blue_size : %d\n", value);
1099 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1100 TRACE(" gl_alpha_size : %d\n", value);
1101 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1102 TRACE(" gl_depth_size : %d\n", value);
1103 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1104 TRACE(" gl_stencil_size : %d\n", value);
1106 /* Now choose a simila visual ID*/
1108 #ifdef USE_CONTEXT_MANAGER
1110 /** TODO: use a context mamager **/
1114 IWineD3DSwapChain *implSwapChain;
1115 if (D3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1116 /* The first time around we create the context that is shared with all other swapchains and render targets */
1117 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1118 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1121 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1122 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1123 /* and create a new context with the implicit swapchains context as the shared context */
1124 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1125 IWineD3DSwapChain_Release(implSwapChain);
1130 XFree(object->visInfo);
1131 object->visInfo = NULL;
1133 if (NULL == object->glCtx) {
1134 ERR("cannot create glxContext\n");
1136 return D3DERR_NOTAVAILABLE;
1140 if (object->glCtx == NULL) {
1141 ERR("Error in context creation !\n");
1142 return D3DERR_INVALIDCALL;
1144 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1145 object->win_handle, object->glCtx, object->win, object->visInfo);
1148 /*********************
1149 * Windowed / Fullscreen
1150 *******************/
1153 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1154 * so we should really check to see if their is a fullscreen swapchain already
1155 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1156 **************************************/
1158 if (!*(pPresentationParameters->Windowed)) {
1164 /* Get info on the current display setup */
1165 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1166 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1169 /* Change the display settings */
1170 memset(&devmode, 0, sizeof(DEVMODEW));
1171 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1172 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1173 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1174 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1175 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1176 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1178 /* Make popup window */
1179 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1180 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1181 *(pPresentationParameters->BackBufferWidth),
1182 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1188 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1189 * then the corresponding dimension of the client area of the hDeviceWindow
1190 * (or the focus window, if hDeviceWindow is NULL) is taken.
1191 **********************/
1193 if (*(pPresentationParameters->Windowed) &&
1194 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1195 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1198 GetClientRect(object->win_handle, &Rect);
1200 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1201 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1202 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1204 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1205 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1206 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1210 /*********************
1211 * finish off parameter initialization
1212 *******************/
1214 /* Put the correct figures in the presentation parameters */
1215 TRACE("Coppying accross presentaion paraneters\n");
1216 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1217 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1218 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1219 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1220 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1221 object->presentParms.MultiSampleQuality = *(pPresentationParameters->MultiSampleQuality);
1222 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1223 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1224 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1225 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1226 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1227 object->presentParms.Flags = *(pPresentationParameters->Flags);
1228 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1229 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1232 /*********************
1233 * Create the back, front and stencil buffers
1234 *******************/
1235 TRACE("calling rendertarget CB\n");
1236 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1237 object->presentParms.BackBufferWidth,
1238 object->presentParms.BackBufferHeight,
1239 object->presentParms.BackBufferFormat,
1240 object->presentParms.MultiSampleType,
1241 object->presentParms.MultiSampleQuality,
1242 TRUE /* Lockable */,
1243 &object->frontBuffer,
1244 NULL /* pShared (always null)*/);
1245 if (object->frontBuffer != NULL)
1246 IWineD3DSurface_SetContainer(object->frontBuffer, (IUnknown *)object);
1247 TRACE("calling rendertarget CB\n");
1248 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1249 object->presentParms.BackBufferWidth,
1250 object->presentParms.BackBufferHeight,
1251 object->presentParms.BackBufferFormat,
1252 object->presentParms.MultiSampleType,
1253 object->presentParms.MultiSampleQuality,
1254 TRUE /* Lockable */,
1255 &object->backBuffer,
1256 NULL /* pShared (always null)*/);
1257 if (object->backBuffer != NULL)
1258 IWineD3DSurface_SetContainer(object->backBuffer, (IUnknown *)object);
1260 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1261 if (pPresentationParameters->EnableAutoDepthStencil) {
1262 TRACE("Creating depth stencil buffer\n");
1263 if (This->depthStencilBuffer == NULL ) {
1264 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1265 object->presentParms.BackBufferWidth,
1266 object->presentParms.BackBufferHeight,
1267 object->presentParms.AutoDepthStencilFormat,
1268 object->presentParms.MultiSampleType,
1269 object->presentParms.MultiSampleQuality,
1270 FALSE /* FIXME: Discard */,
1271 &This->depthStencilBuffer,
1272 NULL /* pShared (always null)*/ );
1273 if (This->depthStencilBuffer != NULL)
1274 IWineD3DSurface_SetContainer(This->depthStencilBuffer, (IUnknown *)iface);
1277 /** TODO: A check on width, height and multisample types
1278 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1279 ****************************/
1280 object->wantsDepthStencilBuffer = TRUE;
1282 object->wantsDepthStencilBuffer = FALSE;
1285 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1288 /*********************
1289 * init the default renderTarget management
1290 *******************/
1291 object->drawable = object->win;
1292 object->render_ctx = object->glCtx;
1295 /*********************
1296 * Setup some defaults and clear down the buffers
1297 *******************/
1299 /** save current context and drawable **/
1300 oldContext = glXGetCurrentContext();
1301 oldDrawable = glXGetCurrentDrawable();
1303 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1304 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1305 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1307 checkGLcall("glXMakeCurrent");
1309 TRACE("Setting up the screen\n");
1310 /* Clear the screen */
1311 glClearColor(0.0, 0.0, 0.0, 0.0);
1312 checkGLcall("glClearColor");
1315 glClearStencil(0xffff);
1317 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1318 checkGLcall("glClear");
1320 glColor3f(1.0, 1.0, 1.0);
1321 checkGLcall("glColor3f");
1323 glEnable(GL_LIGHTING);
1324 checkGLcall("glEnable");
1326 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1327 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1329 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1330 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1332 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1333 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1335 /* switch back to the original context (unless it was zero)*/
1336 if (This->swapchains != NULL) {
1337 /** TODO: restore the context and drawable **/
1338 glXMakeCurrent(object->display, oldDrawable, oldContext);
1343 { /* Finally add the swapchain to the end of the devices' swapchain list */
1344 SwapChainList **nextSwapchain;
1345 nextSwapchain = &This->swapchains;
1346 while(*nextSwapchain != NULL) {
1347 nextSwapchain = &((*nextSwapchain)->next);
1349 (*nextSwapchain) = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->swapchains));
1350 (*nextSwapchain)->swapchain = (IWineD3DSwapChain *)object;
1352 TRACE("Set swapchain to %p\n", object);
1353 } else { /* something went wrong so clean up */
1354 IUnknown* bufferParent;
1355 if (object->frontBuffer) {
1356 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1357 IUnknown_Release(bufferParent); /* once for the get parent */
1358 if(IUnknown_Release(bufferParent) > 0) {
1359 FIXME("(%p) Something's still holding the front buffer\n",This);
1362 if (object->backBuffer) {
1363 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1364 IUnknown_Release(bufferParent); /* once for the get parent */
1365 if(IUnknown_Release(bufferParent) > 0) {
1366 FIXME("(%p) Something's still holding the back buffer\n",This);
1369 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1370 /* Clean up the context */
1371 /* check that we are the current context first (we shouldn't be though!) */
1372 if (object->glCtx != 0) {
1373 if(glXGetCurrentContext() == object->glCtx) {
1374 glXMakeCurrent(object->display, None, NULL);
1376 glXDestroyContext(object->display, object->glCtx);
1378 HeapFree(GetProcessHeap(), 0, object);
1384 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1385 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1386 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1387 unsigned int numberOfSwapChains = 0;
1388 SwapChainList *swapchain;
1390 swapchain = This->swapchains;
1391 /* itterate through the list to get a count */
1392 while (swapchain != NULL) {
1393 swapchain = swapchain->next;
1394 numberOfSwapChains++;
1397 TRACE("(%p) returning %d\n", This, numberOfSwapChains);
1398 return numberOfSwapChains;
1401 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1402 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1403 SwapChainList *swapchain;
1404 HRESULT hr = D3DERR_INVALIDCALL;
1405 swapchain = This->swapchains;
1406 TRACE("(%p) : swapchain %d \n", This, iSwapChain);
1409 TRACE("(%p) Finding swapchain %d\n", This, iSwapChain);
1410 while (iSwapChain > 0 && swapchain != NULL) {
1411 swapchain = swapchain->next;
1415 if (iSwapChain > 0 || swapchain == NULL) {
1416 FIXME("(%p) Unable to find swapchain %d\n", This, iSwapChain);
1419 /** TODO: move off to a linkesList implementation **/
1420 *pSwapChain = swapchain->swapchain;
1421 IWineD3DSwapChain_AddRef(*pSwapChain);
1425 TRACE("(%p) returning %p\n", This, *pSwapChain);
1429 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
1430 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1432 FIXME("(%p) : Stub\n",This);
1438 * Vertex Declaration
1440 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1441 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1442 IWineD3DVertexDeclarationImpl *object = NULL;
1443 HRESULT hr = D3D_OK;
1444 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1445 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1448 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1453 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1454 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DVertexShader** ppVertexShader, IUnknown *parent) {
1455 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1456 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1457 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1458 object->function = pFunction;
1459 FIXME("(%p) : STUB: Created Vertex shader %p\n", This, ppVertexShader);
1464 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DPixelShader** ppPixelShader, IUnknown *parent) {
1465 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1466 FIXME("(%p) : Stub\n", This);
1470 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice* iface, IWineD3D** ppD3D) {
1471 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1472 *ppD3D= This->wineD3D;
1473 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1474 IWineD3D_AddRef(*ppD3D);
1479 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1480 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1481 * Into the video ram as possible and seeing how many fit
1482 * you can also get the correct initial value from via X and ATI's driver
1483 *******************/
1484 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1485 static BOOL showfixmes = TRUE;
1487 FIXME("(%p) : stub, emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1488 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1491 TRACE("(%p) : emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1492 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1493 /* videomemory is simulated videomemory + AGP memory left */
1494 return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1502 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1503 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1505 /* Update the current state block */
1506 This->updateStateBlock->fvf = fvf;
1507 This->updateStateBlock->changed.fvf = TRUE;
1508 This->updateStateBlock->set.fvf = TRUE;
1510 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1511 /* clear down the vertex declaration
1512 NOTE: Axis and Allies doesn't work properly otherwise
1513 (may be a stateblock problem though!)
1515 /* No difference if recording or not */
1516 return IWineD3DDevice_SetVertexDeclaration(iface, NULL);
1521 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1522 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1523 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1524 *pfvf = This->stateBlock->fvf;
1529 * Get / Set Stream Source
1531 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1532 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1533 IWineD3DVertexBuffer *oldSrc;
1535 oldSrc = This->stateBlock->streamSource[StreamNumber];
1536 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1538 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
1539 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
1540 This->updateStateBlock->streamStride[StreamNumber] = Stride;
1541 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
1542 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
1544 /* Handle recording of state blocks */
1545 if (This->isRecordingState) {
1546 TRACE("Recording... not performing anything\n");
1550 /* Not recording... */
1551 if (pStreamData != NULL) {
1552 IUnknown *newVertexBufferParent;
1553 /* GetParent will add a ref, so leave it hanging until the vertex buffer is cleared */
1554 IWineD3DVertexBuffer_GetParent(pStreamData, &newVertexBufferParent);
1556 if (oldSrc != NULL) {
1557 IUnknown *oldVertexBufferParent;
1558 IWineD3DVertexBuffer_GetParent(oldSrc, &oldVertexBufferParent);
1559 IUnknown_Release(oldVertexBufferParent);
1560 IUnknown_Release(oldVertexBufferParent);
1566 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
1567 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1569 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
1570 *pStream = This->stateBlock->streamSource[StreamNumber];
1571 *pStride = This->stateBlock->streamStride[StreamNumber];
1572 *pOffset = This->stateBlock->streamOffset[StreamNumber];
1573 if (*pStream != NULL) IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
1577 /*Should be quite easy, just an extension of vertexdata
1579 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1581 The divider is a bit odd though
1583 VertexOffset = StartVertex / Divider * StreamStride +
1584 VertexIndex / Divider * StreamStride + StreamOffset
1587 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
1588 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1590 FIXME("(%p) : stub\n", This);
1594 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
1595 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1597 FIXME("(%p) : stub\n", This);
1602 * Get / Set & Multiply Transform
1604 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1605 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1607 /* Most of this routine, comments included copied from ddraw tree initially: */
1608 TRACE("(%p) : Transform State=%d\n", This, d3dts);
1610 /* Handle recording of state blocks */
1611 if (This->isRecordingState) {
1612 TRACE("Recording... not performing anything\n");
1613 This->updateStateBlock->changed.transform[d3dts] = TRUE;
1614 This->updateStateBlock->set.transform[d3dts] = TRUE;
1615 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1620 * If the new matrix is the same as the current one,
1621 * we cut off any further processing. this seems to be a reasonable
1622 * optimization because as was noticed, some apps (warcraft3 for example)
1623 * tend towards setting the same matrix repeatedly for some reason.
1625 * From here on we assume that the new matrix is different, wherever it matters.
1627 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1628 TRACE("The app is setting the same matrix over again\n");
1631 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1635 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1636 where ViewMat = Camera space, WorldMat = world space.
1638 In OpenGL, camera and world space is combined into GL_MODELVIEW
1639 matrix. The Projection matrix stay projection matrix.
1642 /* Capture the times we can just ignore the change for now */
1643 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1644 This->modelview_valid = FALSE;
1647 } else if (d3dts == D3DTS_PROJECTION) {
1648 This->proj_valid = FALSE;
1651 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1652 /* Indexed Vertex Blending Matrices 256 -> 511 */
1653 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1654 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1658 /* Now we really are going to have to change a matrix */
1661 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1662 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
1663 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1666 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1667 * NOTE: We have to reset the positions even if the light/plane is not currently
1668 * enabled, since the call to enable it will not reset the position.
1669 * NOTE2: Apparently texture transforms do NOT need reapplying
1672 PLIGHTINFOEL *lightChain = NULL;
1673 This->modelview_valid = FALSE;
1674 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
1676 glMatrixMode(GL_MODELVIEW);
1677 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1679 glLoadMatrixf((float *)lpmatrix);
1680 checkGLcall("glLoadMatrixf(...)");
1683 lightChain = This->stateBlock->lights;
1684 while (lightChain && lightChain->glIndex != -1) {
1685 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1686 checkGLcall("glLightfv posn");
1687 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1688 checkGLcall("glLightfv dirn");
1689 lightChain = lightChain->next;
1692 /* Reset Clipping Planes if clipping is enabled */
1693 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1694 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1695 checkGLcall("glClipPlane");
1699 } else { /* What was requested!?? */
1700 WARN("invalid matrix specified: %i\n", d3dts);
1703 /* Release lock, all done */
1708 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1709 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1710 TRACE("(%p) : for Transform State %d\n", This, State);
1711 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1715 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1716 D3DMATRIX *mat = NULL;
1719 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1720 * below means it will be recorded in a state block change, but it
1721 * works regardless where it is recorded.
1722 * If this is found to be wrong, change to StateBlock.
1724 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1725 TRACE("(%p) : For state %u\n", This, State);
1727 if (State < HIGHEST_TRANSFORMSTATE)
1729 mat = &This->updateStateBlock->transforms[State];
1731 FIXME("Unhandled transform state!!\n");
1734 /* Copied from ddraw code: */
1735 temp.u.s._11 = (mat->u.s._11 * pMatrix->u.s._11) + (mat->u.s._21 * pMatrix->u.s._12) + (mat->u.s._31 * pMatrix->u.s._13) + (mat->u.s._41 * pMatrix->u.s._14);
1736 temp.u.s._21 = (mat->u.s._11 * pMatrix->u.s._21) + (mat->u.s._21 * pMatrix->u.s._22) + (mat->u.s._31 * pMatrix->u.s._23) + (mat->u.s._41 * pMatrix->u.s._24);
1737 temp.u.s._31 = (mat->u.s._11 * pMatrix->u.s._31) + (mat->u.s._21 * pMatrix->u.s._32) + (mat->u.s._31 * pMatrix->u.s._33) + (mat->u.s._41 * pMatrix->u.s._34);
1738 temp.u.s._41 = (mat->u.s._11 * pMatrix->u.s._41) + (mat->u.s._21 * pMatrix->u.s._42) + (mat->u.s._31 * pMatrix->u.s._43) + (mat->u.s._41 * pMatrix->u.s._44);
1740 temp.u.s._12 = (mat->u.s._12 * pMatrix->u.s._11) + (mat->u.s._22 * pMatrix->u.s._12) + (mat->u.s._32 * pMatrix->u.s._13) + (mat->u.s._42 * pMatrix->u.s._14);
1741 temp.u.s._22 = (mat->u.s._12 * pMatrix->u.s._21) + (mat->u.s._22 * pMatrix->u.s._22) + (mat->u.s._32 * pMatrix->u.s._23) + (mat->u.s._42 * pMatrix->u.s._24);
1742 temp.u.s._32 = (mat->u.s._12 * pMatrix->u.s._31) + (mat->u.s._22 * pMatrix->u.s._32) + (mat->u.s._32 * pMatrix->u.s._33) + (mat->u.s._42 * pMatrix->u.s._34);
1743 temp.u.s._42 = (mat->u.s._12 * pMatrix->u.s._41) + (mat->u.s._22 * pMatrix->u.s._42) + (mat->u.s._32 * pMatrix->u.s._43) + (mat->u.s._42 * pMatrix->u.s._44);
1745 temp.u.s._13 = (mat->u.s._13 * pMatrix->u.s._11) + (mat->u.s._23 * pMatrix->u.s._12) + (mat->u.s._33 * pMatrix->u.s._13) + (mat->u.s._43 * pMatrix->u.s._14);
1746 temp.u.s._23 = (mat->u.s._13 * pMatrix->u.s._21) + (mat->u.s._23 * pMatrix->u.s._22) + (mat->u.s._33 * pMatrix->u.s._23) + (mat->u.s._43 * pMatrix->u.s._24);
1747 temp.u.s._33 = (mat->u.s._13 * pMatrix->u.s._31) + (mat->u.s._23 * pMatrix->u.s._32) + (mat->u.s._33 * pMatrix->u.s._33) + (mat->u.s._43 * pMatrix->u.s._34);
1748 temp.u.s._43 = (mat->u.s._13 * pMatrix->u.s._41) + (mat->u.s._23 * pMatrix->u.s._42) + (mat->u.s._33 * pMatrix->u.s._43) + (mat->u.s._43 * pMatrix->u.s._44);
1750 temp.u.s._14 = (mat->u.s._14 * pMatrix->u.s._11) + (mat->u.s._24 * pMatrix->u.s._12) + (mat->u.s._34 * pMatrix->u.s._13) + (mat->u.s._44 * pMatrix->u.s._14);
1751 temp.u.s._24 = (mat->u.s._14 * pMatrix->u.s._21) + (mat->u.s._24 * pMatrix->u.s._22) + (mat->u.s._34 * pMatrix->u.s._23) + (mat->u.s._44 * pMatrix->u.s._24);
1752 temp.u.s._34 = (mat->u.s._14 * pMatrix->u.s._31) + (mat->u.s._24 * pMatrix->u.s._32) + (mat->u.s._34 * pMatrix->u.s._33) + (mat->u.s._44 * pMatrix->u.s._34);
1753 temp.u.s._44 = (mat->u.s._14 * pMatrix->u.s._41) + (mat->u.s._24 * pMatrix->u.s._42) + (mat->u.s._34 * pMatrix->u.s._43) + (mat->u.s._44 * pMatrix->u.s._44);
1755 /* Apply change via set transform - will reapply to eg. lights this way */
1756 IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
1762 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
1764 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1765 you can reference any indexes you want as long as that number max are enabled at any
1766 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1767 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1768 but when recording, just build a chain pretty much of commands to be replayed. */
1770 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
1772 PLIGHTINFOEL *object, *temp;
1774 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1775 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1777 /* If recording state block, just add to end of lights chain */
1778 if (This->isRecordingState) {
1779 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1780 if (NULL == object) {
1781 return D3DERR_OUTOFVIDEOMEMORY;
1783 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1784 object->OriginalIndex = Index;
1785 object->glIndex = -1;
1786 object->changed = TRUE;
1788 /* Add to the END of the chain of lights changes to be replayed */
1789 if (This->updateStateBlock->lights == NULL) {
1790 This->updateStateBlock->lights = object;
1792 temp = This->updateStateBlock->lights;
1793 while (temp->next != NULL) temp=temp->next;
1794 temp->next = object;
1796 TRACE("Recording... not performing anything more\n");
1800 /* Ok, not recording any longer so do real work */
1801 object = This->stateBlock->lights;
1802 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1804 /* If we didn't find it in the list of lights, time to add it */
1805 if (object == NULL) {
1806 PLIGHTINFOEL *insertAt,*prevPos;
1808 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1809 if (NULL == object) {
1810 return D3DERR_OUTOFVIDEOMEMORY;
1812 object->OriginalIndex = Index;
1813 object->glIndex = -1;
1815 /* Add it to the front of list with the idea that lights will be changed as needed
1816 BUT after any lights currently assigned GL indexes */
1817 insertAt = This->stateBlock->lights;
1819 while (insertAt != NULL && insertAt->glIndex != -1) {
1821 insertAt = insertAt->next;
1824 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1825 This->stateBlock->lights = object;
1826 } else if (insertAt == NULL) { /* End of list */
1827 prevPos->next = object;
1828 object->prev = prevPos;
1829 } else { /* Middle of chain */
1830 if (prevPos == NULL) {
1831 This->stateBlock->lights = object;
1833 prevPos->next = object;
1835 object->prev = prevPos;
1836 object->next = insertAt;
1837 insertAt->prev = object;
1841 /* Initialze the object */
1842 TRACE("Light %ld setting to type %d, Diffuse(%f,%f,%f,%f), Specular(%f,%f,%f,%f), Ambient(%f,%f,%f,%f)\n", Index, pLight->Type,
1843 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1844 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1845 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1846 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1847 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1848 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1850 /* Save away the information */
1851 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1853 switch (pLight->Type) {
1854 case D3DLIGHT_POINT:
1856 object->lightPosn[0] = pLight->Position.x;
1857 object->lightPosn[1] = pLight->Position.y;
1858 object->lightPosn[2] = pLight->Position.z;
1859 object->lightPosn[3] = 1.0f;
1860 object->cutoff = 180.0f;
1864 case D3DLIGHT_DIRECTIONAL:
1866 object->lightPosn[0] = -pLight->Direction.x;
1867 object->lightPosn[1] = -pLight->Direction.y;
1868 object->lightPosn[2] = -pLight->Direction.z;
1869 object->lightPosn[3] = 0.0;
1870 object->exponent = 0.0f;
1871 object->cutoff = 180.0f;
1876 object->lightPosn[0] = pLight->Position.x;
1877 object->lightPosn[1] = pLight->Position.y;
1878 object->lightPosn[2] = pLight->Position.z;
1879 object->lightPosn[3] = 1.0;
1882 object->lightDirn[0] = pLight->Direction.x;
1883 object->lightDirn[1] = pLight->Direction.y;
1884 object->lightDirn[2] = pLight->Direction.z;
1885 object->lightDirn[3] = 1.0;
1888 * opengl-ish and d3d-ish spot lights use too different models for the
1889 * light "intensity" as a function of the angle towards the main light direction,
1890 * so we only can approximate very roughly.
1891 * however spot lights are rather rarely used in games (if ever used at all).
1892 * furthermore if still used, probably nobody pays attention to such details.
1894 if (pLight->Falloff == 0) {
1897 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1899 if (rho < 0.0001) rho = 0.0001f;
1900 object->exponent = -0.3/log(cos(rho/2));
1901 object->cutoff = pLight->Phi*90/M_PI;
1907 FIXME("Unrecognized light type %d\n", pLight->Type);
1910 /* Update the live definitions if the light is currently assigned a glIndex */
1911 if (object->glIndex != -1) {
1912 setup_light(iface, object->glIndex, object);
1917 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
1918 PLIGHTINFOEL *lightInfo = NULL;
1919 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1920 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1922 /* Locate the light in the live lights */
1923 lightInfo = This->stateBlock->lights;
1924 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1926 if (lightInfo == NULL) {
1927 TRACE("Light information requested but light not defined\n");
1928 return D3DERR_INVALIDCALL;
1931 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
1936 * Get / Set Light Enable
1937 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
1939 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
1940 PLIGHTINFOEL *lightInfo = NULL;
1941 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1942 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1944 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1945 if (This->isRecordingState) {
1946 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1947 if (NULL == lightInfo) {
1948 return D3DERR_OUTOFVIDEOMEMORY;
1950 lightInfo->OriginalIndex = Index;
1951 lightInfo->glIndex = -1;
1952 lightInfo->enabledChanged = TRUE;
1954 /* Add to the END of the chain of lights changes to be replayed */
1955 if (This->updateStateBlock->lights == NULL) {
1956 This->updateStateBlock->lights = lightInfo;
1958 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
1959 while (temp->next != NULL) temp=temp->next;
1960 temp->next = lightInfo;
1962 TRACE("Recording... not performing anything more\n");
1966 /* Not recording... So, locate the light in the live lights */
1967 lightInfo = This->stateBlock->lights;
1968 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1970 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1971 if (lightInfo == NULL) {
1972 D3DLIGHT9 lightParms;
1973 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1974 wait until someone confirms it seems to work! */
1975 TRACE("Light enabled requested but light not defined, so defining one!\n");
1976 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1977 lightParms.Diffuse.r = 1.0;
1978 lightParms.Diffuse.g = 1.0;
1979 lightParms.Diffuse.b = 1.0;
1980 lightParms.Diffuse.a = 0.0;
1981 lightParms.Specular.r = 0.0;
1982 lightParms.Specular.g = 0.0;
1983 lightParms.Specular.b = 0.0;
1984 lightParms.Specular.a = 0.0;
1985 lightParms.Ambient.r = 0.0;
1986 lightParms.Ambient.g = 0.0;
1987 lightParms.Ambient.b = 0.0;
1988 lightParms.Ambient.a = 0.0;
1989 lightParms.Position.x = 0.0;
1990 lightParms.Position.y = 0.0;
1991 lightParms.Position.z = 0.0;
1992 lightParms.Direction.x = 0.0;
1993 lightParms.Direction.y = 0.0;
1994 lightParms.Direction.z = 1.0;
1995 lightParms.Range = 0.0;
1996 lightParms.Falloff = 0.0;
1997 lightParms.Attenuation0 = 0.0;
1998 lightParms.Attenuation1 = 0.0;
1999 lightParms.Attenuation2 = 0.0;
2000 lightParms.Theta = 0.0;
2001 lightParms.Phi = 0.0;
2002 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
2004 /* Search for it again! Should be fairly quick as near head of list */
2005 lightInfo = This->stateBlock->lights;
2006 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2007 if (lightInfo == NULL) {
2008 FIXME("Adding default lights has failed dismally\n");
2009 return D3DERR_INVALIDCALL;
2013 /* OK, we now have a light... */
2014 if (Enable == FALSE) {
2016 /* If we are disabling it, check it was enabled, and
2017 still only do something if it has assigned a glIndex (which it should have!) */
2018 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2019 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2021 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2022 checkGLcall("glDisable GL_LIGHT0+Index");
2025 TRACE("Nothing to do as light was not enabled\n");
2027 lightInfo->lightEnabled = FALSE;
2030 /* We are enabling it. If it is enabled, it's really simple */
2031 if (lightInfo->lightEnabled) {
2033 TRACE("Nothing to do as light was enabled\n");
2035 /* If it already has a glIndex, it's still simple */
2036 } else if (lightInfo->glIndex != -1) {
2037 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2038 lightInfo->lightEnabled = TRUE;
2040 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2041 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2044 /* Otherwise got to find space - lights are ordered gl indexes first */
2046 PLIGHTINFOEL *bsf = NULL;
2047 PLIGHTINFOEL *pos = This->stateBlock->lights;
2048 PLIGHTINFOEL *prev = NULL;
2052 /* Try to minimize changes as much as possible */
2053 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2055 /* Try to remember which index can be replaced if necessary */
2056 if (bsf==NULL && pos->lightEnabled == FALSE) {
2057 /* Found a light we can replace, save as best replacement */
2061 /* Step to next space */
2067 /* If we have too many active lights, fail the call */
2068 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2069 FIXME("Program requests too many concurrent lights\n");
2070 return D3DERR_INVALIDCALL;
2072 /* If we have allocated all lights, but not all are enabled,
2073 reuse one which is not enabled */
2074 } else if (Index == This->maxConcurrentLights) {
2075 /* use bsf - Simply swap the new light and the BSF one */
2076 PLIGHTINFOEL *bsfNext = bsf->next;
2077 PLIGHTINFOEL *bsfPrev = bsf->prev;
2080 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2081 if (bsf->prev != NULL) {
2082 bsf->prev->next = lightInfo;
2084 This->stateBlock->lights = lightInfo;
2087 /* If not side by side, lots of chains to update */
2088 if (bsf->next != lightInfo) {
2089 lightInfo->prev->next = bsf;
2090 bsf->next->prev = lightInfo;
2091 bsf->next = lightInfo->next;
2092 bsf->prev = lightInfo->prev;
2093 lightInfo->next = bsfNext;
2094 lightInfo->prev = bsfPrev;
2098 bsf->prev = lightInfo;
2099 bsf->next = lightInfo->next;
2100 lightInfo->next = bsf;
2101 lightInfo->prev = bsfPrev;
2106 glIndex = bsf->glIndex;
2108 lightInfo->glIndex = glIndex;
2109 lightInfo->lightEnabled = TRUE;
2111 /* Finally set up the light in gl itself */
2112 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2114 setup_light(iface, glIndex, lightInfo);
2115 glEnable(GL_LIGHT0 + glIndex);
2116 checkGLcall("glEnable GL_LIGHT0 new setup");
2119 /* If we reached the end of the allocated lights, with space in the
2120 gl lights, setup a new light */
2121 } else if (pos->glIndex == -1) {
2123 /* We reached the end of the allocated gl lights, so already
2124 know the index of the next one! */
2126 lightInfo->glIndex = glIndex;
2127 lightInfo->lightEnabled = TRUE;
2129 /* In an ideal world, it's already in the right place */
2130 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2131 /* No need to move it */
2133 /* Remove this light from the list */
2134 lightInfo->prev->next = lightInfo->next;
2135 if (lightInfo->next != NULL) {
2136 lightInfo->next->prev = lightInfo->prev;
2139 /* Add in at appropriate place (inbetween prev and pos) */
2140 lightInfo->prev = prev;
2141 lightInfo->next = pos;
2143 This->stateBlock->lights = lightInfo;
2145 prev->next = lightInfo;
2148 pos->prev = lightInfo;
2152 /* Finally set up the light in gl itself */
2153 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2155 setup_light(iface, glIndex, lightInfo);
2156 glEnable(GL_LIGHT0 + glIndex);
2157 checkGLcall("glEnable GL_LIGHT0 new setup");
2166 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2168 PLIGHTINFOEL *lightInfo = NULL;
2169 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2170 TRACE("(%p) : for idx(%ld)\n", This, Index);
2172 /* Locate the light in the live lights */
2173 lightInfo = This->stateBlock->lights;
2174 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2176 if (lightInfo == NULL) {
2177 TRACE("Light enabled state requested but light not defined\n");
2178 return D3DERR_INVALIDCALL;
2180 *pEnable = lightInfo->lightEnabled;
2185 * Get / Set Clip Planes
2187 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2188 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2189 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2191 /* Validate Index */
2192 if (Index >= GL_LIMITS(clipplanes)) {
2193 TRACE("Application has requested clipplane this device doesn't support\n");
2194 return D3DERR_INVALIDCALL;
2197 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2198 This->updateStateBlock->set.clipplane[Index] = TRUE;
2199 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2200 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2201 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2202 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2204 /* Handle recording of state blocks */
2205 if (This->isRecordingState) {
2206 TRACE("Recording... not performing anything\n");
2214 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2215 glMatrixMode(GL_MODELVIEW);
2217 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2219 TRACE("Clipplane [%f,%f,%f,%f]\n",
2220 This->updateStateBlock->clipplane[Index][0],
2221 This->updateStateBlock->clipplane[Index][1],
2222 This->updateStateBlock->clipplane[Index][2],
2223 This->updateStateBlock->clipplane[Index][3]);
2224 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2225 checkGLcall("glClipPlane");
2233 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2234 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2235 TRACE("(%p) : for idx %ld\n", This, Index);
2237 /* Validate Index */
2238 if (Index >= GL_LIMITS(clipplanes)) {
2239 TRACE("Application has requested clipplane this device doesn't support\n");
2240 return D3DERR_INVALIDCALL;
2243 pPlane[0] = This->stateBlock->clipplane[Index][0];
2244 pPlane[1] = This->stateBlock->clipplane[Index][1];
2245 pPlane[2] = This->stateBlock->clipplane[Index][2];
2246 pPlane[3] = This->stateBlock->clipplane[Index][3];
2251 * Get / Set Clip Plane Status
2252 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2254 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2255 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2256 FIXME("(%p) : stub\n", This);
2257 if (NULL == pClipStatus) {
2258 return D3DERR_INVALIDCALL;
2260 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2261 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2265 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2266 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2267 FIXME("(%p) : stub\n", This);
2268 if (NULL == pClipStatus) {
2269 return D3DERR_INVALIDCALL;
2271 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2272 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2277 * Get / Set Material
2278 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2280 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2281 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2283 This->updateStateBlock->changed.material = TRUE;
2284 This->updateStateBlock->set.material = TRUE;
2285 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2287 /* Handle recording of state blocks */
2288 if (This->isRecordingState) {
2289 TRACE("Recording... not performing anything\n");
2294 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2295 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2296 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2297 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2298 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2300 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2301 checkGLcall("glMaterialfv");
2302 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2303 checkGLcall("glMaterialfv");
2305 /* Only change material color if specular is enabled, otherwise it is set to black */
2306 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2307 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2308 checkGLcall("glMaterialfv");
2310 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2311 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2312 checkGLcall("glMaterialfv");
2314 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2315 checkGLcall("glMaterialfv");
2316 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2317 checkGLcall("glMaterialf");
2323 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2324 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2325 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2326 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2327 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2328 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2329 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2330 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2337 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2338 UINT BaseVertexIndex) {
2339 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2340 IWineD3DIndexBuffer *oldIdxs;
2342 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2343 oldIdxs = This->updateStateBlock->pIndexData;
2345 This->updateStateBlock->changed.indices = TRUE;
2346 This->updateStateBlock->set.indices = TRUE;
2347 This->updateStateBlock->pIndexData = pIndexData;
2348 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2350 /* Handle recording of state blocks */
2351 if (This->isRecordingState) {
2352 TRACE("Recording... not performing anything\n");
2357 IUnknown *indexBufferParent;
2358 /* Getting the parent causes a addRef... it gets released when the indicies are clear */
2359 IWineD3DIndexBuffer_GetParent(pIndexData, &indexBufferParent);
2362 IUnknown *indexBufferParent;
2363 IWineD3DIndexBuffer_GetParent(oldIdxs, &indexBufferParent);
2364 IUnknown_Release(indexBufferParent);
2365 IUnknown_Release(indexBufferParent);
2370 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2371 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2373 *ppIndexData = This->stateBlock->pIndexData;
2375 /* up ref count on ppindexdata */
2376 if (*ppIndexData) IWineD3DIndexBuffer_AddRef(*ppIndexData);
2377 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2383 * Get / Set Viewports
2385 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2386 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2388 TRACE("(%p)\n", This);
2389 This->updateStateBlock->changed.viewport = TRUE;
2390 This->updateStateBlock->set.viewport = TRUE;
2391 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2393 /* Handle recording of state blocks */
2394 if (This->isRecordingState) {
2395 TRACE("Recording... not performing anything\n");
2401 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2402 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2404 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2405 checkGLcall("glDepthRange");
2406 /* Note: GL requires lower left, DirectX supplies upper left */
2407 /* TODO: replace usage of renderTarget with context management */
2408 glViewport(pViewport->X,
2409 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2410 pViewport->Width, pViewport->Height);
2412 checkGLcall("glViewport");
2420 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2421 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2422 TRACE("(%p)\n", This);
2423 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2428 * Get / Set Render States
2429 * TODO: Verify against dx9 definitions
2431 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2433 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2434 DWORD OldValue = This->stateBlock->renderState[State];
2436 /* Simple way of referring to either a DWORD or a 4 byte float */
2442 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2443 This->updateStateBlock->changed.renderState[State] = TRUE;
2444 This->updateStateBlock->set.renderState[State] = TRUE;
2445 This->updateStateBlock->renderState[State] = Value;
2447 /* Handle recording of state blocks */
2448 if (This->isRecordingState) {
2449 TRACE("Recording... not performing anything\n");
2456 case WINED3DRS_FILLMODE :
2457 switch ((D3DFILLMODE) Value) {
2458 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2459 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2460 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2462 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
2464 checkGLcall("glPolygonMode (fillmode)");
2467 case WINED3DRS_LIGHTING :
2469 glEnable(GL_LIGHTING);
2470 checkGLcall("glEnable GL_LIGHTING");
2472 glDisable(GL_LIGHTING);
2473 checkGLcall("glDisable GL_LIGHTING");
2477 case WINED3DRS_ZENABLE :
2478 switch ((D3DZBUFFERTYPE) Value) {
2480 glDisable(GL_DEPTH_TEST);
2481 checkGLcall("glDisable GL_DEPTH_TEST");
2484 glEnable(GL_DEPTH_TEST);
2485 checkGLcall("glEnable GL_DEPTH_TEST");
2488 glEnable(GL_DEPTH_TEST);
2489 checkGLcall("glEnable GL_DEPTH_TEST");
2490 FIXME("W buffer is not well handled\n");
2493 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2497 case WINED3DRS_CULLMODE :
2499 /* If we are culling "back faces with clockwise vertices" then
2500 set front faces to be counter clockwise and enable culling
2502 switch ((D3DCULL) Value) {
2504 glDisable(GL_CULL_FACE);
2505 checkGLcall("glDisable GL_CULL_FACE");
2508 glEnable(GL_CULL_FACE);
2509 checkGLcall("glEnable GL_CULL_FACE");
2510 if (This->renderUpsideDown) {
2512 checkGLcall("glFrontFace GL_CW");
2514 glFrontFace(GL_CCW);
2515 checkGLcall("glFrontFace GL_CCW");
2517 glCullFace(GL_BACK);
2520 glEnable(GL_CULL_FACE);
2521 checkGLcall("glEnable GL_CULL_FACE");
2522 if (This->renderUpsideDown) {
2523 glFrontFace(GL_CCW);
2524 checkGLcall("glFrontFace GL_CCW");
2527 checkGLcall("glFrontFace GL_CW");
2529 glCullFace(GL_BACK);
2532 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2536 case WINED3DRS_SHADEMODE :
2537 switch ((D3DSHADEMODE) Value) {
2539 glShadeModel(GL_FLAT);
2540 checkGLcall("glShadeModel");
2542 case D3DSHADE_GOURAUD:
2543 glShadeModel(GL_SMOOTH);
2544 checkGLcall("glShadeModel");
2546 case D3DSHADE_PHONG:
2547 FIXME("D3DSHADE_PHONG isn't supported?\n");
2550 return D3DERR_INVALIDCALL;
2552 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2556 case WINED3DRS_DITHERENABLE :
2558 glEnable(GL_DITHER);
2559 checkGLcall("glEnable GL_DITHER");
2561 glDisable(GL_DITHER);
2562 checkGLcall("glDisable GL_DITHER");
2566 case WINED3DRS_ZWRITEENABLE :
2569 checkGLcall("glDepthMask");
2572 checkGLcall("glDepthMask");
2576 case WINED3DRS_ZFUNC :
2578 int glParm = GL_LESS;
2580 switch ((D3DCMPFUNC) Value) {
2581 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2582 case D3DCMP_LESS: glParm=GL_LESS; break;
2583 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2584 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2585 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2586 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2587 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2588 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2590 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2592 glDepthFunc(glParm);
2593 checkGLcall("glDepthFunc");
2597 case WINED3DRS_AMBIENT :
2600 D3DCOLORTOGLFLOAT4(Value, col);
2601 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2602 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2603 checkGLcall("glLightModel for MODEL_AMBIENT");
2608 case WINED3DRS_ALPHABLENDENABLE :
2611 checkGLcall("glEnable GL_BLEND");
2613 glDisable(GL_BLEND);
2614 checkGLcall("glDisable GL_BLEND");
2618 case WINED3DRS_SRCBLEND :
2619 case WINED3DRS_DESTBLEND :
2621 int newVal = GL_ZERO;
2623 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2624 case D3DBLEND_ONE : newVal = GL_ONE; break;
2625 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2626 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2627 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2628 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2629 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2630 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2631 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2632 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2633 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2635 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2636 This->srcBlend = newVal;
2637 This->dstBlend = newVal;
2640 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2641 This->srcBlend = newVal;
2642 This->dstBlend = newVal;
2645 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2648 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2649 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2650 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2651 glBlendFunc(This->srcBlend, This->dstBlend);
2653 checkGLcall("glBlendFunc");
2657 case WINED3DRS_ALPHATESTENABLE :
2659 glEnable(GL_ALPHA_TEST);
2660 checkGLcall("glEnable GL_ALPHA_TEST");
2662 glDisable(GL_ALPHA_TEST);
2663 checkGLcall("glDisable GL_ALPHA_TEST");
2667 case WINED3DRS_ALPHAFUNC :
2669 int glParm = GL_LESS;
2670 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2672 switch ((D3DCMPFUNC) Value) {
2673 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2674 case D3DCMP_LESS: glParm = GL_LESS; break;
2675 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2676 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2677 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2678 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2679 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2680 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2682 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2684 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2685 glAlphaFunc(glParm, ref);
2686 This->alphafunc = glParm;
2687 checkGLcall("glAlphaFunc");
2691 case WINED3DRS_ALPHAREF :
2693 int glParm = This->alphafunc;
2696 ref = ((float) Value) / 255.0f;
2697 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2698 glAlphaFunc(glParm, ref);
2699 checkGLcall("glAlphaFunc");
2703 case WINED3DRS_CLIPPLANEENABLE :
2704 case WINED3DRS_CLIPPING :
2706 /* Ensure we only do the changed clip planes */
2707 DWORD enable = 0xFFFFFFFF;
2708 DWORD disable = 0x00000000;
2710 /* If enabling / disabling all */
2711 if (State == WINED3DRS_CLIPPING) {
2713 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2716 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2720 enable = Value & ~OldValue;
2721 disable = ~Value & OldValue;
2724 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2725 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2726 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2727 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2728 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2729 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2731 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2732 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2733 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2734 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2735 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2736 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2738 /** update clipping status */
2740 This->stateBlock->clip_status.ClipUnion = 0;
2741 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
2743 This->stateBlock->clip_status.ClipUnion = 0;
2744 This->stateBlock->clip_status.ClipIntersection = 0;
2749 case WINED3DRS_BLENDOP :
2751 int glParm = GL_FUNC_ADD;
2753 switch ((D3DBLENDOP) Value) {
2754 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2755 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2756 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2757 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2758 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2760 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2762 TRACE("glBlendEquation(%x)\n", glParm);
2763 glBlendEquation(glParm);
2764 checkGLcall("glBlendEquation");
2768 case WINED3DRS_TEXTUREFACTOR :
2772 /* Note the texture color applies to all textures whereas
2773 GL_TEXTURE_ENV_COLOR applies to active only */
2775 D3DCOLORTOGLFLOAT4(Value, col);
2776 /* Set the default alpha blend color */
2777 glBlendColor(col[0], col[1], col[2], col[3]);
2778 checkGLcall("glBlendColor");
2780 /* And now the default texture color as well */
2781 for (i = 0; i < GL_LIMITS(textures); i++) {
2783 /* Note the D3DRS value applies to all textures, but GL has one
2784 per texture, so apply it now ready to be used! */
2785 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2788 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2791 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2792 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2797 case WINED3DRS_SPECULARENABLE :
2799 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2800 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2801 specular color. This is wrong:
2802 Separate specular color means the specular colour is maintained separately, whereas
2803 single color means it is merged in. However in both cases they are being used to
2805 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2806 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2810 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2811 checkGLcall("glMaterialfv");
2812 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2813 glEnable(GL_COLOR_SUM_EXT);
2815 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2817 checkGLcall("glEnable(GL_COLOR_SUM)");
2819 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2821 /* for the case of enabled lighting: */
2822 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2823 checkGLcall("glMaterialfv");
2825 /* for the case of disabled lighting: */
2826 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2827 glDisable(GL_COLOR_SUM_EXT);
2829 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2831 checkGLcall("glDisable(GL_COLOR_SUM)");
2836 case WINED3DRS_STENCILENABLE :
2838 glEnable(GL_STENCIL_TEST);
2839 checkGLcall("glEnable GL_STENCIL_TEST");
2841 glDisable(GL_STENCIL_TEST);
2842 checkGLcall("glDisable GL_STENCIL_TEST");
2846 case WINED3DRS_STENCILFUNC :
2848 int glParm = GL_ALWAYS;
2849 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2850 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2852 switch ((D3DCMPFUNC) Value) {
2853 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2854 case D3DCMP_LESS: glParm=GL_LESS; break;
2855 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2856 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2857 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2858 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2859 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2860 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2862 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2864 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2865 This->stencilfunc = glParm;
2866 glStencilFunc(glParm, ref, mask);
2867 checkGLcall("glStencilFunc");
2871 case WINED3DRS_STENCILREF :
2873 int glParm = This->stencilfunc;
2875 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2878 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2879 glStencilFunc(glParm, ref, mask);
2880 checkGLcall("glStencilFunc");
2884 case WINED3DRS_STENCILMASK :
2886 int glParm = This->stencilfunc;
2887 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2888 GLuint mask = Value;
2890 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2891 glStencilFunc(glParm, ref, mask);
2892 checkGLcall("glStencilFunc");
2896 case WINED3DRS_STENCILFAIL :
2902 fail = StencilOp(Value);
2903 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2904 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2905 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2906 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2908 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2909 glStencilOp(fail, zfail, zpass);
2910 checkGLcall("glStencilOp(fail, zfail, zpass);");
2913 case WINED3DRS_STENCILZFAIL :
2919 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2920 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2921 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2922 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2923 zfail = StencilOp(Value);
2925 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2926 glStencilOp(fail, zfail, zpass);
2927 checkGLcall("glStencilOp(fail, zfail, zpass);");
2930 case WINED3DRS_STENCILPASS :
2936 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2937 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2938 zpass = StencilOp(Value);
2939 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2940 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2942 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2943 glStencilOp(fail, zfail, zpass);
2944 checkGLcall("glStencilOp(fail, zfail, zpass);");
2948 case WINED3DRS_STENCILWRITEMASK :
2950 glStencilMask(Value);
2951 TRACE("glStencilMask(%lu)\n", Value);
2952 checkGLcall("glStencilMask");
2956 case WINED3DRS_FOGENABLE :
2958 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2960 checkGLcall("glEnable GL_FOG");
2963 checkGLcall("glDisable GL_FOG");
2968 case WINED3DRS_RANGEFOGENABLE :
2971 TRACE("Enabled RANGEFOG");
2973 TRACE("Disabled RANGEFOG");
2978 case WINED3DRS_FOGCOLOR :
2981 D3DCOLORTOGLFLOAT4(Value, col);
2982 /* Set the default alpha blend color */
2983 glFogfv(GL_FOG_COLOR, &col[0]);
2984 checkGLcall("glFog GL_FOG_COLOR");
2988 case WINED3DRS_FOGTABLEMODE :
2990 glHint(GL_FOG_HINT, GL_NICEST);
2992 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2993 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2994 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2995 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2997 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
2999 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3000 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3005 case WINED3DRS_FOGVERTEXMODE :
3007 glHint(GL_FOG_HINT, GL_FASTEST);
3009 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3010 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3011 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3012 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3014 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3016 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3017 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
3022 case WINED3DRS_FOGSTART :
3025 glFogfv(GL_FOG_START, &tmpvalue.f);
3026 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3027 TRACE("Fog Start == %f\n", tmpvalue.f);
3031 case WINED3DRS_FOGEND :
3034 glFogfv(GL_FOG_END, &tmpvalue.f);
3035 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3036 TRACE("Fog End == %f\n", tmpvalue.f);
3040 case WINED3DRS_FOGDENSITY :
3043 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3044 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3048 case WINED3DRS_VERTEXBLEND :
3050 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3051 TRACE("Vertex Blending state to %ld\n", Value);
3055 case WINED3DRS_TWEENFACTOR :
3058 This->updateStateBlock->tween_factor = tmpvalue.f;
3059 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3063 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
3065 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3069 case WINED3DRS_COLORVERTEX :
3070 case WINED3DRS_DIFFUSEMATERIALSOURCE :
3071 case WINED3DRS_SPECULARMATERIALSOURCE :
3072 case WINED3DRS_AMBIENTMATERIALSOURCE :
3073 case WINED3DRS_EMISSIVEMATERIALSOURCE :
3075 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3077 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3078 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3079 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3080 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3081 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3082 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3084 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3085 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3086 Parm = GL_AMBIENT_AND_DIFFUSE;
3090 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3092 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3094 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3101 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3103 This->tracking_color = NEEDS_TRACKING;
3104 This->tracking_parm = Parm;
3108 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3113 case WINED3DRS_LINEPATTERN :
3119 tmppattern.d = Value;
3121 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3123 if (tmppattern.lp.wRepeatFactor) {
3124 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3125 checkGLcall("glLineStipple(repeat, linepattern)");
3126 glEnable(GL_LINE_STIPPLE);
3127 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3129 glDisable(GL_LINE_STIPPLE);
3130 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3135 case WINED3DRS_ZBIAS :
3139 TRACE("ZBias value %f\n", tmpvalue.f);
3140 glPolygonOffset(0, -tmpvalue.f);
3141 checkGLcall("glPolygonOffset(0, -Value)");
3142 glEnable(GL_POLYGON_OFFSET_FILL);
3143 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3144 glEnable(GL_POLYGON_OFFSET_LINE);
3145 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3146 glEnable(GL_POLYGON_OFFSET_POINT);
3147 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3149 glDisable(GL_POLYGON_OFFSET_FILL);
3150 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3151 glDisable(GL_POLYGON_OFFSET_LINE);
3152 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3153 glDisable(GL_POLYGON_OFFSET_POINT);
3154 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3159 case WINED3DRS_NORMALIZENORMALS :
3161 glEnable(GL_NORMALIZE);
3162 checkGLcall("glEnable(GL_NORMALIZE);");
3164 glDisable(GL_NORMALIZE);
3165 checkGLcall("glDisable(GL_NORMALIZE);");
3169 case WINED3DRS_POINTSIZE :
3171 TRACE("Set point size to %f\n", tmpvalue.f);
3172 glPointSize(tmpvalue.f);
3173 checkGLcall("glPointSize(...);");
3176 case WINED3DRS_POINTSIZE_MIN :
3177 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3179 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3180 checkGLcall("glPointParameterfEXT(...);");
3182 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3186 case WINED3DRS_POINTSIZE_MAX :
3187 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3189 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3190 checkGLcall("glPointParameterfEXT(...);");
3192 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3196 case WINED3DRS_POINTSCALE_A :
3197 case WINED3DRS_POINTSCALE_B :
3198 case WINED3DRS_POINTSCALE_C :
3199 case WINED3DRS_POINTSCALEENABLE :
3201 /* If enabled, supply the parameters, otherwise fall back to defaults */
3202 if (This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3203 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3204 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]);
3205 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]);
3206 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]);
3208 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3209 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3210 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3212 TRACE("WINED3DRS_POINTSCALEENABLE not supported on this opengl\n");
3215 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3216 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3217 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3218 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3220 TRACE("WINED3DRS_POINTSCALEENABLE not supported, but not on either\n");
3226 case WINED3DRS_COLORWRITEENABLE :
3228 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3229 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3230 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3231 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3232 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3233 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3234 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3235 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3236 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3237 checkGLcall("glColorMask(...)");
3241 case WINED3DRS_LOCALVIEWER :
3243 GLint state = (Value) ? 1 : 0;
3244 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3245 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3249 case WINED3DRS_LASTPIXEL :
3252 TRACE("Last Pixel Drawing Enabled\n");
3254 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3259 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3262 TRACE("Software Processing Enabled\n");
3264 TRACE("Software Processing Disabled\n");
3269 /** not supported */
3270 case WINED3DRS_ZVISIBLE :
3273 return D3DERR_INVALIDCALL;
3276 /* Unhandled yet...! */
3277 case WINED3DRS_EDGEANTIALIAS :
3278 case WINED3DRS_WRAP0 :
3279 case WINED3DRS_WRAP1 :
3280 case WINED3DRS_WRAP2 :
3281 case WINED3DRS_WRAP3 :
3282 case WINED3DRS_WRAP4 :
3283 case WINED3DRS_WRAP5 :
3284 case WINED3DRS_WRAP6 :
3285 case WINED3DRS_WRAP7 :
3286 case WINED3DRS_POINTSPRITEENABLE :
3287 case WINED3DRS_MULTISAMPLEANTIALIAS :
3288 case WINED3DRS_MULTISAMPLEMASK :
3289 case WINED3DRS_PATCHEDGESTYLE :
3290 case WINED3DRS_PATCHSEGMENTS :
3291 case WINED3DRS_DEBUGMONITORTOKEN :
3292 case WINED3DRS_POSITIONORDER :
3293 case WINED3DRS_NORMALORDER :
3294 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3295 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3298 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3306 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3307 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3308 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3309 *pValue = This->stateBlock->renderState[State];
3314 * Get / Set Sampler States
3315 * TODO: Verify against dx9 definitions
3318 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3319 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3321 * SetSampler is designed to allow for more than the standard up to 8 textures
3322 * and Geforce has stopped supporting more than 6 standard textures in openGL.
3323 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3325 * http://developer.nvidia.com/object/General_FAQ.html#t6
3327 * There are two new settings for GForce
3329 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3330 * and the texture one:
3331 * GL_MAX_TEXTURE_COORDS_ARB.
3332 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3334 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
3335 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
3337 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
3338 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE, Sampler, Type);
3339 return D3DERR_INVALIDCALL;
3341 TRACE("Setting sampler %ld %d to %ld \n", Sampler, Type, Value);
3342 This->updateStateBlock->samplerState[Sampler][Type] = Value;
3344 /* Handle recording of state blocks */
3345 if (This->isRecordingState) {
3346 TRACE("Recording... not performing anything\n");
3353 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3354 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3355 /** TODO: check that sampler is in range **/
3356 *Value = This->updateStateBlock->samplerState[Sampler][Type];
3357 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
3362 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3363 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3366 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3367 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3368 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3374 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3375 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3376 GLint scissorBox[4];
3379 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3380 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
3381 pRect->left = scissorBox[1];
3382 pRect->top = scissorBox[2];
3383 pRect->right = scissorBox[1] + scissorBox[3];
3384 pRect->bottom = scissorBox[2] + scissorBox[4];
3385 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3390 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3391 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3393 TRACE("(%p) : pDecl=%p\n", This, pDecl);
3395 /* TODO: what about recording stateblocks? */
3396 if (NULL != pDecl) {
3397 IWineD3DVertexDeclaration_AddRef(pDecl);
3399 if (NULL != This->updateStateBlock->vertexDecl) {
3400 IWineD3DVertexDeclaration_Release(This->updateStateBlock->vertexDecl);
3402 This->updateStateBlock->vertexDecl = pDecl;
3403 This->updateStateBlock->changed.vertexDecl = TRUE;
3404 This->updateStateBlock->set.vertexDecl = TRUE;
3408 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3409 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3411 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3413 *ppDecl = This->updateStateBlock->vertexDecl;
3414 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3418 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
3419 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3421 static BOOL showFixmes = TRUE;
3423 This->updateStateBlock->vertexShader = pShader;
3424 This->updateStateBlock->changed.vertexShader = TRUE;
3425 This->updateStateBlock->set.vertexShader = TRUE;
3427 if(pShader == NULL) {
3428 /* clear down the shader */
3429 TRACE("Clear down the shader\n");
3432 FIXME("(%p) : stub pShader(%p)\n", This, pShader);
3439 /** FIXME: refernece counting? **/
3440 if (pShader == NULL) { /* only valid with non FVF shaders */
3441 TRACE_(d3d_shader)("(%p) : FVF Shader, pShader=%p\n", This, pShader);
3442 This->updateStateBlock->vertexShader = NULL;
3444 TRACE_(d3d_shader)("(%p) : Created shader, pShader=%p\n", This, pShader);
3445 This->updateStateBlock->vertexShader = pShader;
3448 This->updateStateBlock->changed.vertexShader = TRUE;
3449 This->updateStateBlock->set.vertexShader = TRUE;
3451 /* Handle recording of state blocks */
3452 if (This->isRecordingState) {
3453 TRACE("Recording... not performing anything\n");
3457 * TODO: merge HAL shaders context switching from prototype
3463 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
3464 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3465 *ppShader = This->stateBlock->vertexShader;
3466 if(*ppShader != NULL)
3467 IWineD3DVertexShader_AddRef(*ppShader);
3468 TRACE("(%p) : returning %p\n", This, *ppShader);
3472 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
3473 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3475 TRACE("(%p) : stub\n", This);
3479 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
3480 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3481 TRACE("(%p) : stub\n", This);
3485 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
3486 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3487 TRACE("(%p) : stub\n", This);
3491 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
3492 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3493 TRACE("(%p) : stub\n", This);
3497 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
3498 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3499 TRACE("(%p) : stub\n", This);
3503 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
3504 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3505 TRACE("(%p) : stub\n", This);
3509 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
3510 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3511 TRACE("(%p) : stub\n", This);
3515 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3516 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3517 TRACE("(%p) : stub\n", This);
3522 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
3523 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3524 TRACE("(%p) : stub\n", This);
3528 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
3529 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3530 TRACE("(%p) : stub\n", This);
3534 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
3535 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3536 TRACE("(%p) : stub\n", This);
3540 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
3541 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3542 TRACE("(%p) : stub\n", This);
3546 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
3547 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3548 TRACE("(%p) : stub\n", This);
3552 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
3553 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3554 TRACE("(%p) : stub\n", This);
3558 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
3559 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3560 FIXME("(%p) : stub\n", This);
3565 * Apply / Get / Set Texture Stage States
3566 * TODO: Verify against dx9 definitions
3569 /* 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 */
3570 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
3571 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3572 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
3573 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3575 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3577 /* Check that the stage is within limits */
3578 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
3579 TRACE("Attempt to access invalid texture rejected\n");
3586 case WINED3DTSS_ALPHAOP :
3587 case WINED3DTSS_COLOROP :
3590 if ((Value == D3DTOP_DISABLE) && (Type == WINED3DTSS_COLOROP)) {
3591 /* TODO: Disable by making this and all later levels disabled */
3592 glDisable(GL_TEXTURE_1D);
3593 checkGLcall("Disable GL_TEXTURE_1D");
3594 glDisable(GL_TEXTURE_2D);
3595 checkGLcall("Disable GL_TEXTURE_2D");
3596 glDisable(GL_TEXTURE_3D);
3597 checkGLcall("Disable GL_TEXTURE_3D");
3598 break; /* Don't bother setting the texture operations */
3600 /* Enable only the appropriate texture dimension */
3601 if (Type == WINED3DTSS_COLOROP) {
3602 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3603 glEnable(GL_TEXTURE_1D);
3604 checkGLcall("Enable GL_TEXTURE_1D");
3606 glDisable(GL_TEXTURE_1D);
3607 checkGLcall("Disable GL_TEXTURE_1D");
3609 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3610 if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
3611 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
3612 checkGLcall("Enable GL_TEXTURE_2D");
3614 glEnable(GL_TEXTURE_2D);
3615 checkGLcall("Enable GL_TEXTURE_2D");
3618 glDisable(GL_TEXTURE_2D);
3619 checkGLcall("Disable GL_TEXTURE_2D");
3621 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3622 glEnable(GL_TEXTURE_3D);
3623 checkGLcall("Enable GL_TEXTURE_3D");
3625 glDisable(GL_TEXTURE_3D);
3626 checkGLcall("Disable GL_TEXTURE_3D");
3628 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3629 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3630 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3632 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3633 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3637 /* Drop through... (Except disable case) */
3638 case WINED3DTSS_COLORARG0 :
3639 case WINED3DTSS_COLORARG1 :
3640 case WINED3DTSS_COLORARG2 :
3641 case WINED3DTSS_ALPHAARG0 :
3642 case WINED3DTSS_ALPHAARG1 :
3643 case WINED3DTSS_ALPHAARG2 :
3645 BOOL isAlphaArg = (Type == WINED3DTSS_ALPHAOP || Type == WINED3DTSS_ALPHAARG1 ||
3646 Type == WINED3DTSS_ALPHAARG2 || Type == WINED3DTSS_ALPHAARG0);
3648 set_tex_op(iface, TRUE, Stage, This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAOP],
3649 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG1],
3650 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG2],
3651 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG0]);
3653 set_tex_op(iface, FALSE, Stage, This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP],
3654 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG1],
3655 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG2],
3656 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG0]);
3662 case WINED3DTSS_ADDRESSW :
3664 GLint wrapParm = GL_REPEAT;
3667 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3668 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3669 case D3DTADDRESS_BORDER:
3671 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3672 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3674 /* FIXME: Not right, but better */
3675 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3676 wrapParm = GL_REPEAT;
3680 case D3DTADDRESS_MIRROR:
3682 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3683 wrapParm = GL_MIRRORED_REPEAT_ARB;
3685 /* Unsupported in OpenGL pre-1.4 */
3686 FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3687 wrapParm = GL_REPEAT;
3691 case D3DTADDRESS_MIRRORONCE:
3693 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3694 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3696 FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3697 wrapParm = GL_REPEAT;
3703 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3704 wrapParm = GL_REPEAT;
3707 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
3708 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3709 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3713 case WINED3DTSS_TEXCOORDINDEX :
3715 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3717 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
3718 one flag, you can still specify an index value, which the system uses to
3719 determine the texture wrapping mode.
3720 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3721 means use the vertex position (camera-space) as the input texture coordinates
3722 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
3723 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3724 to the TEXCOORDINDEX value */
3727 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3729 switch (Value & 0xFFFF0000) {
3730 case D3DTSS_TCI_PASSTHRU:
3731 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3732 glDisable(GL_TEXTURE_GEN_S);
3733 glDisable(GL_TEXTURE_GEN_T);
3734 glDisable(GL_TEXTURE_GEN_R);
3735 glDisable(GL_TEXTURE_GEN_Q);
3736 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3739 case D3DTSS_TCI_CAMERASPACEPOSITION:
3740 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3741 as the input texture coordinates for this stage's texture transformation. This
3742 equates roughly to EYE_LINEAR */
3744 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3745 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3746 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3747 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3748 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3750 glMatrixMode(GL_MODELVIEW);
3753 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3754 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3755 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3756 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3759 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3760 glEnable(GL_TEXTURE_GEN_S);
3761 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3762 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3763 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3764 glEnable(GL_TEXTURE_GEN_T);
3765 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3766 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3767 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3768 glEnable(GL_TEXTURE_GEN_R);
3769 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3770 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3771 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3775 case D3DTSS_TCI_CAMERASPACENORMAL:
3777 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3778 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3779 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3780 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3781 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3782 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3784 glMatrixMode(GL_MODELVIEW);
3787 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3788 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3789 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3790 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3793 glEnable(GL_TEXTURE_GEN_S);
3794 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3795 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3796 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3797 glEnable(GL_TEXTURE_GEN_T);
3798 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3799 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3800 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3801 glEnable(GL_TEXTURE_GEN_R);
3802 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3803 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3804 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3809 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3811 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3812 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3813 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3814 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3815 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3816 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3818 glMatrixMode(GL_MODELVIEW);
3821 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3822 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3823 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3824 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3827 glEnable(GL_TEXTURE_GEN_S);
3828 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3829 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3830 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3831 glEnable(GL_TEXTURE_GEN_T);
3832 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3833 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3834 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3835 glEnable(GL_TEXTURE_GEN_R);
3836 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3837 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3838 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3843 /* Unhandled types: */
3846 /* ? disable GL_TEXTURE_GEN_n ? */
3847 glDisable(GL_TEXTURE_GEN_S);
3848 glDisable(GL_TEXTURE_GEN_T);
3849 glDisable(GL_TEXTURE_GEN_R);
3850 glDisable(GL_TEXTURE_GEN_Q);
3851 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
3858 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
3859 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);
3862 case WINED3DTSS_BUMPENVMAT00 :
3863 case WINED3DTSS_BUMPENVMAT01 :
3864 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
3866 case WINED3DTSS_BUMPENVMAT10 :
3867 case WINED3DTSS_BUMPENVMAT11 :
3868 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
3871 case WINED3DTSS_BUMPENVLSCALE :
3872 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3875 case WINED3DTSS_BUMPENVLOFFSET :
3876 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3879 case WINED3DTSS_RESULTARG :
3880 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3884 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3885 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3893 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3894 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3896 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3898 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3900 /* Reject invalid texture units */
3901 if (Stage >= GL_LIMITS(textures)) {
3902 TRACE("Attempt to access invalid texture rejected\n");
3903 return D3DERR_INVALIDCALL;
3906 This->updateStateBlock->textureState[Stage][Type] = Value;
3911 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
3912 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3913 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
3914 *pValue = This->updateStateBlock->textureState[Stage][Type];
3921 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
3923 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3924 IWineD3DBaseTexture *oldTexture;
3926 oldTexture = This->updateStateBlock->textures[Stage];
3927 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3929 #if 0 /* TODO: check so vertex textures */
3930 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
3931 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
3936 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
3937 WARN("Attempt to access invalid texture rejected\n");
3938 return D3DERR_INVALIDCALL;
3941 oldTexture = This->updateStateBlock->textures[Stage];
3942 TRACE("GL_LIMITS %d\n",GL_LIMITS(textures));
3943 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
3945 This->updateStateBlock->set.textures[Stage] = TRUE;
3946 This->updateStateBlock->changed.textures[Stage] = TRUE;
3947 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
3948 This->updateStateBlock->textures[Stage] = pTexture;
3950 /* Handle recording of state blocks */
3951 if (This->isRecordingState) {
3952 TRACE("Recording... not performing anything\n");
3956 /** NOTE: MSDN says that setTexture increases the reference count,
3957 * and the the application nust set the texture back to null (or have a leaky application),
3958 * This means we should pass the refcount upto the parent
3959 *******************************/
3960 if (NULL != This->updateStateBlock->textures[Stage]) {
3961 IUnknown *textureParent;
3962 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[Stage], (IUnknown **)&textureParent);
3963 /** NOTE: GetParent will increase the ref count for me, I won't clean up until the texture is set to NULL **/
3966 if (NULL != oldTexture) {
3967 IUnknown *textureParent;
3968 IWineD3DBaseTexture_GetParent(oldTexture, (IUnknown **)&textureParent);
3969 IUnknown_Release(textureParent);
3970 IUnknown_Release(textureParent); /** NOTE: Twice because GetParent adds a ref **/
3977 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
3978 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3979 TRACE("(%p) : returning %p for stage %ld\n", This, This->updateStateBlock->textures[Stage], Stage);
3980 *ppTexture = (IWineD3DBaseTexture *) This->updateStateBlock->textures[Stage];
3982 IWineD3DBaseTexture_AddRef(*ppTexture);
3989 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type,
3990 IWineD3DSurface** ppBackBuffer) {
3991 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3992 IWineD3DSwapChain *swapChain;
3995 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
3997 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
3999 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4000 IWineD3DSwapChain_Release(swapChain);
4002 *ppBackBuffer = NULL;
4007 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4008 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4009 WARN("(%p) : stub, calling idirect3d for now\n", This);
4010 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4013 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
4014 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4015 IWineD3DSwapChain *swapChain;
4018 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4020 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4021 IWineD3DSwapChain_Release(swapChain);
4023 FIXME("(%p) Error getting display mode\n", This);
4028 * Stateblock related functions
4031 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4032 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4033 IWineD3DStateBlockImpl *object;
4034 TRACE("(%p)", This);
4035 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4036 if(NULL == object ) {
4037 FIXME("(%p)Error allocating memory for stateblock\n", This);
4038 return E_OUTOFMEMORY;
4040 TRACE("(%p) creted object %p\n", This, object);
4041 object->wineD3DDevice= This;
4042 /** FIXME: object->parent = parent; **/
4043 object->parent = NULL;
4044 object->blockType = WINED3DSBT_ALL;
4046 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
4048 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4049 This->updateStateBlock = object;
4050 This->isRecordingState = TRUE;
4052 TRACE("(%p) recording stateblock %p\n",This , object);
4056 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4057 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4059 if (!This->isRecordingState) {
4060 FIXME("(%p) not recording! returning error\n", This);
4061 *ppStateBlock = NULL;
4062 return D3DERR_INVALIDCALL;
4065 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4066 This->isRecordingState = FALSE;
4067 This->updateStateBlock = This->stateBlock;
4068 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4069 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4070 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4075 * Scene related functions
4077 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4078 /* At the moment we have no need for any functionality at the beginning
4080 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4081 TRACE("(%p) : stub\n", This);
4085 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4086 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4087 TRACE("(%p)\n", This);
4089 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4091 checkGLcall("glFlush");
4093 TRACE("End Scene\n");
4094 if(This->renderTarget != NULL) {
4096 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4097 IUnknown *targetContainer = NULL;
4098 if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
4099 || D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
4100 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
4101 /** always dirtify for now. we must find a better way to see that surface have been modified
4102 (Modifications should will only occur via draw-primitive, but we do need better locking
4103 switching to render-to-texture should remove the overhead though.
4105 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4106 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
4107 IWineD3DSurface_PreLoad(This->renderTarget);
4108 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4109 IUnknown_Release(targetContainer);
4112 This->sceneEnded = TRUE;
4117 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4118 CONST RECT* pSourceRect, CONST RECT* pDestRect,
4119 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4120 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4121 IWineD3DSwapChain *swapChain = NULL;
4123 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4125 TRACE("(%p) Presenting the frame\n", This);
4127 for(i = 0 ; i < swapchains ; i ++) {
4129 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4130 TRACE("presentinng chain %d, %p\n", i, swapChain);
4131 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4132 IWineD3DSwapChain_Release(swapChain);
4138 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4139 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4140 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4142 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4143 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4144 when the depth-buffer format does not contain stencil buffer information, this method fails. */
4145 GLbitfield glMask = 0;
4146 GLboolean old_ztest;
4147 GLfloat old_z_clear_value;
4148 GLint old_stencil_clear_value;
4149 GLfloat old_color_clear_value[4];
4151 CONST D3DRECT* curRect;
4153 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4154 Count, pRects, Flags, Z, Stencil);
4158 glEnable(GL_SCISSOR_TEST);
4159 checkGLcall("glEnable GL_SCISSOR_TEST");
4161 if (Count > 0 && pRects) {
4167 /* Only set the values up once, as they are not changing */
4168 if (Flags & D3DCLEAR_STENCIL) {
4169 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4170 glClearStencil(Stencil);
4171 checkGLcall("glClearStencil");
4172 glMask = glMask | GL_STENCIL_BUFFER_BIT;
4173 glStencilMask(0xFFFFFFFF);
4176 if (Flags & D3DCLEAR_ZBUFFER) {
4177 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4178 glDepthMask(GL_TRUE);
4179 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4181 checkGLcall("glClearDepth");
4182 glMask = glMask | GL_DEPTH_BUFFER_BIT;
4185 if (Flags & D3DCLEAR_TARGET) {
4186 TRACE("Clearing screen with glClear to color %lx\n", Color);
4187 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4188 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
4189 ((Color >> 8) & 0xFF) / 255.0f,
4190 ((Color >> 0) & 0xFF) / 255.0f,
4191 ((Color >> 24) & 0xFF) / 255.0f);
4192 checkGLcall("glClearColor");
4194 /* Clear ALL colors! */
4195 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4196 glMask = glMask | GL_COLOR_BUFFER_BIT;
4199 /* Now process each rect in turn */
4200 for (i = 0; i < Count || i == 0; i++) {
4203 /* Note gl uses lower left, width/height */
4204 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4205 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4206 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4207 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4208 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4209 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4210 checkGLcall("glScissor");
4212 glScissor(This->stateBlock->viewport.X,
4213 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4214 This->stateBlock->viewport.Width,
4215 This->stateBlock->viewport.Height);
4216 checkGLcall("glScissor");
4219 /* Clear the selected rectangle (or full screen) */
4221 checkGLcall("glClear");
4223 /* Step to the next rectangle */
4224 if (curRect) curRect = curRect + sizeof(D3DRECT);
4227 /* Restore the old values (why..?) */
4228 if (Flags & D3DCLEAR_STENCIL) {
4229 glClearStencil(old_stencil_clear_value);
4230 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4232 if (Flags & D3DCLEAR_ZBUFFER) {
4233 glDepthMask(old_ztest);
4234 glClearDepth(old_z_clear_value);
4236 if (Flags & D3DCLEAR_TARGET) {
4237 glClearColor(old_color_clear_value[0],
4238 old_color_clear_value[1],
4239 old_color_clear_value[2],
4240 old_color_clear_value[3]);
4241 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4242 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4243 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4244 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4247 glDisable(GL_SCISSOR_TEST);
4248 checkGLcall("glDisable");
4257 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4258 UINT PrimitiveCount) {
4260 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4261 This->stateBlock->streamIsUP = FALSE;
4263 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4264 debug_d3dprimitivetype(PrimitiveType),
4265 StartVertex, PrimitiveCount);
4266 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
4271 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4272 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4273 D3DPRIMITIVETYPE PrimitiveType,
4274 INT baseVIndex, UINT minIndex,
4275 UINT NumVertices,UINT startIndex,UINT primCount) {
4277 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4279 IWineD3DIndexBuffer *pIB;
4280 D3DINDEXBUFFER_DESC IdxBufDsc;
4282 pIB = This->stateBlock->pIndexData;
4283 This->stateBlock->streamIsUP = FALSE;
4285 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d \n", This,
4286 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4287 minIndex, NumVertices, startIndex, baseVIndex, primCount);
4289 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4290 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4296 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex,
4297 startIndex, idxStride,
4298 ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory,
4304 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4305 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4306 UINT VertexStreamZeroStride) {
4307 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4309 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4310 debug_d3dprimitivetype(PrimitiveType),
4311 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4313 if (This->stateBlock->streamSource[0] != NULL) {
4314 IUnknown *vertexBufferParent;
4315 IWineD3DVertexBuffer_GetParent(This->stateBlock->streamSource[0], &vertexBufferParent);
4316 IUnknown_Release(vertexBufferParent);
4317 IUnknown_Release(vertexBufferParent);
4320 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4321 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4322 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4323 This->stateBlock->streamIsUP = TRUE;
4324 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
4325 This->stateBlock->streamStride[0] = 0;
4326 This->stateBlock->streamSource[0] = NULL;
4328 /*stream zero settings set to null at end, as per the msdn */
4332 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4333 UINT MinVertexIndex,
4334 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
4335 WINED3DFORMAT IndexDataFormat, CONST void* pVertexStreamZeroData,
4336 UINT VertexStreamZeroStride) {
4338 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4340 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4341 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4342 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData,
4343 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4345 if (IndexDataFormat == WINED3DFMT_INDEX16) {
4351 if (This->stateBlock->streamSource[0] != NULL) {
4352 IUnknown *vertexBufferParent;
4353 IWineD3DVertexBuffer_GetParent(This->stateBlock->streamSource[0], &vertexBufferParent);
4354 This->stateBlock->streamSource[0] = NULL;
4355 IUnknown_Release(vertexBufferParent);
4356 IUnknown_Release(vertexBufferParent);
4359 if (This->stateBlock->pIndexData) {
4360 IUnknown *indexBufferParent;
4361 IWineD3DIndexBuffer_GetParent(This->stateBlock->pIndexData, &indexBufferParent);
4362 This->stateBlock->pIndexData = NULL;
4363 IUnknown_Release(indexBufferParent);
4364 IUnknown_Release(indexBufferParent);
4367 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4368 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4369 This->stateBlock->streamIsUP = TRUE;
4370 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4372 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, idxStride, pIndexData, MinVertexIndex);
4374 /* stream zero settings set to null at end as per the msdn */
4375 This->stateBlock->streamSource[0] = NULL;
4376 This->stateBlock->streamStride[0] = 0;
4381 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4382 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
4383 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4384 D3DRESOURCETYPE sourceType;
4385 D3DRESOURCETYPE destinationType;
4386 IWineD3DTextureImpl *pDestTexture = (IWineD3DTextureImpl *)pDestinationTexture;
4387 IWineD3DTextureImpl *pSrcTexture = (IWineD3DTextureImpl *)pSourceTexture;
4390 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
4391 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
4392 if(sourceType != D3DRTYPE_TEXTURE && destinationType != D3DRTYPE_TEXTURE){
4393 FIXME("(%p) Only D3DRTYPE_TEXTURE to D3DRTYPE_TEXTURE supported\n", This);
4394 return D3DERR_INVALIDCALL;
4396 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
4398 /** TODO: Get rid of the casts to IWineD3DBaseTextureImpl
4399 repalce surfaces[x] with GetSurfaceLevel, or GetCubeMapSurface etc..
4400 think about moving the code into texture, and adding a member to base texture to occomplish this **/
4402 /* Make sure that the destination texture is loaded */
4403 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
4404 TRACE("Loading source texture\n");
4406 if(pSrcTexture->surfaces[0] == NULL || pDestTexture->surfaces[0] == NULL){
4407 FIXME("(%p) Texture src %p or dest %p has not surface %p %p\n", This, pSrcTexture, pDestTexture,
4408 pSrcTexture->surfaces[0], pDestTexture->surfaces[0]);
4411 if(((IWineD3DSurfaceImpl *)pSrcTexture->surfaces[0])->resource.pool != D3DPOOL_SYSTEMMEM ||
4412 ((IWineD3DSurfaceImpl *)pDestTexture->surfaces[0])->resource.pool != D3DPOOL_DEFAULT){
4414 FIXME("(%p) source %p must be SYSTEMMEM and dest %p must be DEFAULT\n",This, pSrcTexture, pDestTexture);
4415 return D3DERR_INVALIDCALL;
4417 /** TODO: check that both textures have the same number of levels **/
4419 if(IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) !=IWineD3DBaseTexture_GetLevelCount(pSourceTexture))
4420 return D3DERR_INVALIDCALL;
4422 /** TODO: move this code into baseTexture? device should never touch impl*'s **/
4423 for(i = 0 ; i < IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) ; i++){
4424 IWineD3DDevice_UpdateSurface(iface, pSrcTexture->surfaces[i], NULL, pDestTexture->surfaces[i], NULL);
4430 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
4431 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
4432 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
4433 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4435 TRACE("(%p) : stub\n", This);
4438 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
4439 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4441 TRACE("(%p) : stub\n", This);
4445 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
4446 IWineD3DSwapChain *swapChain;
4448 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4450 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
4451 IWineD3DSwapChain_Release(swapChain);
4456 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4457 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4458 /* return a sensible default */
4460 FIXME("(%p) : stub\n", This);
4464 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4465 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4467 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4468 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4469 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4470 return D3DERR_INVALIDCALL;
4472 for (j = 0; j < 256; ++j) {
4473 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
4474 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
4475 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
4476 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
4478 TRACE("(%p) : returning\n", This);
4482 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4483 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4485 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4486 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4487 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4488 return D3DERR_INVALIDCALL;
4490 for (j = 0; j < 256; ++j) {
4491 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
4492 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
4493 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
4494 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
4496 TRACE("(%p) : returning\n", This);
4500 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4501 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4502 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4503 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4504 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4505 return D3DERR_INVALIDCALL;
4507 /*TODO: stateblocks */
4508 This->currentPalette = PaletteNumber;
4509 TRACE("(%p) : returning\n", This);
4513 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4514 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4515 if (PaletteNumber == NULL) {
4516 WARN("(%p) : returning Invalid Call\n", This);
4517 return D3DERR_INVALIDCALL;
4519 /*TODO: stateblocks */
4520 *PaletteNumber = This->currentPalette;
4521 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
4525 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4526 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4527 static BOOL showFixmes = TRUE;
4529 FIXME("(%p) : stub\n", This);
4533 This->updateStateBlock->softwareVertexProcessing = bSoftware;
4538 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4539 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4540 static BOOL showFixmes = TRUE;
4542 FIXME("(%p) : stub\n", This);
4545 return This->updateStateBlock->softwareVertexProcessing;
4549 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
4550 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4552 pRasterStatus->InVBlank = TRUE;
4553 pRasterStatus->ScanLine = 0;
4554 FIXME("(%p) : stub\n", This);
4559 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4560 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4561 static BOOL showfixmes = TRUE;
4562 if(nSegments != 0.0f) {
4564 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4571 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4572 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4573 static BOOL showfixmes = TRUE;
4575 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4582 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4583 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4584 /** TODO: remove casts to IWineD3DSurfaceImpl
4585 * NOTE: move code to surface to accomplish this
4586 ****************************************/
4587 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
4588 int srcWidth, srcHeight;
4589 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
4590 WINED3DFORMAT destFormat, srcFormat;
4592 int destLeft, destTop;
4593 D3DPOOL srcPool, destPool;
4595 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
4596 glDescriptor *glDescription = NULL;
4597 GLenum textureDimensions = GL_TEXTURE_2D;
4598 IWineD3DBaseTexture *baseTexture;
4600 WINED3DSURFACE_DESC winedesc;
4602 memset(&winedesc, 0, sizeof(winedesc));
4603 winedesc.Width = &srcSurfaceWidth;
4604 winedesc.Height = &srcSurfaceHeight;
4605 winedesc.Pool = &srcPool;
4606 winedesc.Format = &srcFormat;
4608 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
4610 winedesc.Width = &destSurfaceWidth;
4611 winedesc.Height = &destSurfaceHeight;
4612 winedesc.Pool = &destPool;
4613 winedesc.Format = &destFormat;
4614 winedesc.Size = &destSize;
4616 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
4618 if(srcPool != D3DPOOL_SYSTEMMEM || destPool != D3DPOOL_DEFAULT){
4619 FIXME("source %p must be SYSTEMMEM and dest %p must be DEFAULT\n", pSourceSurface, pDestinationSurface);
4620 return D3DERR_INVALIDCALL;
4622 /* TODO: change this to use bindTexture */
4623 /* Make sure the surface is loaded and upto date */
4624 IWineD3DSurface_PreLoad(pDestinationSurface);
4626 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
4630 /* this needs to be done in lines if the sourceRect != the sourceWidth */
4631 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
4632 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
4633 destLeft = pDestPoint ? pDestPoint->x : 0;
4634 destTop = pDestPoint ? pDestPoint->y : 0;
4637 /* This function doesn't support compressed textures
4638 the pitch is just bytesPerPixel * width */
4640 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
4641 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
4642 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
4643 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
4645 /* TODO DXT formats */
4647 if(pSourceRect != NULL && pSourceRect->top != 0){
4648 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
4650 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
4652 ,glDescription->level
4657 ,glDescription->glFormat
4658 ,glDescription->glType
4659 ,IWineD3DSurface_GetData(pSourceSurface)
4663 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
4664 /* need to lock the surface to get the data */
4665 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
4667 /* TODO: Cube and volume support */
4669 /* not a whole row so we have to do it a line at a time */
4671 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
4672 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
4674 for(j = destTop ; j < (srcHeight + destTop) ; j++){
4676 glTexSubImage2D(glDescription->target
4677 ,glDescription->level
4682 ,glDescription->glFormat
4683 ,glDescription->glType
4684 ,data/* could be quicker using */
4689 } else { /* Full width, so just write out the whole texture */
4691 if (WINED3DFMT_DXT1 == destFormat ||
4692 WINED3DFMT_DXT3 == destFormat ||
4693 WINED3DFMT_DXT5 == destFormat) {
4694 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
4695 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
4696 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
4697 FIXME("Updating part of a compressed texture is not supported at the moment\n");
4698 } if (destFormat != srcFormat) {
4699 FIXME("Updating mixed format compressed texture is not curretly support\n");
4701 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
4702 glDescription->level,
4703 glDescription->glFormatInternal,
4708 IWineD3DSurface_GetData(pSourceSurface));
4711 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
4716 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
4717 to repack the data from pow2Width/Height to expected Width,Height, this makes the
4718 data returned by GetData non-power2 width/height with hardware non-power2
4719 pow2Width/height are set to surface width height, repacking isn't needed so it
4720 doesn't matter which function gets called. */
4721 glTexSubImage2D(glDescription->target
4722 ,glDescription->level
4727 ,glDescription->glFormat
4728 ,glDescription->glType
4729 ,IWineD3DSurface_GetData(pSourceSurface)
4734 checkGLcall("glTexSubImage2D");
4735 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
4736 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
4737 * surface bigger than it needs to be hmm.. */
4738 if (D3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
4739 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
4740 IWineD3DBaseTexture_Release(baseTexture);
4743 glDisable(textureDimensions); /* This needs to be managed better.... */
4749 /* Implementation details at http://developer.nvidia.com/attach/6494
4751 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
4752 hmm.. no longer supported use
4753 OpenGL evaluators or tessellate surfaces within your application.
4756 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
4757 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4758 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4759 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p) \n", This, Handle, pNumSegs, pRectPatchInfo);
4760 FIXME("(%p) : Stub\n", This);
4765 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
4766 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4767 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4768 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p) \n", This, Handle, pNumSegs, pTriPatchInfo);
4769 FIXME("(%p) : Stub\n", This);
4773 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
4774 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4775 TRACE("(%p) Handle(%d)\n", This, Handle);
4776 FIXME("(%p) : Stub\n", This);
4780 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
4781 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
4782 fill a surface with a block of color! */
4783 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4784 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
4785 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
4786 IWineD3DSwapChainImpl *container = NULL;
4787 BOOL isRenderTarget = FALSE;
4788 unsigned int width, height;
4789 unsigned int top, left;
4792 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
4793 if (surface->resource.pool != D3DPOOL_DEFAULT) {
4794 FIXME("call to colorfill with non D3DPOOL_DEFAULT surface\n");
4795 return D3DERR_INVALIDCALL;
4798 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
4799 if (D3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
4800 if (D3DUSAGE_RENDERTARGET & surface->resource.usage) {
4801 /* TODO: make sure we set everything back to the way it was, and context management!
4802 glGetIntegerv(GL_READ_BUFFER, &prev_read);
4803 vcheckGLcall("glIntegerv");
4804 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
4805 vcheckGLcall("glIntegerv");
4807 TRACE("Color fill to render targets may cause some graphics issues\n");
4808 if (pSurface == container->frontBuffer) {
4809 glDrawBuffer(GL_FRONT);
4811 glDrawBuffer(GL_BACK);
4814 if (D3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
4815 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld \n", surface, surface->resource.usage);
4817 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
4819 if (container != NULL) {
4820 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
4822 /* we can use GL_STENCIL_INDEX etc...*/
4825 if (container != NULL) {
4826 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
4828 isRenderTarget = TRUE;
4830 /* TODO: drawing to GL_FRONT and GL_BACK */
4831 /* TODO: see if things can be speeded up by using the correct
4832 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
4833 if (pRect == NULL) {
4836 width = surface->currentDesc.Width;
4837 height = surface->currentDesc.Height;
4841 width = pRect->x2 - left;
4842 height = pRect->y2 - top;
4845 data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
4846 /* Create a 'line' of color color, in the correct format for the surface */
4847 for (u = 0 ; u < width ; u ++) {
4852 if (isRenderTarget == FALSE) {
4853 glDescriptor *glDesc;
4854 IWineD3DSurface_PreLoad(pSurface);
4856 /* draw a block of the coloured line on the sufrace */
4857 IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
4858 for (v = 0 ; v< height;v++) {
4859 glTexSubImage2D(glDesc->target
4860 ,glDesc->level /* level */
4870 checkGLcall("glTexSubImage2D");
4872 glDisable(glDesc->target);
4874 /** FIXME: Using GLClear may be faster **/
4875 glRasterPos2i(left, top);
4876 glPixelZoom((float)width ,(float)height);
4877 glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
4878 checkGLcall("glDrawPixels");
4880 HeapFree(GetProcessHeap(), 0, data);
4886 /* rendertarget and deptth stencil functions */
4887 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
4888 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4890 /* FIXME: Implelent RenderTargetIndex >0 */
4891 if(RenderTargetIndex > 0)
4892 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
4894 *ppRenderTarget = This->renderTarget;
4895 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
4896 /* Note inc ref on returned surface */
4897 if(*ppRenderTarget != NULL)
4898 IWineD3DSurface_AddRef(*ppRenderTarget);
4902 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
4903 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4904 *ppZStencilSurface = This->depthStencilBuffer;
4905 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
4907 if(*ppZStencilSurface != NULL) {
4908 /* Note inc ref on returned surface */
4909 IWineD3DSurface_AddRef(*ppZStencilSurface);
4914 /* internal static helper functions */
4915 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
4916 IWineD3DSurface *RenderSurface);
4918 HRESULT WINAPI static IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain);
4920 HRESULT WINAPI static IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context);
4922 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
4923 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4924 HRESULT hr = D3D_OK;
4925 WINED3DVIEWPORT viewport;
4927 TRACE("(%p) Swapping rendertarget\n",This);
4928 if (RenderTargetIndex > 0) {
4929 FIXME("(%p) Render targets other than the first are not supported\n",This);
4930 RenderTargetIndex = 0;
4933 /* MSDN says that null disables the render target
4934 but a device must always be associated with a render target
4935 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
4937 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
4940 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
4941 FIXME("Trying to set render target 0 to NULL\n");
4942 return D3DERR_INVALIDCALL;
4944 /* TODO: replace Impl* usage with interface usage */
4945 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & D3DUSAGE_RENDERTARGET) {
4946 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);
4947 return D3DERR_INVALIDCALL;
4949 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
4950 * builds, but I think wine counts as a 'debug' build for now.
4951 ******************************/
4952 /* If we are trying to set what we already have, don't bother */
4953 if (pRenderTarget == This->renderTarget) {
4954 TRACE("Trying to do a NOP SetRenderTarget operation\n");
4956 /* Otherwise, set the render target up */
4958 if (FALSE == This->sceneEnded) {
4959 IWineD3DDevice_EndScene(iface);
4961 TRACE("clearing renderer\n");
4962 /* IWineD3DDeviceImpl_CleanRender(iface); */
4963 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
4964 depending on the renter target implementation being used.
4965 A shared context implementation will share all buffers between all rendertargets (including swapchains),
4966 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
4967 stencil buffer and incure an extra memory overhead */
4968 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
4971 if (SUCCEEDED(hr)) {
4972 /* Finally, reset the viewport as the MSDN states. */
4973 /* TODO: Replace impl usage */
4974 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
4975 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
4978 viewport.MaxZ = 1.0f;
4979 viewport.MinZ = 0.0f;
4980 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
4982 FIXME("Unknown error setting the render target\n");
4984 This->sceneEnded = FALSE;
4988 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
4989 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4990 HRESULT hr = D3D_OK;
4991 IWineD3DSurface *tmp;
4993 TRACE("(%p) Swapping z-buffer\n",This);
4995 if (pNewZStencil == This->stencilBufferTarget) {
4996 TRACE("Trying to do a NOP SetRenderTarget operation\n");
4998 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
4999 * depending on the renter target implementation being used.
5000 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5001 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5002 * stencil buffer and incure an extra memory overhead
5003 ******************************************************/
5006 tmp = This->stencilBufferTarget;
5007 This->stencilBufferTarget = pNewZStencil;
5008 /* should we be calling the parent or the wined3d surface? */
5009 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
5010 if (NULL != tmp) IWineD3DSurface_Release(tmp);
5012 /** TODO: glEnable/glDisable on depth/stencil depending on
5013 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
5014 **********************************************************/
5021 /* Internal functions not in DirectX */
5022 /** TODO: move this off to the opengl context manager
5023 *(the swapchain doesn't need to know anything about offscreen rendering!)
5024 ****************************************************/
5026 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
5028 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5030 TRACE("(%p), %p\n", This, swapchain);
5032 if (swapchain->win != swapchain->drawable) {
5033 /* Set everything back the way it ws */
5034 swapchain->render_ctx = swapchain->glCtx;
5035 swapchain->drawable = swapchain->win;
5039 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
5040 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
5041 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5044 unsigned int height;
5045 WINED3DFORMAT format;
5046 WINED3DSURFACE_DESC surfaceDesc;
5047 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5048 surfaceDesc.Width = &width;
5049 surfaceDesc.Height = &height;
5050 surfaceDesc.Format = &format;
5051 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5053 /* I need a get width/height function (and should do something with the format) */
5054 for (i = 0; i < CONTEXT_CACHE; ++i) {
5055 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
5056 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
5057 the pSurface can be set to 0 allowing it to be reused from cache **/
5058 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
5059 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
5060 *context = &This->contextCache[i];
5063 if (This->contextCache[i].Width == 0) {
5064 This->contextCache[i].pSurface = pSurface;
5065 This->contextCache[i].Width = width;
5066 This->contextCache[i].Height = height;
5067 *context = &This->contextCache[i];
5071 if (i == CONTEXT_CACHE) {
5072 int minUsage = 0x7FFFFFFF; /* MAX_INT */
5073 glContext *dropContext = 0;
5074 for (i = 0; i < CONTEXT_CACHE; i++) {
5075 if (This->contextCache[i].usedcount < minUsage) {
5076 dropContext = &This->contextCache[i];
5077 minUsage = This->contextCache[i].usedcount;
5080 /* clean up the context (this doesn't work for ATI at the moment */
5082 glXDestroyContext(swapchain->display, dropContext->context);
5083 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
5086 dropContext->Width = 0;
5087 dropContext->pSurface = pSurface;
5088 *context = dropContext;
5090 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
5091 for (i = 0; i < CONTEXT_CACHE; i++) {
5092 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
5096 if (*context != NULL)
5099 return E_OUTOFMEMORY;
5102 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
5103 * the functionality needs splitting up so that we don't do more than we should do.
5104 * this only seems to impact performance a little.
5105 ******************************/
5106 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5107 IWineD3DSurface *RenderSurface) {
5108 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5110 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
5111 HRESULT ret = D3DERR_INVALIDCALL;
5112 IWineD3DSurface *tmp;
5114 * Currently only active for GLX >= 1.3
5115 * for others versions we'll have to use GLXPixmaps
5117 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
5118 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
5119 * so only check OpenGL version
5120 * ..........................
5121 * I don't believe that it is a problem with NVidia headers,
5122 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
5123 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
5125 * Your application will report GLX version 1.2 on glXQueryVersion.
5126 * However, it is safe to call the GLX 1.3 functions as described below.
5128 #if defined(GL_VERSION_1_3)
5130 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
5131 GLXFBConfig* cfgs = NULL;
5135 IWineD3DSwapChain *currentSwapchain;
5136 IWineD3DSwapChainImpl *swapchain;
5137 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
5138 * but switch them off if the StencilSurface is set to NULL
5139 ** *********************************************************/
5140 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
5141 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
5144 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
5145 it StencilSurface != NULL && zBufferTarget == NULL switch it on
5148 #define PUSH1(att) attribs[nAttribs++] = (att);
5149 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
5151 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
5153 /** TODO: remove the reff to Impl (context manager should fix this!) **/
5154 IWineD3DSwapChainImpl *impSwapChain;
5155 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
5156 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
5157 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
5162 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
5163 PUSH2(GLX_X_RENDERABLE, TRUE);
5164 PUSH2(GLX_DOUBLEBUFFER, TRUE);
5165 TRACE("calling makeglcfg\n");
5166 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
5169 TRACE("calling chooseFGConfig\n");
5170 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5173 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
5174 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
5175 why we failed and only show this message once! */
5176 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"); /**/
5178 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
5179 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
5180 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
5181 PUSH2(GLX_DOUBLEBUFFER, FALSE);
5182 TRACE("calling makeglcfg\n");
5183 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
5185 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5192 for (i = 0; i < nCfgs; ++i) {
5193 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
5194 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
5195 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
5198 if (NULL != This->renderTarget) {
5200 vcheckGLcall("glFlush");
5201 /** This is only useful if the old render target was a swapchain,
5202 * we need to supercede this with a function that displays
5203 * the current buffer on the screen. This is easy to do in glx1.3 but
5204 * we need to do copy-write pixels in glx 1.2.
5205 ************************************************/
5206 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
5208 printf("Hit Enter to get next frame ...\n");
5214 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain) != D3D_OK) {
5215 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
5216 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
5220 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
5221 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
5222 **********************************************************************/
5223 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == D3D_OK) {
5224 /* We also need to make sure that the lights &co are also in the context of the swapchains */
5225 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
5226 TRACE("making swapchain active\n");
5227 if (RenderSurface != This->renderTarget) {
5228 if (RenderSurface == swapchain->backBuffer) {
5230 /* This could be flagged so that some operations work directly with the front buffer */
5231 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
5233 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
5235 TRACE("Error in setting current context: context %p drawable %ld !\n",
5236 impSwapChain->glCtx, impSwapChain->win);
5239 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5241 checkGLcall("glXMakeContextCurrent");
5243 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5245 else if (pbuffer_support == TRUE && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
5247 /** ********************************************************************
5248 * This is a quickly hacked out implementation of offscreen textures.
5249 * It will work in most cases but there may be problems if the client
5250 * modifies the texture directly, or expects the contents of the rendertarget
5253 * There are some real speed vs compatibility issues here:
5254 * we should really use a new context for every texture, but that eats ram.
5255 * we should also be restoring the texture to the pbuffer but that eats CPU
5256 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
5257 * but if this means reusing the display backbuffer then we need to make sure that
5258 * states are correctly preserved.
5259 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
5260 * and gain a good performance increase at the cost of compatibility.
5261 * I would suggest that, when this is the case, a user configurable flag be made
5262 * available, allowing the user to choose the best emmulated experience for them.
5263 *********************************************************************/
5265 XVisualInfo *visinfo;
5266 glContext *newContext;
5268 /* Here were using a shared context model */
5269 if (D3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
5270 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5273 /* If the context doesn't exist then create a new one */
5274 /* TODO: This should really be part of findGlContext */
5275 if (NULL == newContext->context) {
5277 TRACE("making new buffer\n");
5279 PUSH2(GLX_PBUFFER_WIDTH, newContext->Width);
5280 PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
5283 newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
5285 /** ****************************************
5286 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
5288 * In future releases, we may provide the calls glXCreateNewContext,
5289 * glXQueryDrawable and glXMakeContextCurrent.
5290 * so until then we have to use glXGetVisualFromFBConfig &co..
5291 ********************************************/
5294 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
5296 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
5298 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
5302 if (NULL == newContext || NULL == newContext->context) {
5303 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5305 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
5306 if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
5307 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
5310 /* Clean up the old context */
5311 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5312 /* Set the current context of the swapchain to the new context */
5313 impSwapChain->drawable = newContext->drawable;
5314 impSwapChain->render_ctx = newContext->context;
5318 #if 1 /* Apply the stateblock to the new context
5319 FIXME: This is a bit of a hack, each context should know it's own state,
5320 the directX current directX state should then be applied to the context */
5323 IWineD3DStateBlockImpl *oldUpdateStateBlock;
5324 oldUpdateStateBlock = This->updateStateBlock;
5325 oldRecording= This->isRecordingState;
5326 This->isRecordingState = FALSE;
5327 This->updateStateBlock = This->stateBlock;
5328 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
5330 This->isRecordingState = oldRecording;
5331 This->updateStateBlock = oldUpdateStateBlock;
5336 /* clean up the current rendertargets swapchain (if it belonged to one) */
5337 if (currentSwapchain != NULL) {
5338 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
5341 /* Were done with the opengl context management, setup the rendertargets */
5343 tmp = This->renderTarget;
5344 This->renderTarget = RenderSurface;
5345 IWineD3DSurface_AddRef(This->renderTarget);
5346 IWineD3DSurface_Release(tmp);
5352 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
5353 /* Check that the container is not a swapchain member */
5355 IWineD3DSwapChain *tmpSwapChain;
5356 if (D3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
5357 This->renderUpsideDown = TRUE;
5359 This->renderUpsideDown = FALSE;
5360 IWineD3DSwapChain_Release(tmpSwapChain);
5362 /* Force updating the cull mode */
5363 TRACE("setting render state\n");
5364 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
5365 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
5367 /* Force updating projection matrix */
5368 This->last_was_rhw = FALSE;
5369 This->proj_valid = FALSE;
5377 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
5378 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
5383 if ( NULL != impSwapChain) {
5384 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
5392 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
5393 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
5394 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5395 /* TODO: the use of Impl is deprecated. */
5396 /* some basic validation checks */
5397 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
5399 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
5401 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
5402 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
5403 return D3DERR_INVALIDCALL;
5405 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
5406 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
5407 return D3DERR_INVALIDCALL;
5409 /* TODO: make the cursor 'real' */
5411 This->xHotSpot = XHotSpot;
5412 This->yHotSpot = YHotSpot;
5417 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
5418 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5419 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
5421 This->xScreenSpace = XScreenSpace;
5422 This->yScreenSpace = YScreenSpace;
5428 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
5429 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5430 TRACE("(%p) : visible(%d)\n", This, bShow);
5432 This->bCursorVisible = bShow;
5437 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
5438 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5439 FIXME("(%p) : stub\n", This); /* No way of notifying yet! */
5444 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
5445 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5446 /** FIXME: Resource tracking needs to be done,
5447 * The closes we can do to this is set the priorities of all managed textures low
5448 * and then reset them.
5449 ***********************************************************/
5450 FIXME("(%p) : stub\n", This);
5454 HRESULT WINAPI IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
5455 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5456 /** FIXME: Resource trascking needs to be done.
5457 * in effect this pulls all non only default
5458 * textures out of video memory and deletes all glTextures (glDeleteTextures)
5459 * and should clear down the context and set it up according to pPresentationParameters
5460 ***********************************************************/
5461 FIXME("(%p) : stub\n", This);
5465 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
5466 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5467 /** FIXME: always true at the moment **/
5468 if(bEnableDialogs == FALSE) {
5469 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
5475 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
5476 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5478 FIXME("(%p) : stub\n", This);
5479 /* Setup some reasonable defaults */
5480 pParameters->AdapterOrdinal = 0; /* always for now */
5481 pParameters->DeviceType = D3DDEVTYPE_HAL; /* always for now */
5482 pParameters->hFocusWindow = 0;
5483 pParameters->BehaviorFlags =0;
5487 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
5488 IWineD3DSwapChain *swapchain;
5489 HRESULT hrc = D3D_OK;
5491 TRACE("Relaying to swapchain\n");
5493 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
5494 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (D3DGAMMARAMP *)pRamp);
5495 IWineD3DSwapChain_Release(swapchain);
5500 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
5501 IWineD3DSwapChain *swapchain;
5502 HRESULT hrc = D3D_OK;
5504 TRACE("Relaying to swapchain\n");
5506 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
5507 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
5508 IWineD3DSwapChain_Release(swapchain);
5514 /** ********************************************************
5515 * Notification functions
5516 ** ********************************************************/
5517 /** This function must be called in the release of a resource when ref == 0,
5518 * the contents of resource must still be correct,
5519 * any handels to other resource held by the caller must be closed
5520 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
5521 *****************************************************/
5522 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5523 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5524 ResourceList* resourceList;
5526 TRACE("(%p) : resource %p\n", This, resource);
5528 EnterCriticalSection(&resourceStoreCriticalSection);
5530 /* add a new texture to the frot of the linked list */
5531 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
5532 resourceList->resource = resource;
5534 /* Get the old head */
5535 resourceList->next = This->resources;
5537 This->resources = resourceList;
5538 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
5541 LeaveCriticalSection(&resourceStoreCriticalSection);
5546 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5547 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5548 ResourceList* resourceList = NULL;
5549 ResourceList* previousResourceList = NULL;
5551 TRACE("(%p) : resource %p\n", This, resource);
5554 EnterCriticalSection(&resourceStoreCriticalSection);
5556 resourceList = This->resources;
5558 while (resourceList != NULL) {
5559 if(resourceList->resource == resource) break;
5560 previousResourceList = resourceList;
5561 resourceList = resourceList->next;
5564 if (resourceList == NULL) {
5565 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
5567 LeaveCriticalSection(&resourceStoreCriticalSection);
5571 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
5573 /* make sure we don't leave a hole in the list */
5574 if (previousResourceList != NULL) {
5575 previousResourceList->next = resourceList->next;
5577 This->resources = resourceList->next;
5581 LeaveCriticalSection(&resourceStoreCriticalSection);
5587 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
5588 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5591 TRACE("(%p) : resource %p\n", This, resource);
5592 switch(IWineD3DResource_GetType(resource)){
5593 case D3DRTYPE_SURFACE:
5594 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
5596 case D3DRTYPE_TEXTURE:
5597 case D3DRTYPE_CUBETEXTURE:
5598 case D3DRTYPE_VOLUMETEXTURE:
5599 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
5600 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5601 IUnknown *textureParent;
5602 IWineD3DBaseTexture_GetParent(This->stateBlock->textures[counter], &textureParent);
5603 /* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
5604 FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter, resource, textureParent);
5605 IUnknown_Release(textureParent);
5606 This->stateBlock->textures[counter] = NULL;
5608 if (This->updateStateBlock != This->stateBlock ){
5609 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5610 IUnknown *textureParent;
5611 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[counter], &textureParent);
5612 /* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
5613 FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter, resource, textureParent);
5614 IUnknown_Release(textureParent);
5615 This->updateStateBlock->textures[counter] = NULL;
5620 case D3DRTYPE_VOLUME:
5621 /* TODO: nothing really? */
5623 case D3DRTYPE_VERTEXBUFFER:
5624 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
5627 TRACE("Cleaning up stream pointers\n");
5629 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
5630 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
5631 FINDOUT: should changes.streamSource[StreamNumber] be set ?
5633 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5634 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
5635 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
5636 This->updateStateBlock->streamSource[streamNumber] = 0;
5637 /* Set changed flag? */
5640 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) */
5641 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
5642 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
5643 This->stateBlock->streamSource[streamNumber] = 0;
5646 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
5647 else { /* This shouldn't happen */
5648 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
5655 case D3DRTYPE_INDEXBUFFER:
5656 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
5657 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5658 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5659 This->updateStateBlock->pIndexData = NULL;
5662 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
5663 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5664 This->stateBlock->pIndexData = NULL;
5670 FIXME("(%p) unknown resource type %p %u \n", This, resource, IWineD3DResource_GetType(resource));
5675 /* Remove the resoruce from the resourceStore */
5676 IWineD3DDeviceImpl_RemoveResource(iface, resource);
5678 TRACE("Resource released\n");
5683 /** This function is to be called by the swapchain when it is released and it's ref = 0
5684 *****************************************************/
5685 void WINAPI IWineD3DDeviceImpl_SwapChainReleased(IWineD3DDevice *iface, IWineD3DSwapChain *swapChain){
5686 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5687 SwapChainList **nextSwapchain;
5688 nextSwapchain = &This->swapchains;
5690 /* Check to see if the swapchian is being used as the render target */
5691 if (This->renderTarget != NULL) {
5692 IWineD3DSurface *swapchainBackBuffer;
5694 IWineD3DSwapChain_GetBackBuffer(swapChain, 0 ,( D3DBACKBUFFER_TYPE) 0, &swapchainBackBuffer);
5695 if (This->renderTarget == swapchainBackBuffer) {
5696 /* Don't know what to do, so warn and carry on as usual (which in this case leaves the renderterget in limbo) */
5697 FIXME("Atempting to release a swapchain that is currently beuing used as a render target, behaviour is undefined\n");
5701 /* Go through the swapchain list and try to find the swapchain being released */
5702 while(*nextSwapchain != NULL && (*nextSwapchain)->swapchain != swapChain) {
5703 nextSwapchain = &(*nextSwapchain)->next;
5706 /* Check to see if we found the swapchain */
5707 if (NULL != *nextSwapchain) {
5708 /* We found the swapchain so remove it from the list */
5709 TRACE("(%p) releasing swapchain(%p)\n", iface, swapChain);
5710 HeapFree(GetProcessHeap(), 0 , *nextSwapchain);
5711 *nextSwapchain = (*nextSwapchain)->next;
5713 /* We didn't find the swapchain on the list, this can only heppen because of a programming error in wined3d */
5714 FIXME("(%p) Attempting to release a swapchain (%p) that hasn't been stored\n", iface, swapChain);
5717 TRACE("swapchain (%p) released\n", swapChain);
5721 /**********************************************************
5722 * IWineD3DDevice VTbl follows
5723 **********************************************************/
5725 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
5727 /*** IUnknown methods ***/
5728 IWineD3DDeviceImpl_QueryInterface,
5729 IWineD3DDeviceImpl_AddRef,
5730 IWineD3DDeviceImpl_Release,
5731 /*** IWineD3DDevice methods ***/
5732 IWineD3DDeviceImpl_GetParent,
5733 /*** Creation methods**/
5734 IWineD3DDeviceImpl_CreateVertexBuffer,
5735 IWineD3DDeviceImpl_CreateIndexBuffer,
5736 IWineD3DDeviceImpl_CreateStateBlock,
5737 IWineD3DDeviceImpl_CreateSurface,
5738 IWineD3DDeviceImpl_CreateTexture,
5739 IWineD3DDeviceImpl_CreateVolumeTexture,
5740 IWineD3DDeviceImpl_CreateVolume,
5741 IWineD3DDeviceImpl_CreateCubeTexture,
5742 IWineD3DDeviceImpl_CreateQuery,
5743 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
5744 IWineD3DDeviceImpl_CreateVertexDeclaration,
5745 IWineD3DDeviceImpl_CreateVertexShader,
5746 IWineD3DDeviceImpl_CreatePixelShader,
5748 /*** Odd functions **/
5749 IWineD3DDeviceImpl_EvictManagedResources,
5750 IWineD3DDeviceImpl_GetAvailableTextureMem,
5751 IWineD3DDeviceImpl_GetBackBuffer,
5752 IWineD3DDeviceImpl_GetCreationParameters,
5753 IWineD3DDeviceImpl_GetDeviceCaps,
5754 IWineD3DDeviceImpl_GetDirect3D,
5755 IWineD3DDeviceImpl_GetDisplayMode,
5756 IWineD3DDeviceImpl_GetNumberOfSwapChains,
5757 IWineD3DDeviceImpl_GetRasterStatus,
5758 IWineD3DDeviceImpl_GetSwapChain,
5759 IWineD3DDeviceImpl_Reset,
5760 IWineD3DDeviceImpl_SetDialogBoxMode,
5761 IWineD3DDeviceImpl_SetCursorProperties,
5762 IWineD3DDeviceImpl_SetCursorPosition,
5763 IWineD3DDeviceImpl_ShowCursor,
5764 IWineD3DDeviceImpl_TestCooperativeLevel,
5765 /*** Getters and setters **/
5766 IWineD3DDeviceImpl_SetClipPlane,
5767 IWineD3DDeviceImpl_GetClipPlane,
5768 IWineD3DDeviceImpl_SetClipStatus,
5769 IWineD3DDeviceImpl_GetClipStatus,
5770 IWineD3DDeviceImpl_SetCurrentTexturePalette,
5771 IWineD3DDeviceImpl_GetCurrentTexturePalette,
5772 IWineD3DDeviceImpl_SetDepthStencilSurface,
5773 IWineD3DDeviceImpl_GetDepthStencilSurface,
5774 IWineD3DDeviceImpl_SetFVF,
5775 IWineD3DDeviceImpl_GetFVF,
5776 IWineD3DDeviceImpl_SetGammaRamp,
5777 IWineD3DDeviceImpl_GetGammaRamp,
5778 IWineD3DDeviceImpl_SetIndices,
5779 IWineD3DDeviceImpl_GetIndices,
5780 IWineD3DDeviceImpl_SetLight,
5781 IWineD3DDeviceImpl_GetLight,
5782 IWineD3DDeviceImpl_SetLightEnable,
5783 IWineD3DDeviceImpl_GetLightEnable,
5784 IWineD3DDeviceImpl_SetMaterial,
5785 IWineD3DDeviceImpl_GetMaterial,
5786 IWineD3DDeviceImpl_SetNPatchMode,
5787 IWineD3DDeviceImpl_GetNPatchMode,
5788 IWineD3DDeviceImpl_SetPaletteEntries,
5789 IWineD3DDeviceImpl_GetPaletteEntries,
5790 IWineD3DDeviceImpl_SetPixelShader,
5791 IWineD3DDeviceImpl_GetPixelShader,
5792 IWineD3DDeviceImpl_SetPixelShaderConstantB,
5793 IWineD3DDeviceImpl_GetPixelShaderConstantB,
5794 IWineD3DDeviceImpl_SetPixelShaderConstantI,
5795 IWineD3DDeviceImpl_GetPixelShaderConstantI,
5796 IWineD3DDeviceImpl_SetPixelShaderConstantF,
5797 IWineD3DDeviceImpl_GetPixelShaderConstantF,
5798 IWineD3DDeviceImpl_SetRenderState,
5799 IWineD3DDeviceImpl_GetRenderState,
5800 IWineD3DDeviceImpl_SetRenderTarget,
5801 IWineD3DDeviceImpl_GetRenderTarget,
5802 IWineD3DDeviceImpl_SetSamplerState,
5803 IWineD3DDeviceImpl_GetSamplerState,
5804 IWineD3DDeviceImpl_SetScissorRect,
5805 IWineD3DDeviceImpl_GetScissorRect,
5806 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
5807 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
5808 IWineD3DDeviceImpl_SetStreamSource,
5809 IWineD3DDeviceImpl_GetStreamSource,
5810 IWineD3DDeviceImpl_SetStreamSourceFreq,
5811 IWineD3DDeviceImpl_GetStreamSourceFreq,
5812 IWineD3DDeviceImpl_SetTexture,
5813 IWineD3DDeviceImpl_GetTexture,
5814 IWineD3DDeviceImpl_SetTextureStageState,
5815 IWineD3DDeviceImpl_GetTextureStageState,
5816 IWineD3DDeviceImpl_SetTransform,
5817 IWineD3DDeviceImpl_GetTransform,
5818 IWineD3DDeviceImpl_SetVertexDeclaration,
5819 IWineD3DDeviceImpl_GetVertexDeclaration,
5820 IWineD3DDeviceImpl_SetVertexShader,
5821 IWineD3DDeviceImpl_GetVertexShader,
5822 IWineD3DDeviceImpl_SetVertexShaderConstantB,
5823 IWineD3DDeviceImpl_GetVertexShaderConstantB,
5824 IWineD3DDeviceImpl_SetVertexShaderConstantI,
5825 IWineD3DDeviceImpl_GetVertexShaderConstantI,
5826 IWineD3DDeviceImpl_SetVertexShaderConstantF,
5827 IWineD3DDeviceImpl_GetVertexShaderConstantF,
5828 IWineD3DDeviceImpl_SetViewport,
5829 IWineD3DDeviceImpl_GetViewport,
5830 IWineD3DDeviceImpl_MultiplyTransform,
5831 IWineD3DDeviceImpl_ValidateDevice,
5832 IWineD3DDeviceImpl_ProcessVertices,
5833 /*** State block ***/
5834 IWineD3DDeviceImpl_BeginStateBlock,
5835 IWineD3DDeviceImpl_EndStateBlock,
5836 /*** Scene management ***/
5837 IWineD3DDeviceImpl_BeginScene,
5838 IWineD3DDeviceImpl_EndScene,
5839 IWineD3DDeviceImpl_Present,
5840 IWineD3DDeviceImpl_Clear,
5842 IWineD3DDeviceImpl_DrawPrimitive,
5843 IWineD3DDeviceImpl_DrawIndexedPrimitive,
5844 IWineD3DDeviceImpl_DrawPrimitiveUP,
5845 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
5846 IWineD3DDeviceImpl_DrawRectPatch,
5847 IWineD3DDeviceImpl_DrawTriPatch,
5848 IWineD3DDeviceImpl_DeletePatch,
5849 IWineD3DDeviceImpl_ColorFill,
5850 IWineD3DDeviceImpl_UpdateTexture,
5851 IWineD3DDeviceImpl_UpdateSurface,
5852 IWineD3DDeviceImpl_StretchRect,
5853 IWineD3DDeviceImpl_GetRenderTargetData,
5854 IWineD3DDeviceImpl_GetFrontBufferData,
5855 /*** Internal use IWineD3DDevice methods ***/
5856 IWineD3DDeviceImpl_SetupTextureStates,
5857 IWineD3DDeviceImpl_SwapChainReleased,
5858 /*** object tracking ***/
5859 IWineD3DDeviceImpl_ResourceReleased
5863 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
5864 WINED3DRS_ALPHABLENDENABLE ,
5865 WINED3DRS_ALPHAFUNC ,
5866 WINED3DRS_ALPHAREF ,
5867 WINED3DRS_ALPHATESTENABLE ,
5869 WINED3DRS_COLORWRITEENABLE ,
5870 WINED3DRS_DESTBLEND ,
5871 WINED3DRS_DITHERENABLE ,
5872 WINED3DRS_FILLMODE ,
5873 WINED3DRS_FOGDENSITY ,
5875 WINED3DRS_FOGSTART ,
5876 WINED3DRS_LASTPIXEL ,
5877 WINED3DRS_SHADEMODE ,
5878 WINED3DRS_SRCBLEND ,
5879 WINED3DRS_STENCILENABLE ,
5880 WINED3DRS_STENCILFAIL ,
5881 WINED3DRS_STENCILFUNC ,
5882 WINED3DRS_STENCILMASK ,
5883 WINED3DRS_STENCILPASS ,
5884 WINED3DRS_STENCILREF ,
5885 WINED3DRS_STENCILWRITEMASK ,
5886 WINED3DRS_STENCILZFAIL ,
5887 WINED3DRS_TEXTUREFACTOR ,
5898 WINED3DRS_ZWRITEENABLE
5901 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
5902 WINED3DTSS_ADDRESSW ,
5903 WINED3DTSS_ALPHAARG0 ,
5904 WINED3DTSS_ALPHAARG1 ,
5905 WINED3DTSS_ALPHAARG2 ,
5906 WINED3DTSS_ALPHAOP ,
5907 WINED3DTSS_BUMPENVLOFFSET ,
5908 WINED3DTSS_BUMPENVLSCALE ,
5909 WINED3DTSS_BUMPENVMAT00 ,
5910 WINED3DTSS_BUMPENVMAT01 ,
5911 WINED3DTSS_BUMPENVMAT10 ,
5912 WINED3DTSS_BUMPENVMAT11 ,
5913 WINED3DTSS_COLORARG0 ,
5914 WINED3DTSS_COLORARG1 ,
5915 WINED3DTSS_COLORARG2 ,
5916 WINED3DTSS_COLOROP ,
5917 WINED3DTSS_RESULTARG ,
5918 WINED3DTSS_TEXCOORDINDEX ,
5919 WINED3DTSS_TEXTURETRANSFORMFLAGS
5922 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
5923 WINED3DSAMP_ADDRESSU ,
5924 WINED3DSAMP_ADDRESSV ,
5925 WINED3DSAMP_ADDRESSW ,
5926 WINED3DSAMP_BORDERCOLOR ,
5927 WINED3DSAMP_MAGFILTER ,
5928 WINED3DSAMP_MINFILTER ,
5929 WINED3DSAMP_MIPFILTER ,
5930 WINED3DSAMP_MIPMAPLODBIAS ,
5931 WINED3DSAMP_MAXMIPLEVEL ,
5932 WINED3DSAMP_MAXANISOTROPY ,
5933 WINED3DSAMP_SRGBTEXTURE ,
5934 WINED3DSAMP_ELEMENTINDEX
5937 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
5939 WINED3DRS_AMBIENTMATERIALSOURCE ,
5940 WINED3DRS_CLIPPING ,
5941 WINED3DRS_CLIPPLANEENABLE ,
5942 WINED3DRS_COLORVERTEX ,
5943 WINED3DRS_DIFFUSEMATERIALSOURCE ,
5944 WINED3DRS_EMISSIVEMATERIALSOURCE ,
5945 WINED3DRS_FOGDENSITY ,
5947 WINED3DRS_FOGSTART ,
5948 WINED3DRS_FOGTABLEMODE ,
5949 WINED3DRS_FOGVERTEXMODE ,
5950 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
5951 WINED3DRS_LIGHTING ,
5952 WINED3DRS_LOCALVIEWER ,
5953 WINED3DRS_MULTISAMPLEANTIALIAS ,
5954 WINED3DRS_MULTISAMPLEMASK ,
5955 WINED3DRS_NORMALIZENORMALS ,
5956 WINED3DRS_PATCHEDGESTYLE ,
5957 WINED3DRS_POINTSCALE_A ,
5958 WINED3DRS_POINTSCALE_B ,
5959 WINED3DRS_POINTSCALE_C ,
5960 WINED3DRS_POINTSCALEENABLE ,
5961 WINED3DRS_POINTSIZE ,
5962 WINED3DRS_POINTSIZE_MAX ,
5963 WINED3DRS_POINTSIZE_MIN ,
5964 WINED3DRS_POINTSPRITEENABLE ,
5965 WINED3DRS_RANGEFOGENABLE ,
5966 WINED3DRS_SPECULARMATERIALSOURCE ,
5967 WINED3DRS_TWEENFACTOR ,
5968 WINED3DRS_VERTEXBLEND
5971 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
5972 WINED3DTSS_TEXCOORDINDEX ,
5973 WINED3DTSS_TEXTURETRANSFORMFLAGS
5976 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
5977 WINED3DSAMP_DMAPOFFSET