2 * IWineD3DDevice implementation
4 * Copyright 2002-2005 Jason Edmeades
5 * Copyright 2003-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "wined3d_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
28 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
29 WINE_DECLARE_DEBUG_CHANNEL(d3d_fps);
30 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
31 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
33 /* x11drv GDI escapes */
34 #define X11DRV_ESCAPE 6789
35 enum x11drv_escape_codes
37 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
38 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
39 X11DRV_GET_FONT, /* get current X font for a DC */
42 /* retrieve the X display to use on a given DC */
43 inline static Display *get_display( HDC hdc )
46 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
48 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
49 sizeof(display), (LPSTR)&display )) display = NULL;
53 /* Memory tracking and object counting */
54 static unsigned int emulated_textureram = 64*1024*1024;
56 /* TODO: setup some flags in the regestry to enable, disable pbuffer support */
57 /* enable pbuffer support for offscreen textures */
58 BOOL pbuffer_support = FALSE;
59 /* allocate one pbuffer per surface */
60 BOOL pbuffer_per_surface = FALSE;
62 /* static function declarations */
63 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
65 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type);
68 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return D3DERR_OUTOFVIDEOMEMORY;}
70 #define D3DCREATEOBJECTINSTANCE(object, type) { \
71 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
72 D3DMEMCHECK(object, pp##type); \
73 object->lpVtbl = &IWineD3D##type##_Vtbl; \
74 object->wineD3DDevice = This; \
75 object->parent = parent; \
77 *pp##type = (IWineD3D##type *) object; \
80 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
81 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
82 D3DMEMCHECK(object, pp##type); \
83 object->lpVtbl = &IWineD3D##type##_Vtbl; \
84 object->resource.wineD3DDevice = This; \
85 object->resource.parent = parent; \
86 object->resource.resourceType = d3dtype; \
87 object->resource.ref = 1; \
88 object->resource.pool = Pool; \
89 object->resource.format = Format; \
90 object->resource.usage = Usage; \
91 object->resource.size = _size; \
92 /* Check that we have enough video ram left */ \
93 if (Pool == D3DPOOL_DEFAULT) { \
94 if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
95 WARN("Out of 'bogus' video memory\n"); \
96 HeapFree(GetProcessHeap(), 0, object); \
98 return D3DERR_OUTOFVIDEOMEMORY; \
100 globalChangeGlRam(_size); \
102 object->resource.allocatedMemory = (0 == _size ? NULL : Pool == D3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
103 if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != D3DPOOL_DEFAULT) { \
104 FIXME("Out of memory!\n"); \
105 HeapFree(GetProcessHeap(), 0, object); \
107 return D3DERR_OUTOFVIDEOMEMORY; \
109 *pp##type = (IWineD3D##type *) object; \
110 IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
111 TRACE("(%p) : Created resource %p\n", This, object); \
114 #define D3DINITILIZEBASETEXTURE(_basetexture) { \
115 _basetexture.levels = Levels; \
116 _basetexture.filterType = (Usage & D3DUSAGE_AUTOGENMIPMAP) ? D3DTEXF_LINEAR : D3DTEXF_NONE; \
117 _basetexture.LOD = 0; \
118 _basetexture.dirty = TRUE; \
121 /**********************************************************
122 * Global variable / Constants follow
123 **********************************************************/
124 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
126 /**********************************************************
127 * Utility functions follow
128 **********************************************************/
129 /* Convert the D3DLIGHT properties into equivalent gl lights */
130 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
133 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
134 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
136 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
137 glMatrixMode(GL_MODELVIEW);
139 glLoadMatrixf((float *)&This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
142 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
143 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
144 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
145 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
146 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
147 checkGLcall("glLightfv");
150 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
151 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
152 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
153 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
154 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
155 checkGLcall("glLightfv");
158 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
159 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
160 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
161 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
162 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
163 checkGLcall("glLightfv");
165 /* Attenuation - Are these right? guessing... */
166 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
167 checkGLcall("glLightf");
168 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
169 checkGLcall("glLightf");
171 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) != 0) {
172 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
174 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
177 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
178 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
179 checkGLcall("glLightf");
181 switch (lightInfo->OriginalParms.Type) {
184 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
185 checkGLcall("glLightfv");
186 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
187 checkGLcall("glLightf");
193 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
194 checkGLcall("glLightfv");
196 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
197 checkGLcall("glLightfv");
198 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
199 checkGLcall("glLightf");
200 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
201 checkGLcall("glLightf");
205 case D3DLIGHT_DIRECTIONAL:
207 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
208 checkGLcall("glLightfv");
209 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
210 checkGLcall("glLightf");
211 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
212 checkGLcall("glLightf");
216 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
219 /* Restore the modelview matrix */
223 /* Apply the current values to the specified texture stage */
224 void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Sampler, DWORD Flags) {
225 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
233 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
234 clamping, MIPLOD, etc. This will work for up to 16 samplers.
237 if (Sampler >= GL_LIMITS(samplers)) {
238 FIXME("Trying to set the state of more samplers %ld than are supported %d by this openGL implementation\n", Sampler, GL_LIMITS(samplers));
241 VTRACE(("Activating appropriate texture state %ld\n", Sampler));
242 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
244 GLACTIVETEXTURE(Sampler);
246 /* Could we use bindTexture and then apply the states instead of GLACTIVETEXTURE */
247 } else if (Sampler > 0) {
248 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
252 /* TODO: change this to a lookup table
253 LOOKUP_TEXTURE_STATES lists all texture states that should be applied.
254 LOOKUP_CONTEXT_SATES list all context applicable states that can be applied
255 etc.... it's a lot cleaner, quicker and possibly easier to maintain than running a switch and setting a skip flag...
256 especially when there are a number of groups of states. */
258 TRACE("-----------------------> Updating the texture at Sampler %ld to have new texture state information\n", Sampler);
260 /* The list of states not to apply is a big as the list of states to apply, so it makes sense to produce an inclusive list */
261 #define APPLY_STATE(_state) IWineD3DDeviceImpl_ApplyTextureUnitState(iface, Sampler, _state)
262 /* these are the only two supported states that need to be applied */
263 APPLY_STATE(WINED3DTSS_TEXCOORDINDEX);
264 APPLY_STATE(WINED3DTSS_TEXTURETRANSFORMFLAGS);
265 #if 0 /* not supported at the moment */
266 APPLY_STATE(WINED3DTSS_BUMPENVMAT00);
267 APPLY_STATE(WINED3DTSS_BUMPENVMAT01);
268 APPLY_STATE(WINED3DTSS_BUMPENVMAT10);
269 APPLY_STATE(WINED3DTSS_BUMPENVMAT11);
270 APPLY_STATE(WINED3DTSS_BUMPENVLSCALE);
271 APPLY_STATE(WINED3DTSS_BUMPENVLOFFSET);
272 APPLY_STATE(WINED3DTSS_RESULTARG);
273 APPLY_STATE(WINED3DTSS_CONSTANT);
275 /* a quick sanity check in case someone forgot to update this function */
276 if (WINED3D_HIGHEST_TEXTURE_STATE > WINED3DTSS_CONSTANT) {
277 FIXME("(%p) : There are more texture states than expected, update device.c to match\n", This);
281 /* apply any sampler states that always need applying */
282 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
283 tmpvalue.d = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPMAPLODBIAS];
284 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
285 GL_TEXTURE_LOD_BIAS_EXT,
287 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
290 /* Note the D3DRS value applies to all textures, but GL has one
291 * per texture, so apply it now ready to be used!
293 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
294 /* Set the default alpha blend color */
295 glBlendColor(col[0], col[1], col[2], col[3]);
296 checkGLcall("glBlendColor");
298 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
299 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
300 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
302 TRACE("-----------------------> Updated the texture at Sampler %ld to have new texture state information\n", Sampler);
305 /**********************************************************
306 * IUnknown parts follows
307 **********************************************************/
309 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
311 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
312 /* FIXME: This needs to extend an IWineD3DBaseObject */
314 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
315 if (IsEqualGUID(riid, &IID_IUnknown)
316 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
317 IUnknown_AddRef(iface);
322 return E_NOINTERFACE;
325 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
326 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
327 ULONG refCount = InterlockedIncrement(&This->ref);
329 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
333 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
334 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
335 ULONG refCount = InterlockedDecrement(&This->ref);
337 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
340 /* TODO: Clean up all the surfaces and textures! */
341 /* FIXME: Create targets and state blocks in d3d8 */
342 if (((IWineD3DImpl *)This->wineD3D)->dxVersion > 8) { /*We don't create a state block in d3d8 yet*/
343 /* NOTE: You must release the parent if the object was created via a callback
344 ** ***************************/
345 IUnknown* swapChainParent;
347 /* NOTE: Don't release swapchain 0 here, it's 'special' */
348 SwapChainList *nextSwapchain = This->swapchains;
349 if (nextSwapchain != NULL) {
350 nextSwapchain = nextSwapchain->next;
352 WARN("Expected to find the implicit swapchain\n");
355 /* release all the other swapchains */
356 while (nextSwapchain != NULL) {
357 SwapChainList *prevSwapchain = nextSwapchain;
358 nextSwapchain = nextSwapchain->next;
359 IWineD3DSwapChain_Release(prevSwapchain->swapchain);
360 /* NOTE: no need to free the list element, it will be done by the release callback
361 HeapFree(GetProcessHeap(), 0, prevSwapchain); */
364 if (This->stateBlock != NULL) {
365 IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->stateBlock);
368 if (This->swapchains != NULL) {
369 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
370 IWineD3DSwapChain_GetParent(This->swapchains->swapchain, &swapChainParent);
371 IUnknown_Release(swapChainParent); /* once for the get parent */
372 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
373 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
378 IWineD3D_Release(This->wineD3D);
379 HeapFree(GetProcessHeap(), 0, This);
384 /**********************************************************
385 * IWineD3DDevice implementation follows
386 **********************************************************/
387 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
388 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
389 *pParent = This->parent;
390 IUnknown_AddRef(This->parent);
394 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
395 DWORD FVF, D3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
397 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
398 IWineD3DVertexBufferImpl *object;
399 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
400 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, D3DRTYPE_VERTEXBUFFER, Size)
403 if (Pool == D3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
404 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
408 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
409 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
414 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
415 WINED3DFORMAT Format, D3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
416 HANDLE *sharedHandle, IUnknown *parent) {
417 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
418 IWineD3DIndexBufferImpl *object;
419 TRACE("(%p) Creating index buffer\n", This);
421 /* Allocate the storage for the device */
422 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,D3DRTYPE_INDEXBUFFER, Length)
425 if (Pool == D3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
426 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
429 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
430 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
431 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
436 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
438 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
439 IWineD3DStateBlockImpl *object;
442 D3DCREATEOBJECTINSTANCE(object, StateBlock)
443 object->blockType = Type;
445 /* Special case - Used during initialization to produce a placeholder stateblock
446 so other functions called can update a state block */
447 if (Type == WINED3DSBT_INIT) {
448 /* Don't bother increasing the reference count otherwise a device will never
449 be freed due to circular dependencies */
453 /* Otherwise, might as well set the whole state block to the appropriate values */
454 if ( This->stateBlock != NULL) {
455 memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
457 memset(object->streamFreq, 1, sizeof(object->streamFreq));
460 /* Reset the ref and type after kludging it */
461 object->wineD3DDevice = This;
463 object->blockType = Type;
465 TRACE("Updating changed flags appropriate for type %d\n", Type);
467 if (Type == WINED3DSBT_ALL) {
469 TRACE("ALL => Pretend everything has changed\n");
470 memset(&object->changed, TRUE, sizeof(This->stateBlock->changed));
471 } else if (Type == WINED3DSBT_PIXELSTATE) {
473 TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
474 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
475 /* TODO: Pixel Shader Constants */
476 object->changed.pixelShader = TRUE;
477 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
478 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
481 } else if (Type == WINED3DSBT_VERTEXSTATE) {
483 TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
484 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
485 /* TODO: Vertex Shader Constants */
486 object->changed.vertexShader = TRUE;
487 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
488 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
491 /* Duplicate light chain */
493 PLIGHTINFOEL *src = NULL;
494 PLIGHTINFOEL *dst = NULL;
495 PLIGHTINFOEL *newEl = NULL;
496 src = This->stateBlock->lights;
497 object->lights = NULL;
501 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
502 if (newEl == NULL) return D3DERR_OUTOFVIDEOMEMORY;
503 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
505 newEl->changed = TRUE;
506 newEl->enabledChanged = TRUE;
508 object->lights = newEl;
519 FIXME("Unrecognized state block type %d\n", Type);
522 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
527 /* ************************************
529 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
532 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
534 If this flag is set, the contents of the depth stencil buffer will be invalid after calling either IDirect3DDevice9::Present or IDirect3DDevice9::SetDepthStencilSurface with a different depth surface.
536 ******************************** */
538 HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height, WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **ppSurface,D3DRESOURCETYPE Type, DWORD Usage, D3DPOOL Pool, D3DMULTISAMPLE_TYPE MultiSample ,DWORD MultisampleQuality, HANDLE* pSharedHandle, IUnknown *parent) {
539 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
540 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
541 unsigned int pow2Width, pow2Height;
542 unsigned int Size = 1;
543 TRACE("(%p) Create surface\n",This);
545 /** FIXME: Check ranges on the inputs are valid
548 * [in] Quality level. The valid range is between zero and one less than the level
549 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
550 * Passing a larger value returns the error D3DERR_INVALIDCALL. The MultisampleQuality
551 * values of paired render targets, depth stencil surfaces, and the MultiSample type
553 *******************************/
558 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
560 * If this flag is set, the contents of the depth stencil buffer will be
561 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
562 * with a different depth surface.
564 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
565 ***************************/
567 if(MultisampleQuality < 0) {
568 FIXME("Invalid multisample level %ld \n", MultisampleQuality);
569 return D3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
572 if(MultisampleQuality > 0) {
573 FIXME("MultisampleQuality set to %ld, substituting 0 \n" , MultisampleQuality);
574 MultisampleQuality=0;
577 /** FIXME: Check that the format is supported
579 *******************************/
580 /* TODO: add support for dxt2 and dxt4 formats */
581 if (Format == D3DFMT_DXT2 || Format == D3DFMT_DXT4) return D3DERR_NOTAVAILABLE;
583 /* Non-power2 support */
585 /* Find the nearest pow2 match */
586 pow2Width = pow2Height = 1;
587 while (pow2Width < Width) pow2Width <<= 1;
588 while (pow2Height < Height) pow2Height <<= 1;
590 if (pow2Width > Width || pow2Height > Height) {
591 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
592 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
593 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
594 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d) \n",
595 This, Width, Height);
596 return D3DERR_NOTAVAILABLE;
600 /** Check against the maximum texture sizes supported by the video card **/
601 if (pow2Width > GL_LIMITS(texture_size) || pow2Height > GL_LIMITS(texture_size)) {
602 /* one of three options
603 1: Do the same as we do with nonpow 2 and scale the texture, (any texture ops would require the texture to be scaled which is potentially slow)
604 2: Set the texture to the maxium size (bad idea)
605 3: WARN and return D3DERR_NOTAVAILABLE;
607 WARN("(%p) Application requested a surface w %d, h %d, but the graphics card only supports %d\n", This, Width, Height, GL_LIMITS(texture_size));
608 return D3DERR_NOTAVAILABLE;
613 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
614 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
616 *********************************/
617 if (Format == WINED3DFMT_DXT1) {
618 /* DXT1 is half byte per pixel */
619 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4)) >> 1;
621 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
622 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
623 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4));
625 Size = (pow2Width * D3DFmtGetBpp(This, Format)) * pow2Height;
628 /** Create the and initilise surface resource **/
629 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,D3DRTYPE_SURFACE, Size)
630 object->container = (IUnknown*) This;
632 object->currentDesc.Width = Width;
633 object->currentDesc.Height = Height;
634 object->currentDesc.MultiSampleType = MultiSample;
635 object->currentDesc.MultiSampleQuality = MultisampleQuality;
637 /* Setup some glformat defaults */
638 object->glDescription.glFormat = D3DFmt2GLFmt(This, object->resource.format);
639 object->glDescription.glFormatInternal = D3DFmt2GLIntFmt(This, object->resource.format);
640 object->glDescription.glType = D3DFmt2GLType(This, object->resource.format);
641 object->glDescription.textureName = 0;
642 object->glDescription.level = Level;
643 object->glDescription.target = GL_TEXTURE_2D;
646 object->pow2Width = pow2Width;
647 object->pow2Height = pow2Height;
648 object->nonpow2 = (pow2Width != Width || pow2Height != Height) ? TRUE : FALSE;
649 object->discard = Discard;
650 object->activeLock = FALSE;
651 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
652 object->pow2Size = (pow2Width * object->bytesPerPixel) * pow2Height;
654 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
656 TRACE("Pool %d %d %d %d",Pool, D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM);
658 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
659 * this function is too deap to need to care about things like this.
660 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
661 * ****************************************/
663 case D3DPOOL_SCRATCH:
664 if(Lockable == FALSE)
665 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
666 which are mutually exclusive, setting lockable to true\n");
669 case D3DPOOL_SYSTEMMEM:
670 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
671 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
672 case D3DPOOL_MANAGED:
673 if(Usage == D3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
674 Usage of DYNAMIC which are mutually exclusive, not doing \
675 anything just telling you.\n");
677 case D3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
678 if(!(Usage & D3DUSAGE_DYNAMIC) && !(Usage & D3DUSAGE_RENDERTARGET)
679 && !(Usage && D3DUSAGE_DEPTHSTENCIL ) && Lockable == TRUE)
680 FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
683 FIXME("(%p) Unknown pool %d\n", This, Pool);
687 if (Usage & D3DUSAGE_RENDERTARGET && Pool != D3DPOOL_DEFAULT) {
688 FIXME("Trying to create a render target that isn't in the default pool\n");
692 object->locked = FALSE;
693 object->lockable = (WINED3DFMT_D16_LOCKABLE == Format) ? TRUE : Lockable;
695 /* mark the texture as dirty so that it get's loaded first time around*/
696 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
697 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
698 This, Width, Height, Format, debug_d3dformat(Format),
699 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
704 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
705 DWORD Usage, WINED3DFORMAT Format, D3DPOOL Pool,
706 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
707 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
709 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
710 IWineD3DTextureImpl *object;
715 unsigned int pow2Width = Width;
716 unsigned int pow2Height = Height;
719 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) .... \n", This, Width, Height, Levels, Usage);
721 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, D3DRTYPE_TEXTURE, 0);
722 D3DINITILIZEBASETEXTURE(object->baseTexture);
723 object->width = Width;
724 object->height = Height;
726 /** Non-power2 support **/
727 /* Find the nearest pow2 match */
728 pow2Width = pow2Height = 1;
729 while (pow2Width < Width) pow2Width <<= 1;
730 while (pow2Height < Height) pow2Height <<= 1;
732 /** FIXME: add support for real non-power-two if it's provided by the video card **/
733 /* Precalculated scaling for 'faked' non power of two texture coords */
734 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
735 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
736 TRACE(" xf(%f) yf(%f) \n", object->pow2scalingFactorX, object->pow2scalingFactorY);
738 /* Calculate levels for mip mapping */
740 TRACE("calculating levels %d\n", object->baseTexture.levels);
741 object->baseTexture.levels++;
744 while (tmpW > 1 && tmpH > 1) {
745 tmpW = max(1, tmpW >> 1);
746 tmpH = max(1, tmpH >> 1);
747 object->baseTexture.levels++;
749 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
752 /* Generate all the surfaces */
755 for (i = 0; i < object->baseTexture.levels; i++)
757 /* use the callback to create the texture surface */
758 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
761 FIXME("Failed to create surface %p \n",object);
763 for (j = 0 ; j < i ; j++) {
764 IWineD3DSurface_Release(object->surfaces[j]);
766 /* heap free object */
767 HeapFree(GetProcessHeap(), 0, object);
773 IWineD3DSurface_SetContainer(object->surfaces[i], (IUnknown *)object);
774 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
775 /* calculate the next mipmap level */
776 tmpW = max(1, tmpW >> 1);
777 tmpH = max(1, tmpH >> 1);
780 TRACE("(%p) : Created texture %p\n", This, object);
784 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
785 UINT Width, UINT Height, UINT Depth,
786 UINT Levels, DWORD Usage,
787 WINED3DFORMAT Format, D3DPOOL Pool,
788 IWineD3DVolumeTexture **ppVolumeTexture,
789 HANDLE *pSharedHandle, IUnknown *parent,
790 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
792 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
793 IWineD3DVolumeTextureImpl *object;
799 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, D3DRTYPE_VOLUMETEXTURE, 0);
800 D3DINITILIZEBASETEXTURE(object->baseTexture);
802 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
803 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
805 object->width = Width;
806 object->height = Height;
807 object->depth = Depth;
809 /* Calculate levels for mip mapping */
811 object->baseTexture.levels++;
815 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
816 tmpW = max(1, tmpW >> 1);
817 tmpH = max(1, tmpH >> 1);
818 tmpD = max(1, tmpD >> 1);
819 object->baseTexture.levels++;
821 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
824 /* Generate all the surfaces */
829 for (i = 0; i < object->baseTexture.levels; i++)
831 /* Create the volume */
832 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
833 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
835 /* Set it's container to this object */
836 IWineD3DVolume_SetContainer(object->volumes[i], (IUnknown *)object);
838 /* calcualte the next mipmap level */
839 tmpW = max(1, tmpW >> 1);
840 tmpH = max(1, tmpH >> 1);
841 tmpD = max(1, tmpD >> 1);
844 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
845 TRACE("(%p) : Created volume texture %p\n", This, object);
849 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
850 UINT Width, UINT Height, UINT Depth,
852 WINED3DFORMAT Format, D3DPOOL Pool,
853 IWineD3DVolume** ppVolume,
854 HANDLE* pSharedHandle, IUnknown *parent) {
856 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
857 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
859 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, D3DRTYPE_VOLUME, ((Width * D3DFmtGetBpp(This, Format)) * Height * Depth))
861 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
862 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
864 object->currentDesc.Width = Width;
865 object->currentDesc.Height = Height;
866 object->currentDesc.Depth = Depth;
867 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
869 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
870 object->lockable = TRUE;
871 object->locked = FALSE;
872 memset(&object->lockedBox, 0, sizeof(D3DBOX));
873 object->dirty = TRUE;
875 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
878 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
879 UINT Levels, DWORD Usage,
880 WINED3DFORMAT Format, D3DPOOL Pool,
881 IWineD3DCubeTexture **ppCubeTexture,
882 HANDLE *pSharedHandle, IUnknown *parent,
883 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
885 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
886 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
890 unsigned int pow2EdgeLength = EdgeLength;
892 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, D3DRTYPE_CUBETEXTURE, 0);
893 D3DINITILIZEBASETEXTURE(object->baseTexture);
895 TRACE("(%p) Create Cube Texture \n", This);
897 /** Non-power2 support **/
899 /* Find the nearest pow2 match */
901 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
903 object->edgeLength = EdgeLength;
904 /* TODO: support for native non-power 2 */
905 /* Precalculated scaling for 'faked' non power of two texture coords */
906 object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
908 /* Calculate levels for mip mapping */
910 object->baseTexture.levels++;
913 tmpW = max(1, tmpW >> 1);
914 object->baseTexture.levels++;
916 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
919 /* Generate all the surfaces */
921 for (i = 0; i < object->baseTexture.levels; i++) {
923 /* Create the 6 faces */
924 for (j = 0; j < 6; j++) {
926 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
927 i /* Level */, &object->surfaces[j][i],pSharedHandle);
933 for (l = 0; l < j; l++) {
934 IWineD3DSurface_Release(object->surfaces[j][i]);
936 for (k = 0; k < i; k++) {
937 for (l = 0; l < 6; l++) {
938 IWineD3DSurface_Release(object->surfaces[l][j]);
942 FIXME("(%p) Failed to create surface\n",object);
943 HeapFree(GetProcessHeap(),0,object);
944 *ppCubeTexture = NULL;
947 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IUnknown *)object);
948 TRACE("Created surface level %d @ %p, \n", i, object->surfaces[j][i]);
950 tmpW = max(1, tmpW >> 1);
953 TRACE("(%p) : Created Cube Texture %p\n", This, object);
954 *ppCubeTexture = (IWineD3DCubeTexture *) object;
958 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
959 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
960 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
962 if (NULL == ppQuery) {
963 /* Just a check to see if we support this type of query */
964 HRESULT hr = D3DERR_NOTAVAILABLE;
965 /* Lie and say everything is good (we can return ok fake data from a stub) */
967 case WINED3DQUERYTYPE_VCACHE:
968 case WINED3DQUERYTYPE_RESOURCEMANAGER:
969 case WINED3DQUERYTYPE_VERTEXSTATS:
970 case WINED3DQUERYTYPE_EVENT:
971 case WINED3DQUERYTYPE_OCCLUSION:
972 case WINED3DQUERYTYPE_TIMESTAMP:
973 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
974 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
975 case WINED3DQUERYTYPE_PIPELINETIMINGS:
976 case WINED3DQUERYTYPE_INTERFACETIMINGS:
977 case WINED3DQUERYTYPE_VERTEXTIMINGS:
978 case WINED3DQUERYTYPE_PIXELTIMINGS:
979 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
980 case WINED3DQUERYTYPE_CACHEUTILIZATION:
984 FIXME("(%p) Unhandled query type %d\n",This , Type);
986 FIXME("(%p) : Stub request for query type %d returned %ld\n", This, Type, hr);
990 D3DCREATEOBJECTINSTANCE(object, Query)
992 object->extendedData = 0;
993 TRACE("(%p) : Created Query %p\n", This, object);
997 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
998 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1000 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1001 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1002 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1005 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1007 XVisualInfo template;
1008 GLXContext oldContext;
1009 Drawable oldDrawable;
1010 HRESULT hr = D3D_OK;
1012 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1014 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1015 * does a device hold a reference to a swap chain giving them a lifetime of the device
1016 * or does the swap chain notify the device of it'd destruction.
1017 *******************************/
1019 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1021 /* Initialize other useful values */
1022 object->presentParms.BackBufferCount = 1; /* TODO:? support for gl_aux buffers */
1024 /*********************
1025 * Lookup the window Handle and the relating X window handle
1026 ********************/
1028 /* Setup hwnd we are using, plus which display this equates to */
1029 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1030 if (!object->win_handle) {
1031 object->win_handle = This->createParms.hFocusWindow;
1034 object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window" );
1035 hDc = GetDC(object->win_handle);
1036 object->display = get_display(hDc);
1037 ReleaseDC(object->win_handle, hDc);
1038 TRACE("Using a display of %p %p \n", object->display, hDc);
1040 if (NULL == object->display || NULL == hDc) {
1041 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1042 return D3DERR_NOTAVAILABLE;
1045 if (object->win == 0) {
1046 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1047 return D3DERR_NOTAVAILABLE;
1050 * Create an opengl context for the display visual
1051 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1052 * use different properties after that point in time. FIXME: How to handle when requested format
1053 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1054 * it chooses is identical to the one already being used!
1055 **********************************/
1057 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1060 /* Create a new context for this swapchain */
1061 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1062 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1063 (or the best possible if none is requested) */
1064 TRACE("Found x visual ID : %ld\n", template.visualid);
1066 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1067 if (NULL == object->visInfo) {
1068 ERR("cannot really get XVisual\n");
1070 return D3DERR_NOTAVAILABLE;
1073 /* Write out some debug info about the visual/s */
1074 TRACE("Using x visual ID : %ld\n", template.visualid);
1075 TRACE(" visual info: %p\n", object->visInfo);
1076 TRACE(" num items : %d\n", num);
1077 for (n = 0;n < num; n++) {
1078 TRACE("=====item=====: %d\n", n + 1);
1079 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1080 TRACE(" screen : %d\n", object->visInfo[n].screen);
1081 TRACE(" depth : %u\n", object->visInfo[n].depth);
1082 TRACE(" class : %d\n", object->visInfo[n].class);
1083 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1084 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1085 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1086 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1087 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1088 /* log some extra glx info */
1089 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1090 TRACE(" gl_aux_buffers : %d\n", value);
1091 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1092 TRACE(" gl_buffer_size : %d\n", value);
1093 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1094 TRACE(" gl_red_size : %d\n", value);
1095 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1096 TRACE(" gl_green_size : %d\n", value);
1097 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1098 TRACE(" gl_blue_size : %d\n", value);
1099 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1100 TRACE(" gl_alpha_size : %d\n", value);
1101 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1102 TRACE(" gl_depth_size : %d\n", value);
1103 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1104 TRACE(" gl_stencil_size : %d\n", value);
1106 /* Now choose a simila visual ID*/
1108 #ifdef USE_CONTEXT_MANAGER
1110 /** TODO: use a context mamager **/
1114 IWineD3DSwapChain *implSwapChain;
1115 if (D3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1116 /* The first time around we create the context that is shared with all other swapchains and render targets */
1117 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1118 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1121 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1122 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1123 /* and create a new context with the implicit swapchains context as the shared context */
1124 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1125 IWineD3DSwapChain_Release(implSwapChain);
1130 XFree(object->visInfo);
1131 object->visInfo = NULL;
1133 if (NULL == object->glCtx) {
1134 ERR("cannot create glxContext\n");
1136 return D3DERR_NOTAVAILABLE;
1140 if (object->glCtx == NULL) {
1141 ERR("Error in context creation !\n");
1142 return D3DERR_INVALIDCALL;
1144 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1145 object->win_handle, object->glCtx, object->win, object->visInfo);
1148 /*********************
1149 * Windowed / Fullscreen
1150 *******************/
1153 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1154 * so we should really check to see if their is a fullscreen swapchain already
1155 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1156 **************************************/
1158 if (!*(pPresentationParameters->Windowed)) {
1164 /* Get info on the current display setup */
1165 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1166 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1169 /* Change the display settings */
1170 memset(&devmode, 0, sizeof(DEVMODEW));
1171 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1172 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1173 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1174 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1175 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1176 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1178 /* Make popup window */
1179 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1180 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1181 *(pPresentationParameters->BackBufferWidth),
1182 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1188 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1189 * then the corresponding dimension of the client area of the hDeviceWindow
1190 * (or the focus window, if hDeviceWindow is NULL) is taken.
1191 **********************/
1193 if (*(pPresentationParameters->Windowed) &&
1194 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1195 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1198 GetClientRect(object->win_handle, &Rect);
1200 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1201 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1202 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1204 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1205 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1206 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1210 /*********************
1211 * finish off parameter initialization
1212 *******************/
1214 /* Put the correct figures in the presentation parameters */
1215 TRACE("Coppying accross presentaion paraneters\n");
1216 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1217 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1218 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1219 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1220 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1221 object->presentParms.MultiSampleQuality = *(pPresentationParameters->MultiSampleQuality);
1222 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1223 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1224 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1225 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1226 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1227 object->presentParms.Flags = *(pPresentationParameters->Flags);
1228 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1229 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1232 /*********************
1233 * Create the back, front and stencil buffers
1234 *******************/
1235 TRACE("calling rendertarget CB\n");
1236 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1237 object->presentParms.BackBufferWidth,
1238 object->presentParms.BackBufferHeight,
1239 object->presentParms.BackBufferFormat,
1240 object->presentParms.MultiSampleType,
1241 object->presentParms.MultiSampleQuality,
1242 TRUE /* Lockable */,
1243 &object->frontBuffer,
1244 NULL /* pShared (always null)*/);
1245 if (object->frontBuffer != NULL)
1246 IWineD3DSurface_SetContainer(object->frontBuffer, (IUnknown *)object);
1247 TRACE("calling rendertarget CB\n");
1248 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1249 object->presentParms.BackBufferWidth,
1250 object->presentParms.BackBufferHeight,
1251 object->presentParms.BackBufferFormat,
1252 object->presentParms.MultiSampleType,
1253 object->presentParms.MultiSampleQuality,
1254 TRUE /* Lockable */,
1255 &object->backBuffer,
1256 NULL /* pShared (always null)*/);
1257 if (object->backBuffer != NULL)
1258 IWineD3DSurface_SetContainer(object->backBuffer, (IUnknown *)object);
1260 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1261 if (pPresentationParameters->EnableAutoDepthStencil) {
1262 TRACE("Creating depth stencil buffer\n");
1263 if (This->depthStencilBuffer == NULL ) {
1264 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1265 object->presentParms.BackBufferWidth,
1266 object->presentParms.BackBufferHeight,
1267 object->presentParms.AutoDepthStencilFormat,
1268 object->presentParms.MultiSampleType,
1269 object->presentParms.MultiSampleQuality,
1270 FALSE /* FIXME: Discard */,
1271 &This->depthStencilBuffer,
1272 NULL /* pShared (always null)*/ );
1273 if (This->depthStencilBuffer != NULL)
1274 IWineD3DSurface_SetContainer(This->depthStencilBuffer, (IUnknown *)iface);
1277 /** TODO: A check on width, height and multisample types
1278 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1279 ****************************/
1280 object->wantsDepthStencilBuffer = TRUE;
1282 object->wantsDepthStencilBuffer = FALSE;
1285 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1288 /*********************
1289 * init the default renderTarget management
1290 *******************/
1291 object->drawable = object->win;
1292 object->render_ctx = object->glCtx;
1295 /*********************
1296 * Setup some defaults and clear down the buffers
1297 *******************/
1299 /** save current context and drawable **/
1300 oldContext = glXGetCurrentContext();
1301 oldDrawable = glXGetCurrentDrawable();
1303 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1304 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1305 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1307 checkGLcall("glXMakeCurrent");
1309 TRACE("Setting up the screen\n");
1310 /* Clear the screen */
1311 glClearColor(0.0, 0.0, 0.0, 0.0);
1312 checkGLcall("glClearColor");
1315 glClearStencil(0xffff);
1317 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1318 checkGLcall("glClear");
1320 glColor3f(1.0, 1.0, 1.0);
1321 checkGLcall("glColor3f");
1323 glEnable(GL_LIGHTING);
1324 checkGLcall("glEnable");
1326 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1327 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1329 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1330 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1332 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1333 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1335 /* switch back to the original context (if there was one)*/
1336 if (This->swapchains != NULL) {
1337 /** TODO: restore the context and drawable **/
1338 glXMakeCurrent(object->display, oldDrawable, oldContext);
1343 { /* Finally add the swapchain to the end of the devices' swapchain list */
1344 SwapChainList **nextSwapchain;
1345 nextSwapchain = &This->swapchains;
1346 while (*nextSwapchain != NULL) {
1347 nextSwapchain = &((*nextSwapchain)->next);
1349 (*nextSwapchain) = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->swapchains));
1350 (*nextSwapchain)->swapchain = (IWineD3DSwapChain *)object;
1352 TRACE("Set swapchain to %p\n", object);
1353 } else { /* something went wrong so clean up */
1354 IUnknown* bufferParent;
1355 if (object->frontBuffer) {
1356 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1357 IUnknown_Release(bufferParent); /* once for the get parent */
1358 if (IUnknown_Release(bufferParent) > 0) {
1359 FIXME("(%p) Something's still holding the front buffer\n",This);
1362 if (object->backBuffer) {
1363 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1364 IUnknown_Release(bufferParent); /* once for the get parent */
1365 if (IUnknown_Release(bufferParent) > 0) {
1366 FIXME("(%p) Something's still holding the back buffer\n",This);
1369 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1370 /* Clean up the context */
1371 /* check that we are the current context first (we shouldn't be though!) */
1372 if (object->glCtx != 0) {
1373 if(glXGetCurrentContext() == object->glCtx) {
1374 glXMakeCurrent(object->display, None, NULL);
1376 glXDestroyContext(object->display, object->glCtx);
1378 HeapFree(GetProcessHeap(), 0, object);
1385 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1386 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1387 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1388 unsigned int numberOfSwapChains = 0;
1389 SwapChainList *swapchain;
1391 swapchain = This->swapchains;
1392 /* itterate through the list to get a count */
1393 while (swapchain != NULL) {
1394 swapchain = swapchain->next;
1395 numberOfSwapChains++;
1398 TRACE("(%p) returning %d\n", This, numberOfSwapChains);
1399 return numberOfSwapChains;
1402 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1403 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1404 SwapChainList *swapchain;
1405 HRESULT hr = D3DERR_INVALIDCALL;
1406 swapchain = This->swapchains;
1407 TRACE("(%p) : swapchain %d \n", This, iSwapChain);
1410 TRACE("(%p) Finding swapchain %d\n", This, iSwapChain);
1411 while (iSwapChain > 0 && swapchain != NULL) {
1412 swapchain = swapchain->next;
1416 if (iSwapChain > 0 || swapchain == NULL) {
1417 FIXME("(%p) Unable to find swapchain %d\n", This, iSwapChain);
1420 /** TODO: move off to a linkesList implementation **/
1421 *pSwapChain = swapchain->swapchain;
1422 IWineD3DSwapChain_AddRef(*pSwapChain);
1426 TRACE("(%p) returning %p\n", This, *pSwapChain);
1430 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
1431 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1433 FIXME("(%p) : Stub\n",This);
1439 * Vertex Declaration
1441 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1442 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1443 IWineD3DVertexDeclarationImpl *object = NULL;
1444 HRESULT hr = D3D_OK;
1445 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1446 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1449 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1454 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1455 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DVertexShader** ppVertexShader, IUnknown *parent) {
1456 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1457 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1458 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1460 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1461 IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1466 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DPixelShader** ppPixelShader, IUnknown *parent) {
1467 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1468 FIXME("(%p) : Stub\n", This);
1472 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice* iface, IWineD3D** ppD3D) {
1473 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1474 *ppD3D= This->wineD3D;
1475 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1476 IWineD3D_AddRef(*ppD3D);
1480 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1481 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1482 * Into the video ram as possible and seeing how many fit
1483 * you can also get the correct initial value from via X and ATI's driver
1484 *******************/
1485 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1486 static BOOL showfixmes = TRUE;
1488 FIXME("(%p) : stub, emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1489 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1492 TRACE("(%p) : emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1493 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1494 /* videomemory is simulated videomemory + AGP memory left */
1495 return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1503 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1504 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1506 /* Update the current state block */
1507 This->updateStateBlock->fvf = fvf;
1508 This->updateStateBlock->changed.fvf = TRUE;
1509 This->updateStateBlock->set.fvf = TRUE;
1511 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1512 /* clear down the vertex declaration
1513 NOTE: Axis and Allies doesn't work properly otherwise
1514 (may be a stateblock problem though!)
1516 /* No difference if recording or not */
1517 return IWineD3DDevice_SetVertexDeclaration(iface, NULL);
1522 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1523 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1524 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1525 *pfvf = This->stateBlock->fvf;
1530 * Get / Set Stream Source
1532 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1533 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1534 IWineD3DVertexBuffer *oldSrc;
1536 oldSrc = This->stateBlock->streamSource[StreamNumber];
1537 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1539 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
1540 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
1541 This->updateStateBlock->streamStride[StreamNumber] = Stride;
1542 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
1543 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
1545 /* Handle recording of state blocks */
1546 if (This->isRecordingState) {
1547 TRACE("Recording... not performing anything\n");
1551 /* Not recording... */
1552 if (pStreamData != NULL) {
1553 IUnknown *newVertexBufferParent;
1554 /* GetParent will add a ref, so leave it hanging until the vertex buffer is cleared */
1555 IWineD3DVertexBuffer_GetParent(pStreamData, &newVertexBufferParent);
1557 if (oldSrc != NULL) {
1558 IUnknown *oldVertexBufferParent;
1559 IWineD3DVertexBuffer_GetParent(oldSrc, &oldVertexBufferParent);
1560 IUnknown_Release(oldVertexBufferParent);
1561 IUnknown_Release(oldVertexBufferParent);
1567 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
1568 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1570 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
1571 *pStream = This->stateBlock->streamSource[StreamNumber];
1572 *pStride = This->stateBlock->streamStride[StreamNumber];
1573 *pOffset = This->stateBlock->streamOffset[StreamNumber];
1574 if (*pStream != NULL) IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
1578 /*Should be quite easy, just an extension of vertexdata
1580 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1582 The divider is a bit odd though
1584 VertexOffset = StartVertex / Divider * StreamStride +
1585 VertexIndex / Divider * StreamStride + StreamOffset
1588 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
1589 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1591 FIXME("(%p) : stub\n", This);
1595 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
1596 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1598 FIXME("(%p) : stub\n", This);
1603 * Get / Set & Multiply Transform
1605 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1606 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1608 /* Most of this routine, comments included copied from ddraw tree initially: */
1609 TRACE("(%p) : Transform State=%d\n", This, d3dts);
1611 /* Handle recording of state blocks */
1612 if (This->isRecordingState) {
1613 TRACE("Recording... not performing anything\n");
1614 This->updateStateBlock->changed.transform[d3dts] = TRUE;
1615 This->updateStateBlock->set.transform[d3dts] = TRUE;
1616 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1621 * If the new matrix is the same as the current one,
1622 * we cut off any further processing. this seems to be a reasonable
1623 * optimization because as was noticed, some apps (warcraft3 for example)
1624 * tend towards setting the same matrix repeatedly for some reason.
1626 * From here on we assume that the new matrix is different, wherever it matters.
1628 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1629 TRACE("The app is setting the same matrix over again\n");
1632 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1636 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1637 where ViewMat = Camera space, WorldMat = world space.
1639 In OpenGL, camera and world space is combined into GL_MODELVIEW
1640 matrix. The Projection matrix stay projection matrix.
1643 /* Capture the times we can just ignore the change for now */
1644 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1645 This->modelview_valid = FALSE;
1648 } else if (d3dts == D3DTS_PROJECTION) {
1649 This->proj_valid = FALSE;
1652 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1653 /* Indexed Vertex Blending Matrices 256 -> 511 */
1654 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1655 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1659 /* Now we really are going to have to change a matrix */
1662 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1663 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
1664 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1667 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1668 * NOTE: We have to reset the positions even if the light/plane is not currently
1669 * enabled, since the call to enable it will not reset the position.
1670 * NOTE2: Apparently texture transforms do NOT need reapplying
1673 PLIGHTINFOEL *lightChain = NULL;
1674 This->modelview_valid = FALSE;
1675 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
1677 glMatrixMode(GL_MODELVIEW);
1678 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1680 glLoadMatrixf((float *)lpmatrix);
1681 checkGLcall("glLoadMatrixf(...)");
1684 lightChain = This->stateBlock->lights;
1685 while (lightChain && lightChain->glIndex != -1) {
1686 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1687 checkGLcall("glLightfv posn");
1688 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1689 checkGLcall("glLightfv dirn");
1690 lightChain = lightChain->next;
1693 /* Reset Clipping Planes if clipping is enabled */
1694 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1695 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1696 checkGLcall("glClipPlane");
1700 } else { /* What was requested!?? */
1701 WARN("invalid matrix specified: %i\n", d3dts);
1704 /* Release lock, all done */
1709 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1710 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1711 TRACE("(%p) : for Transform State %d\n", This, State);
1712 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1716 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1717 D3DMATRIX *mat = NULL;
1720 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1721 * below means it will be recorded in a state block change, but it
1722 * works regardless where it is recorded.
1723 * If this is found to be wrong, change to StateBlock.
1725 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1726 TRACE("(%p) : For state %u\n", This, State);
1728 if (State < HIGHEST_TRANSFORMSTATE)
1730 mat = &This->updateStateBlock->transforms[State];
1732 FIXME("Unhandled transform state!!\n");
1735 /* Copied from ddraw code: */
1736 temp.u.s._11 = (mat->u.s._11 * pMatrix->u.s._11) + (mat->u.s._21 * pMatrix->u.s._12) +
1737 (mat->u.s._31 * pMatrix->u.s._13) + (mat->u.s._41 * pMatrix->u.s._14);
1738 temp.u.s._21 = (mat->u.s._11 * pMatrix->u.s._21) + (mat->u.s._21 * pMatrix->u.s._22) +
1739 (mat->u.s._31 * pMatrix->u.s._23) + (mat->u.s._41 * pMatrix->u.s._24);
1740 temp.u.s._31 = (mat->u.s._11 * pMatrix->u.s._31) + (mat->u.s._21 * pMatrix->u.s._32) +
1741 (mat->u.s._31 * pMatrix->u.s._33) + (mat->u.s._41 * pMatrix->u.s._34);
1742 temp.u.s._41 = (mat->u.s._11 * pMatrix->u.s._41) + (mat->u.s._21 * pMatrix->u.s._42) +
1743 (mat->u.s._31 * pMatrix->u.s._43) + (mat->u.s._41 * pMatrix->u.s._44);
1745 temp.u.s._12 = (mat->u.s._12 * pMatrix->u.s._11) + (mat->u.s._22 * pMatrix->u.s._12) +
1746 (mat->u.s._32 * pMatrix->u.s._13) + (mat->u.s._42 * pMatrix->u.s._14);
1747 temp.u.s._22 = (mat->u.s._12 * pMatrix->u.s._21) + (mat->u.s._22 * pMatrix->u.s._22) +
1748 (mat->u.s._32 * pMatrix->u.s._23) + (mat->u.s._42 * pMatrix->u.s._24);
1749 temp.u.s._32 = (mat->u.s._12 * pMatrix->u.s._31) + (mat->u.s._22 * pMatrix->u.s._32) +
1750 (mat->u.s._32 * pMatrix->u.s._33) + (mat->u.s._42 * pMatrix->u.s._34);
1751 temp.u.s._42 = (mat->u.s._12 * pMatrix->u.s._41) + (mat->u.s._22 * pMatrix->u.s._42) +
1752 (mat->u.s._32 * pMatrix->u.s._43) + (mat->u.s._42 * pMatrix->u.s._44);
1754 temp.u.s._13 = (mat->u.s._13 * pMatrix->u.s._11) + (mat->u.s._23 * pMatrix->u.s._12) +
1755 (mat->u.s._33 * pMatrix->u.s._13) + (mat->u.s._43 * pMatrix->u.s._14);
1756 temp.u.s._23 = (mat->u.s._13 * pMatrix->u.s._21) + (mat->u.s._23 * pMatrix->u.s._22) +
1757 (mat->u.s._33 * pMatrix->u.s._23) + (mat->u.s._43 * pMatrix->u.s._24);
1758 temp.u.s._33 = (mat->u.s._13 * pMatrix->u.s._31) + (mat->u.s._23 * pMatrix->u.s._32) +
1759 (mat->u.s._33 * pMatrix->u.s._33) + (mat->u.s._43 * pMatrix->u.s._34);
1760 temp.u.s._43 = (mat->u.s._13 * pMatrix->u.s._41) + (mat->u.s._23 * pMatrix->u.s._42) +
1761 (mat->u.s._33 * pMatrix->u.s._43) + (mat->u.s._43 * pMatrix->u.s._44);
1763 temp.u.s._14 = (mat->u.s._14 * pMatrix->u.s._11) + (mat->u.s._24 * pMatrix->u.s._12) +
1764 (mat->u.s._34 * pMatrix->u.s._13) + (mat->u.s._44 * pMatrix->u.s._14);
1765 temp.u.s._24 = (mat->u.s._14 * pMatrix->u.s._21) + (mat->u.s._24 * pMatrix->u.s._22) +
1766 (mat->u.s._34 * pMatrix->u.s._23) + (mat->u.s._44 * pMatrix->u.s._24);
1767 temp.u.s._34 = (mat->u.s._14 * pMatrix->u.s._31) + (mat->u.s._24 * pMatrix->u.s._32) +
1768 (mat->u.s._34 * pMatrix->u.s._33) + (mat->u.s._44 * pMatrix->u.s._34);
1769 temp.u.s._44 = (mat->u.s._14 * pMatrix->u.s._41) + (mat->u.s._24 * pMatrix->u.s._42) +
1770 (mat->u.s._34 * pMatrix->u.s._43) + (mat->u.s._44 * pMatrix->u.s._44);
1772 /* Apply change via set transform - will reapply to eg. lights this way */
1773 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
1778 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
1780 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1781 you can reference any indexes you want as long as that number max are enabled at any
1782 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1783 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1784 but when recording, just build a chain pretty much of commands to be replayed. */
1786 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
1788 PLIGHTINFOEL *object, *temp;
1790 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1791 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1793 /* If recording state block, just add to end of lights chain */
1794 if (This->isRecordingState) {
1795 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1796 if (NULL == object) {
1797 return D3DERR_OUTOFVIDEOMEMORY;
1799 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1800 object->OriginalIndex = Index;
1801 object->glIndex = -1;
1802 object->changed = TRUE;
1804 /* Add to the END of the chain of lights changes to be replayed */
1805 if (This->updateStateBlock->lights == NULL) {
1806 This->updateStateBlock->lights = object;
1808 temp = This->updateStateBlock->lights;
1809 while (temp->next != NULL) temp=temp->next;
1810 temp->next = object;
1812 TRACE("Recording... not performing anything more\n");
1816 /* Ok, not recording any longer so do real work */
1817 object = This->stateBlock->lights;
1818 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1820 /* If we didn't find it in the list of lights, time to add it */
1821 if (object == NULL) {
1822 PLIGHTINFOEL *insertAt,*prevPos;
1824 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1825 if (NULL == object) {
1826 return D3DERR_OUTOFVIDEOMEMORY;
1828 object->OriginalIndex = Index;
1829 object->glIndex = -1;
1831 /* Add it to the front of list with the idea that lights will be changed as needed
1832 BUT after any lights currently assigned GL indexes */
1833 insertAt = This->stateBlock->lights;
1835 while (insertAt != NULL && insertAt->glIndex != -1) {
1837 insertAt = insertAt->next;
1840 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1841 This->stateBlock->lights = object;
1842 } else if (insertAt == NULL) { /* End of list */
1843 prevPos->next = object;
1844 object->prev = prevPos;
1845 } else { /* Middle of chain */
1846 if (prevPos == NULL) {
1847 This->stateBlock->lights = object;
1849 prevPos->next = object;
1851 object->prev = prevPos;
1852 object->next = insertAt;
1853 insertAt->prev = object;
1857 /* Initialze the object */
1858 TRACE("Light %ld setting to type %d, Diffuse(%f,%f,%f,%f), Specular(%f,%f,%f,%f), Ambient(%f,%f,%f,%f)\n", Index, pLight->Type,
1859 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1860 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1861 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1862 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1863 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1864 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1866 /* Save away the information */
1867 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1869 switch (pLight->Type) {
1870 case D3DLIGHT_POINT:
1872 object->lightPosn[0] = pLight->Position.x;
1873 object->lightPosn[1] = pLight->Position.y;
1874 object->lightPosn[2] = pLight->Position.z;
1875 object->lightPosn[3] = 1.0f;
1876 object->cutoff = 180.0f;
1880 case D3DLIGHT_DIRECTIONAL:
1882 object->lightPosn[0] = -pLight->Direction.x;
1883 object->lightPosn[1] = -pLight->Direction.y;
1884 object->lightPosn[2] = -pLight->Direction.z;
1885 object->lightPosn[3] = 0.0;
1886 object->exponent = 0.0f;
1887 object->cutoff = 180.0f;
1892 object->lightPosn[0] = pLight->Position.x;
1893 object->lightPosn[1] = pLight->Position.y;
1894 object->lightPosn[2] = pLight->Position.z;
1895 object->lightPosn[3] = 1.0;
1898 object->lightDirn[0] = pLight->Direction.x;
1899 object->lightDirn[1] = pLight->Direction.y;
1900 object->lightDirn[2] = pLight->Direction.z;
1901 object->lightDirn[3] = 1.0;
1904 * opengl-ish and d3d-ish spot lights use too different models for the
1905 * light "intensity" as a function of the angle towards the main light direction,
1906 * so we only can approximate very roughly.
1907 * however spot lights are rather rarely used in games (if ever used at all).
1908 * furthermore if still used, probably nobody pays attention to such details.
1910 if (pLight->Falloff == 0) {
1913 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1915 if (rho < 0.0001) rho = 0.0001f;
1916 object->exponent = -0.3/log(cos(rho/2));
1917 object->cutoff = pLight->Phi*90/M_PI;
1923 FIXME("Unrecognized light type %d\n", pLight->Type);
1926 /* Update the live definitions if the light is currently assigned a glIndex */
1927 if (object->glIndex != -1) {
1928 setup_light(iface, object->glIndex, object);
1933 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
1934 PLIGHTINFOEL *lightInfo = NULL;
1935 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1936 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1938 /* Locate the light in the live lights */
1939 lightInfo = This->stateBlock->lights;
1940 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1942 if (lightInfo == NULL) {
1943 TRACE("Light information requested but light not defined\n");
1944 return D3DERR_INVALIDCALL;
1947 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
1952 * Get / Set Light Enable
1953 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
1955 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
1956 PLIGHTINFOEL *lightInfo = NULL;
1957 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1958 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1960 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1961 if (This->isRecordingState) {
1962 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1963 if (NULL == lightInfo) {
1964 return D3DERR_OUTOFVIDEOMEMORY;
1966 lightInfo->OriginalIndex = Index;
1967 lightInfo->glIndex = -1;
1968 lightInfo->enabledChanged = TRUE;
1970 /* Add to the END of the chain of lights changes to be replayed */
1971 if (This->updateStateBlock->lights == NULL) {
1972 This->updateStateBlock->lights = lightInfo;
1974 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
1975 while (temp->next != NULL) temp=temp->next;
1976 temp->next = lightInfo;
1978 TRACE("Recording... not performing anything more\n");
1982 /* Not recording... So, locate the light in the live lights */
1983 lightInfo = This->stateBlock->lights;
1984 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1986 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1987 if (lightInfo == NULL) {
1988 D3DLIGHT9 lightParms;
1989 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1990 wait until someone confirms it seems to work! */
1991 TRACE("Light enabled requested but light not defined, so defining one!\n");
1992 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1993 lightParms.Diffuse.r = 1.0;
1994 lightParms.Diffuse.g = 1.0;
1995 lightParms.Diffuse.b = 1.0;
1996 lightParms.Diffuse.a = 0.0;
1997 lightParms.Specular.r = 0.0;
1998 lightParms.Specular.g = 0.0;
1999 lightParms.Specular.b = 0.0;
2000 lightParms.Specular.a = 0.0;
2001 lightParms.Ambient.r = 0.0;
2002 lightParms.Ambient.g = 0.0;
2003 lightParms.Ambient.b = 0.0;
2004 lightParms.Ambient.a = 0.0;
2005 lightParms.Position.x = 0.0;
2006 lightParms.Position.y = 0.0;
2007 lightParms.Position.z = 0.0;
2008 lightParms.Direction.x = 0.0;
2009 lightParms.Direction.y = 0.0;
2010 lightParms.Direction.z = 1.0;
2011 lightParms.Range = 0.0;
2012 lightParms.Falloff = 0.0;
2013 lightParms.Attenuation0 = 0.0;
2014 lightParms.Attenuation1 = 0.0;
2015 lightParms.Attenuation2 = 0.0;
2016 lightParms.Theta = 0.0;
2017 lightParms.Phi = 0.0;
2018 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
2020 /* Search for it again! Should be fairly quick as near head of list */
2021 lightInfo = This->stateBlock->lights;
2022 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2023 if (lightInfo == NULL) {
2024 FIXME("Adding default lights has failed dismally\n");
2025 return D3DERR_INVALIDCALL;
2029 /* OK, we now have a light... */
2030 if (Enable == FALSE) {
2032 /* If we are disabling it, check it was enabled, and
2033 still only do something if it has assigned a glIndex (which it should have!) */
2034 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2035 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2037 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2038 checkGLcall("glDisable GL_LIGHT0+Index");
2041 TRACE("Nothing to do as light was not enabled\n");
2043 lightInfo->lightEnabled = FALSE;
2046 /* We are enabling it. If it is enabled, it's really simple */
2047 if (lightInfo->lightEnabled) {
2049 TRACE("Nothing to do as light was enabled\n");
2051 /* If it already has a glIndex, it's still simple */
2052 } else if (lightInfo->glIndex != -1) {
2053 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2054 lightInfo->lightEnabled = TRUE;
2056 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2057 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2060 /* Otherwise got to find space - lights are ordered gl indexes first */
2062 PLIGHTINFOEL *bsf = NULL;
2063 PLIGHTINFOEL *pos = This->stateBlock->lights;
2064 PLIGHTINFOEL *prev = NULL;
2068 /* Try to minimize changes as much as possible */
2069 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2071 /* Try to remember which index can be replaced if necessary */
2072 if (bsf==NULL && pos->lightEnabled == FALSE) {
2073 /* Found a light we can replace, save as best replacement */
2077 /* Step to next space */
2083 /* If we have too many active lights, fail the call */
2084 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2085 FIXME("Program requests too many concurrent lights\n");
2086 return D3DERR_INVALIDCALL;
2088 /* If we have allocated all lights, but not all are enabled,
2089 reuse one which is not enabled */
2090 } else if (Index == This->maxConcurrentLights) {
2091 /* use bsf - Simply swap the new light and the BSF one */
2092 PLIGHTINFOEL *bsfNext = bsf->next;
2093 PLIGHTINFOEL *bsfPrev = bsf->prev;
2096 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2097 if (bsf->prev != NULL) {
2098 bsf->prev->next = lightInfo;
2100 This->stateBlock->lights = lightInfo;
2103 /* If not side by side, lots of chains to update */
2104 if (bsf->next != lightInfo) {
2105 lightInfo->prev->next = bsf;
2106 bsf->next->prev = lightInfo;
2107 bsf->next = lightInfo->next;
2108 bsf->prev = lightInfo->prev;
2109 lightInfo->next = bsfNext;
2110 lightInfo->prev = bsfPrev;
2114 bsf->prev = lightInfo;
2115 bsf->next = lightInfo->next;
2116 lightInfo->next = bsf;
2117 lightInfo->prev = bsfPrev;
2122 glIndex = bsf->glIndex;
2124 lightInfo->glIndex = glIndex;
2125 lightInfo->lightEnabled = TRUE;
2127 /* Finally set up the light in gl itself */
2128 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2130 setup_light(iface, glIndex, lightInfo);
2131 glEnable(GL_LIGHT0 + glIndex);
2132 checkGLcall("glEnable GL_LIGHT0 new setup");
2135 /* If we reached the end of the allocated lights, with space in the
2136 gl lights, setup a new light */
2137 } else if (pos->glIndex == -1) {
2139 /* We reached the end of the allocated gl lights, so already
2140 know the index of the next one! */
2142 lightInfo->glIndex = glIndex;
2143 lightInfo->lightEnabled = TRUE;
2145 /* In an ideal world, it's already in the right place */
2146 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2147 /* No need to move it */
2149 /* Remove this light from the list */
2150 lightInfo->prev->next = lightInfo->next;
2151 if (lightInfo->next != NULL) {
2152 lightInfo->next->prev = lightInfo->prev;
2155 /* Add in at appropriate place (inbetween prev and pos) */
2156 lightInfo->prev = prev;
2157 lightInfo->next = pos;
2159 This->stateBlock->lights = lightInfo;
2161 prev->next = lightInfo;
2164 pos->prev = lightInfo;
2168 /* Finally set up the light in gl itself */
2169 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2171 setup_light(iface, glIndex, lightInfo);
2172 glEnable(GL_LIGHT0 + glIndex);
2173 checkGLcall("glEnable GL_LIGHT0 new setup");
2182 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2184 PLIGHTINFOEL *lightInfo = NULL;
2185 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2186 TRACE("(%p) : for idx(%ld)\n", This, Index);
2188 /* Locate the light in the live lights */
2189 lightInfo = This->stateBlock->lights;
2190 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2192 if (lightInfo == NULL) {
2193 TRACE("Light enabled state requested but light not defined\n");
2194 return D3DERR_INVALIDCALL;
2196 *pEnable = lightInfo->lightEnabled;
2201 * Get / Set Clip Planes
2203 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2204 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2205 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2207 /* Validate Index */
2208 if (Index >= GL_LIMITS(clipplanes)) {
2209 TRACE("Application has requested clipplane this device doesn't support\n");
2210 return D3DERR_INVALIDCALL;
2213 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2214 This->updateStateBlock->set.clipplane[Index] = TRUE;
2215 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2216 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2217 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2218 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2220 /* Handle recording of state blocks */
2221 if (This->isRecordingState) {
2222 TRACE("Recording... not performing anything\n");
2230 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2231 glMatrixMode(GL_MODELVIEW);
2233 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2235 TRACE("Clipplane [%f,%f,%f,%f]\n",
2236 This->updateStateBlock->clipplane[Index][0],
2237 This->updateStateBlock->clipplane[Index][1],
2238 This->updateStateBlock->clipplane[Index][2],
2239 This->updateStateBlock->clipplane[Index][3]);
2240 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2241 checkGLcall("glClipPlane");
2249 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2250 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2251 TRACE("(%p) : for idx %ld\n", This, Index);
2253 /* Validate Index */
2254 if (Index >= GL_LIMITS(clipplanes)) {
2255 TRACE("Application has requested clipplane this device doesn't support\n");
2256 return D3DERR_INVALIDCALL;
2259 pPlane[0] = This->stateBlock->clipplane[Index][0];
2260 pPlane[1] = This->stateBlock->clipplane[Index][1];
2261 pPlane[2] = This->stateBlock->clipplane[Index][2];
2262 pPlane[3] = This->stateBlock->clipplane[Index][3];
2267 * Get / Set Clip Plane Status
2268 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2270 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2271 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2272 FIXME("(%p) : stub\n", This);
2273 if (NULL == pClipStatus) {
2274 return D3DERR_INVALIDCALL;
2276 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2277 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2281 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2282 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2283 FIXME("(%p) : stub\n", This);
2284 if (NULL == pClipStatus) {
2285 return D3DERR_INVALIDCALL;
2287 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2288 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2293 * Get / Set Material
2294 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2296 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2297 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2299 This->updateStateBlock->changed.material = TRUE;
2300 This->updateStateBlock->set.material = TRUE;
2301 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2303 /* Handle recording of state blocks */
2304 if (This->isRecordingState) {
2305 TRACE("Recording... not performing anything\n");
2310 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2311 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2312 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2313 pMaterial->Ambient.b, pMaterial->Ambient.a);
2314 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2315 pMaterial->Specular.b, pMaterial->Specular.a);
2316 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2317 pMaterial->Emissive.b, pMaterial->Emissive.a);
2318 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2320 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2321 checkGLcall("glMaterialfv(GL_AMBIENT)");
2322 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2323 checkGLcall("glMaterialfv(GL_DIFFUSE)");
2325 /* Only change material color if specular is enabled, otherwise it is set to black */
2326 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2327 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2328 checkGLcall("glMaterialfv(GL_SPECULAR");
2330 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2331 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2332 checkGLcall("glMaterialfv(GL_SPECULAR");
2334 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2335 checkGLcall("glMaterialfv(GL_EMISSION)");
2336 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2337 checkGLcall("glMaterialf(GL_SHININESS");
2343 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2344 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2345 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2346 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2347 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2348 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2349 pMaterial->Ambient.b, pMaterial->Ambient.a);
2350 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2351 pMaterial->Specular.b, pMaterial->Specular.a);
2352 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2353 pMaterial->Emissive.b, pMaterial->Emissive.a);
2354 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2362 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2363 UINT BaseVertexIndex) {
2364 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2365 IWineD3DIndexBuffer *oldIdxs;
2367 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2368 oldIdxs = This->updateStateBlock->pIndexData;
2370 This->updateStateBlock->changed.indices = TRUE;
2371 This->updateStateBlock->set.indices = TRUE;
2372 This->updateStateBlock->pIndexData = pIndexData;
2373 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2375 /* Handle recording of state blocks */
2376 if (This->isRecordingState) {
2377 TRACE("Recording... not performing anything\n");
2382 IUnknown *indexBufferParent;
2383 /* Getting the parent causes a addRef... it gets released when the indicies are clear */
2384 IWineD3DIndexBuffer_GetParent(pIndexData, &indexBufferParent);
2387 IUnknown *indexBufferParent;
2388 IWineD3DIndexBuffer_GetParent(oldIdxs, &indexBufferParent);
2389 IUnknown_Release(indexBufferParent);
2390 IUnknown_Release(indexBufferParent);
2395 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2396 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2398 *ppIndexData = This->stateBlock->pIndexData;
2400 /* up ref count on ppindexdata */
2402 IWineD3DIndexBuffer_AddRef(*ppIndexData);
2403 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2404 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
2406 TRACE("(%p) No index data set\n", This);
2408 TRACE("Returning %p %d \n",*ppIndexData, *pBaseVertexIndex);
2414 * Get / Set Viewports
2416 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2417 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2419 TRACE("(%p)\n", This);
2420 This->updateStateBlock->changed.viewport = TRUE;
2421 This->updateStateBlock->set.viewport = TRUE;
2422 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2424 /* Handle recording of state blocks */
2425 if (This->isRecordingState) {
2426 TRACE("Recording... not performing anything\n");
2432 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2433 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2435 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2436 checkGLcall("glDepthRange");
2437 /* Note: GL requires lower left, DirectX supplies upper left */
2438 /* TODO: replace usage of renderTarget with context management */
2439 glViewport(pViewport->X,
2440 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2441 pViewport->Width, pViewport->Height);
2443 checkGLcall("glViewport");
2451 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2452 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2453 TRACE("(%p)\n", This);
2454 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2459 * Get / Set Render States
2460 * TODO: Verify against dx9 definitions
2462 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2464 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2465 DWORD OldValue = This->stateBlock->renderState[State];
2467 /* Simple way of referring to either a DWORD or a 4 byte float */
2473 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2474 This->updateStateBlock->changed.renderState[State] = TRUE;
2475 This->updateStateBlock->set.renderState[State] = TRUE;
2476 This->updateStateBlock->renderState[State] = Value;
2478 /* Handle recording of state blocks */
2479 if (This->isRecordingState) {
2480 TRACE("Recording... not performing anything\n");
2487 case WINED3DRS_FILLMODE :
2488 switch ((D3DFILLMODE) Value) {
2489 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2490 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2491 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2493 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
2495 checkGLcall("glPolygonMode (fillmode)");
2498 case WINED3DRS_LIGHTING :
2500 glEnable(GL_LIGHTING);
2501 checkGLcall("glEnable GL_LIGHTING");
2503 glDisable(GL_LIGHTING);
2504 checkGLcall("glDisable GL_LIGHTING");
2508 case WINED3DRS_ZENABLE :
2509 switch ((D3DZBUFFERTYPE) Value) {
2511 glDisable(GL_DEPTH_TEST);
2512 checkGLcall("glDisable GL_DEPTH_TEST");
2515 glEnable(GL_DEPTH_TEST);
2516 checkGLcall("glEnable GL_DEPTH_TEST");
2519 glEnable(GL_DEPTH_TEST);
2520 checkGLcall("glEnable GL_DEPTH_TEST");
2521 FIXME("W buffer is not well handled\n");
2524 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2528 case WINED3DRS_CULLMODE :
2530 /* If we are culling "back faces with clockwise vertices" then
2531 set front faces to be counter clockwise and enable culling
2533 switch ((D3DCULL) Value) {
2535 glDisable(GL_CULL_FACE);
2536 checkGLcall("glDisable GL_CULL_FACE");
2539 glEnable(GL_CULL_FACE);
2540 checkGLcall("glEnable GL_CULL_FACE");
2541 if (This->renderUpsideDown) {
2543 checkGLcall("glFrontFace GL_CW");
2545 glFrontFace(GL_CCW);
2546 checkGLcall("glFrontFace GL_CCW");
2548 glCullFace(GL_BACK);
2551 glEnable(GL_CULL_FACE);
2552 checkGLcall("glEnable GL_CULL_FACE");
2553 if (This->renderUpsideDown) {
2554 glFrontFace(GL_CCW);
2555 checkGLcall("glFrontFace GL_CCW");
2558 checkGLcall("glFrontFace GL_CW");
2560 glCullFace(GL_BACK);
2563 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2567 case WINED3DRS_SHADEMODE :
2568 switch ((D3DSHADEMODE) Value) {
2570 glShadeModel(GL_FLAT);
2571 checkGLcall("glShadeModel");
2573 case D3DSHADE_GOURAUD:
2574 glShadeModel(GL_SMOOTH);
2575 checkGLcall("glShadeModel");
2577 case D3DSHADE_PHONG:
2578 FIXME("D3DSHADE_PHONG isn't supported?\n");
2581 return D3DERR_INVALIDCALL;
2583 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2587 case WINED3DRS_DITHERENABLE :
2589 glEnable(GL_DITHER);
2590 checkGLcall("glEnable GL_DITHER");
2592 glDisable(GL_DITHER);
2593 checkGLcall("glDisable GL_DITHER");
2597 case WINED3DRS_ZWRITEENABLE :
2600 checkGLcall("glDepthMask");
2603 checkGLcall("glDepthMask");
2607 case WINED3DRS_ZFUNC :
2609 int glParm = GL_LESS;
2611 switch ((D3DCMPFUNC) Value) {
2612 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2613 case D3DCMP_LESS: glParm=GL_LESS; break;
2614 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2615 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2616 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2617 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2618 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2619 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2621 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2623 glDepthFunc(glParm);
2624 checkGLcall("glDepthFunc");
2628 case WINED3DRS_AMBIENT :
2631 D3DCOLORTOGLFLOAT4(Value, col);
2632 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2633 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2634 checkGLcall("glLightModel for MODEL_AMBIENT");
2639 case WINED3DRS_ALPHABLENDENABLE :
2642 checkGLcall("glEnable GL_BLEND");
2644 glDisable(GL_BLEND);
2645 checkGLcall("glDisable GL_BLEND");
2649 case WINED3DRS_SRCBLEND :
2650 case WINED3DRS_DESTBLEND :
2652 int newVal = GL_ZERO;
2654 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2655 case D3DBLEND_ONE : newVal = GL_ONE; break;
2656 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2657 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2658 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2659 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2660 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2661 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2662 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2663 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2664 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2666 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2667 This->srcBlend = newVal;
2668 This->dstBlend = newVal;
2671 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2672 This->srcBlend = newVal;
2673 This->dstBlend = newVal;
2676 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2679 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2680 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2681 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2682 glBlendFunc(This->srcBlend, This->dstBlend);
2684 checkGLcall("glBlendFunc");
2688 case WINED3DRS_ALPHATESTENABLE :
2690 glEnable(GL_ALPHA_TEST);
2691 checkGLcall("glEnable GL_ALPHA_TEST");
2693 glDisable(GL_ALPHA_TEST);
2694 checkGLcall("glDisable GL_ALPHA_TEST");
2698 case WINED3DRS_ALPHAFUNC :
2700 int glParm = GL_LESS;
2701 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2703 switch ((D3DCMPFUNC) Value) {
2704 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2705 case D3DCMP_LESS: glParm = GL_LESS; break;
2706 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2707 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2708 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2709 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2710 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2711 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2713 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2715 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2716 glAlphaFunc(glParm, ref);
2717 This->alphafunc = glParm;
2718 checkGLcall("glAlphaFunc");
2722 case WINED3DRS_ALPHAREF :
2724 int glParm = This->alphafunc;
2727 ref = ((float) Value) / 255.0f;
2728 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2729 glAlphaFunc(glParm, ref);
2730 checkGLcall("glAlphaFunc");
2734 case WINED3DRS_CLIPPLANEENABLE :
2735 case WINED3DRS_CLIPPING :
2737 /* Ensure we only do the changed clip planes */
2738 DWORD enable = 0xFFFFFFFF;
2739 DWORD disable = 0x00000000;
2741 /* If enabling / disabling all */
2742 if (State == WINED3DRS_CLIPPING) {
2744 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2747 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2751 enable = Value & ~OldValue;
2752 disable = ~Value & OldValue;
2755 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2756 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2757 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2758 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2759 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2760 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2762 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2763 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2764 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2765 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2766 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2767 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2769 /** update clipping status */
2771 This->stateBlock->clip_status.ClipUnion = 0;
2772 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
2774 This->stateBlock->clip_status.ClipUnion = 0;
2775 This->stateBlock->clip_status.ClipIntersection = 0;
2780 case WINED3DRS_BLENDOP :
2782 int glParm = GL_FUNC_ADD;
2784 switch ((D3DBLENDOP) Value) {
2785 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2786 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2787 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2788 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2789 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2791 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2793 TRACE("glBlendEquation(%x)\n", glParm);
2794 glBlendEquation(glParm);
2795 checkGLcall("glBlendEquation");
2799 case WINED3DRS_TEXTUREFACTOR :
2803 /* Note the texture color applies to all textures whereas
2804 GL_TEXTURE_ENV_COLOR applies to active only */
2806 D3DCOLORTOGLFLOAT4(Value, col);
2807 /* Set the default alpha blend color */
2808 glBlendColor(col[0], col[1], col[2], col[3]);
2809 checkGLcall("glBlendColor");
2811 /* And now the default texture color as well */
2812 for (i = 0; i < GL_LIMITS(textures); i++) {
2814 /* Note the D3DRS value applies to all textures, but GL has one
2815 per texture, so apply it now ready to be used! */
2816 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2819 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2822 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2823 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2828 case WINED3DRS_SPECULARENABLE :
2830 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2831 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2832 specular color. This is wrong:
2833 Separate specular color means the specular colour is maintained separately, whereas
2834 single color means it is merged in. However in both cases they are being used to
2836 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2837 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2841 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2842 checkGLcall("glMaterialfv");
2843 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2844 glEnable(GL_COLOR_SUM_EXT);
2846 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2848 checkGLcall("glEnable(GL_COLOR_SUM)");
2850 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2852 /* for the case of enabled lighting: */
2853 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2854 checkGLcall("glMaterialfv");
2856 /* for the case of disabled lighting: */
2857 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2858 glDisable(GL_COLOR_SUM_EXT);
2860 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2862 checkGLcall("glDisable(GL_COLOR_SUM)");
2867 case WINED3DRS_STENCILENABLE :
2869 glEnable(GL_STENCIL_TEST);
2870 checkGLcall("glEnable GL_STENCIL_TEST");
2872 glDisable(GL_STENCIL_TEST);
2873 checkGLcall("glDisable GL_STENCIL_TEST");
2877 case WINED3DRS_STENCILFUNC :
2879 int glParm = GL_ALWAYS;
2880 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2881 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2883 switch ((D3DCMPFUNC) Value) {
2884 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2885 case D3DCMP_LESS: glParm=GL_LESS; break;
2886 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2887 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2888 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2889 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2890 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2891 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2893 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2895 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2896 This->stencilfunc = glParm;
2897 glStencilFunc(glParm, ref, mask);
2898 checkGLcall("glStencilFunc");
2902 case WINED3DRS_STENCILREF :
2904 int glParm = This->stencilfunc;
2906 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2909 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2910 glStencilFunc(glParm, ref, mask);
2911 checkGLcall("glStencilFunc");
2915 case WINED3DRS_STENCILMASK :
2917 int glParm = This->stencilfunc;
2918 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2919 GLuint mask = Value;
2921 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2922 glStencilFunc(glParm, ref, mask);
2923 checkGLcall("glStencilFunc");
2927 case WINED3DRS_STENCILFAIL :
2933 fail = StencilOp(Value);
2934 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2935 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2936 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2937 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2939 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2940 glStencilOp(fail, zfail, zpass);
2941 checkGLcall("glStencilOp(fail, zfail, zpass);");
2944 case WINED3DRS_STENCILZFAIL :
2950 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2951 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2952 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2953 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2954 zfail = StencilOp(Value);
2956 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2957 glStencilOp(fail, zfail, zpass);
2958 checkGLcall("glStencilOp(fail, zfail, zpass);");
2961 case WINED3DRS_STENCILPASS :
2967 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2968 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2969 zpass = StencilOp(Value);
2970 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2971 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2973 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2974 glStencilOp(fail, zfail, zpass);
2975 checkGLcall("glStencilOp(fail, zfail, zpass);");
2979 case WINED3DRS_STENCILWRITEMASK :
2981 glStencilMask(Value);
2982 TRACE("glStencilMask(%lu)\n", Value);
2983 checkGLcall("glStencilMask");
2987 case WINED3DRS_FOGENABLE :
2989 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2991 checkGLcall("glEnable GL_FOG");
2994 checkGLcall("glDisable GL_FOG");
2999 case WINED3DRS_RANGEFOGENABLE :
3002 TRACE("Enabled RANGEFOG");
3004 TRACE("Disabled RANGEFOG");
3009 case WINED3DRS_FOGCOLOR :
3012 D3DCOLORTOGLFLOAT4(Value, col);
3013 /* Set the default alpha blend color */
3014 glFogfv(GL_FOG_COLOR, &col[0]);
3015 checkGLcall("glFog GL_FOG_COLOR");
3019 case WINED3DRS_FOGTABLEMODE :
3021 glHint(GL_FOG_HINT, GL_NICEST);
3023 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3024 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3025 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3026 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3028 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3030 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3031 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3036 case WINED3DRS_FOGVERTEXMODE :
3038 glHint(GL_FOG_HINT, GL_FASTEST);
3040 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3041 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3042 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3043 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3045 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3047 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3048 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
3053 case WINED3DRS_FOGSTART :
3056 glFogfv(GL_FOG_START, &tmpvalue.f);
3057 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3058 TRACE("Fog Start == %f\n", tmpvalue.f);
3062 case WINED3DRS_FOGEND :
3065 glFogfv(GL_FOG_END, &tmpvalue.f);
3066 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3067 TRACE("Fog End == %f\n", tmpvalue.f);
3071 case WINED3DRS_FOGDENSITY :
3074 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3075 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3079 case WINED3DRS_VERTEXBLEND :
3081 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3082 TRACE("Vertex Blending state to %ld\n", Value);
3086 case WINED3DRS_TWEENFACTOR :
3089 This->updateStateBlock->tween_factor = tmpvalue.f;
3090 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3094 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
3096 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3100 case WINED3DRS_COLORVERTEX :
3101 case WINED3DRS_DIFFUSEMATERIALSOURCE :
3102 case WINED3DRS_SPECULARMATERIALSOURCE :
3103 case WINED3DRS_AMBIENTMATERIALSOURCE :
3104 case WINED3DRS_EMISSIVEMATERIALSOURCE :
3106 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3108 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3109 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3110 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3111 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3112 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3113 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3115 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3116 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3117 Parm = GL_AMBIENT_AND_DIFFUSE;
3121 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3123 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3125 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3132 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3134 This->tracking_color = NEEDS_TRACKING;
3135 This->tracking_parm = Parm;
3139 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3144 case WINED3DRS_LINEPATTERN :
3150 tmppattern.d = Value;
3152 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3154 if (tmppattern.lp.wRepeatFactor) {
3155 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3156 checkGLcall("glLineStipple(repeat, linepattern)");
3157 glEnable(GL_LINE_STIPPLE);
3158 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3160 glDisable(GL_LINE_STIPPLE);
3161 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3166 case WINED3DRS_ZBIAS : /* D3D8 only */
3170 TRACE("ZBias value %f\n", tmpvalue.f);
3171 glPolygonOffset(0, -tmpvalue.f);
3172 checkGLcall("glPolygonOffset(0, -Value)");
3173 glEnable(GL_POLYGON_OFFSET_FILL);
3174 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3175 glEnable(GL_POLYGON_OFFSET_LINE);
3176 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3177 glEnable(GL_POLYGON_OFFSET_POINT);
3178 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3180 glDisable(GL_POLYGON_OFFSET_FILL);
3181 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3182 glDisable(GL_POLYGON_OFFSET_LINE);
3183 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3184 glDisable(GL_POLYGON_OFFSET_POINT);
3185 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3190 case WINED3DRS_NORMALIZENORMALS :
3192 glEnable(GL_NORMALIZE);
3193 checkGLcall("glEnable(GL_NORMALIZE);");
3195 glDisable(GL_NORMALIZE);
3196 checkGLcall("glDisable(GL_NORMALIZE);");
3200 case WINED3DRS_POINTSIZE :
3202 TRACE("Set point size to %f\n", tmpvalue.f);
3203 glPointSize(tmpvalue.f);
3204 checkGLcall("glPointSize(...);");
3207 case WINED3DRS_POINTSIZE_MIN :
3208 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3210 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3211 checkGLcall("glPointParameterfEXT(...);");
3213 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3217 case WINED3DRS_POINTSIZE_MAX :
3218 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3220 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3221 checkGLcall("glPointParameterfEXT(...);");
3223 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3227 case WINED3DRS_POINTSCALE_A :
3228 case WINED3DRS_POINTSCALE_B :
3229 case WINED3DRS_POINTSCALE_C :
3230 case WINED3DRS_POINTSCALEENABLE :
3232 /* If enabled, supply the parameters, otherwise fall back to defaults */
3233 if (This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3234 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3235 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]);
3236 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]);
3237 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]);
3239 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3240 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3241 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3243 TRACE("WINED3DRS_POINTSCALEENABLE not supported on this opengl\n");
3246 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3247 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3248 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3249 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3251 TRACE("WINED3DRS_POINTSCALEENABLE not supported, but not on either\n");
3257 case WINED3DRS_COLORWRITEENABLE :
3259 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3260 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3261 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3262 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3263 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3264 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3265 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3266 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3267 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3268 checkGLcall("glColorMask(...)");
3272 case WINED3DRS_LOCALVIEWER :
3274 GLint state = (Value) ? 1 : 0;
3275 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3276 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3280 case WINED3DRS_LASTPIXEL :
3283 TRACE("Last Pixel Drawing Enabled\n");
3285 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3290 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3293 TRACE("Software Processing Enabled\n");
3295 TRACE("Software Processing Disabled\n");
3300 /** not supported */
3301 case WINED3DRS_ZVISIBLE :
3304 return D3DERR_INVALIDCALL;
3307 /* Unhandled yet...! */
3308 case WINED3DRS_EDGEANTIALIAS :
3309 case WINED3DRS_WRAP0 :
3310 case WINED3DRS_WRAP1 :
3311 case WINED3DRS_WRAP2 :
3312 case WINED3DRS_WRAP3 :
3313 case WINED3DRS_WRAP4 :
3314 case WINED3DRS_WRAP5 :
3315 case WINED3DRS_WRAP6 :
3316 case WINED3DRS_WRAP7 :
3318 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
3319 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
3320 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
3321 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
3322 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
3324 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
3326 TRACE("(%p)->(%d,%ld) Texture wraping not yet supported\n",This, State, Value);
3328 case WINED3DRS_POINTSPRITEENABLE :
3329 case WINED3DRS_MULTISAMPLEANTIALIAS :
3330 case WINED3DRS_MULTISAMPLEMASK :
3331 case WINED3DRS_PATCHEDGESTYLE :
3332 case WINED3DRS_PATCHSEGMENTS :
3333 case WINED3DRS_DEBUGMONITORTOKEN :
3334 case WINED3DRS_POSITIONORDER :
3335 case WINED3DRS_NORMALORDER :
3336 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3337 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3340 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3348 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3349 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3350 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3351 *pValue = This->stateBlock->renderState[State];
3356 * Get / Set Sampler States
3357 * TODO: Verify against dx9 definitions
3360 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3361 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3363 * SetSampler is designed to allow for more than the standard up to 8 textures
3364 * and Geforce has stopped supporting more than 6 standard textures in openGL.
3365 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3367 * http://developer.nvidia.com/object/General_FAQ.html#t6
3369 * There are two new settings for GForce
3371 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3372 * and the texture one:
3373 * GL_MAX_TEXTURE_COORDS_ARB.
3374 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3376 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
3377 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
3379 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
3380 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE, Sampler, Type);
3381 return D3DERR_INVALIDCALL;
3383 TRACE("Setting sampler %ld %d to %ld \n", Sampler, Type, Value);
3384 This->updateStateBlock->samplerState[Sampler][Type] = Value;
3385 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
3386 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
3388 /* Handle recording of state blocks */
3389 if (This->isRecordingState) {
3390 TRACE("Recording... not performing anything\n");
3397 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3398 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3399 /** TODO: check that sampler is in range **/
3400 *Value = This->updateStateBlock->samplerState[Sampler][Type];
3401 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
3406 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3407 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3410 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3411 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3412 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3418 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3419 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3420 GLint scissorBox[4];
3423 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3424 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
3425 pRect->left = scissorBox[1];
3426 pRect->top = scissorBox[2];
3427 pRect->right = scissorBox[1] + scissorBox[3];
3428 pRect->bottom = scissorBox[2] + scissorBox[4];
3429 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3434 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3435 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3437 TRACE("(%p) : pDecl=%p\n", This, pDecl);
3439 /* TODO: what about recording stateblocks? */
3440 if (NULL != pDecl) {
3441 IWineD3DVertexDeclaration_AddRef(pDecl);
3443 if (NULL != This->updateStateBlock->vertexDecl) {
3444 IWineD3DVertexDeclaration_Release(This->updateStateBlock->vertexDecl);
3446 This->updateStateBlock->vertexDecl = pDecl;
3447 This->updateStateBlock->changed.vertexDecl = TRUE;
3448 This->updateStateBlock->set.vertexDecl = TRUE;
3452 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3453 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3455 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3457 *ppDecl = This->updateStateBlock->vertexDecl;
3458 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3462 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
3463 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3464 IWineD3DVertexShader *oldShader = This->updateStateBlock->vertexShader;
3466 This->updateStateBlock->vertexShader = pShader;
3467 This->updateStateBlock->changed.vertexShader = TRUE;
3468 This->updateStateBlock->set.vertexShader = TRUE;
3470 if (This->isRecordingState) {
3471 TRACE("Recording... not performing anything\n");
3475 if (pShader != NULL) {
3476 IUnknown *newVertexShaderParent;
3477 /* GetParent will add a ref, so leave it hanging until the vertex buffer is cleared */
3478 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3479 IWineD3DVertexShader_GetParent(pShader, &newVertexShaderParent);
3481 TRACE("Clear down the shader\n");
3483 if (oldShader != NULL) {
3484 IUnknown *oldVertexShaderParent;
3485 IWineD3DVertexShader_GetParent(oldShader, &oldVertexShaderParent);
3486 IUnknown_Release(oldVertexShaderParent);
3487 IUnknown_Release(oldVertexShaderParent);
3490 * TODO: merge HAL shaders context switching from prototype
3495 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
3496 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3498 if (NULL == ppShader) {
3499 return D3DERR_INVALIDCALL;
3501 *ppShader = This->stateBlock->vertexShader;
3502 if( NULL != *ppShader)
3503 IWineD3DVertexShader_AddRef(*ppShader);
3505 TRACE("(%p) : returning %p\n", This, *ppShader);
3509 #define GET_SHADER_CONSTANT(_vertexshaderconstant, _count, _sizecount) \
3510 int count = min(_count, MAX_VSHADER_CONSTANTS - (StartRegister + 1)); \
3511 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3512 return D3DERR_INVALIDCALL; \
3513 memcpy(pConstantData, This->updateStateBlock->_vertexshaderconstant + (StartRegister * _sizecount), count * (sizeof(*pConstantData) * _sizecount));
3515 #define SET_SHADER_CONSTANT(_vertexshaderconstant, _count, _sizecount) \
3516 int count = min(_count, MAX_VSHADER_CONSTANTS - (StartRegister + 1)); \
3517 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3518 return D3DERR_INVALIDCALL; \
3519 memcpy(This->updateStateBlock->_vertexshaderconstant + (StartRegister * _sizecount), pConstantData, count * (sizeof(*pConstantData) * _sizecount)); \
3520 This->updateStateBlock->changed.vertexShader = TRUE; \
3521 This->updateStateBlock->set.vertexShader = TRUE;
3523 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
3524 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3525 static BOOL showFixmes = TRUE;
3526 SET_SHADER_CONSTANT(vertexShaderConstantB, BoolCount, 1);
3527 #if 0 /* TODO: a bitmasp to say which constant type we should load */
3528 memset(This->updateStateBlock->vsibfBitmap + StartRegister, WINESHADER_CONSTANTB, BoolCount);
3530 /* clean out the other constants? */
3531 if(showFixmes || TRUE) {
3532 FIXME("(%p) : stub\n", This);
3538 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
3539 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3540 static BOOL showFixmes = TRUE;
3541 #if 0 /* TODO: a bitmasp to say which constant type we should load */
3542 for (i = 0; i < BoolCount; i++ ) {
3543 if (This->updateStateBlock->vsibfBitmap[StartRegister + i] != WINESHADER_CONSTANTB) {
3544 /* the constant for this register isn't a boolean */
3545 return D3DERR_INVALIDCALL;
3549 GET_SHADER_CONSTANT(vertexShaderConstantB, BoolCount, 1);
3550 if(showFixmes || TRUE) {
3551 FIXME("(%p) : stub\n", This);
3557 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
3558 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3559 static BOOL showFixmes = TRUE;
3560 #if 0 /* TODO: a bitmasp to say which constant type we should load */
3561 memset(This->updateStateBlock->vsibfBitmap + StartRegister, WINESHADER_CONSTANTI, Vector4iCount);
3563 SET_SHADER_CONSTANT(vertexShaderConstantI, Vector4iCount, 4);
3564 /* clean out the other constants? */
3565 if(showFixmes || TRUE) {
3566 FIXME("(%p) : stub\n", This);
3572 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
3573 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3574 static BOOL showFixmes = TRUE;
3575 #if 0 /* TODO: a bitmap to say which constant type we should load */
3576 for (i = 0; i < Vector4iCount; i++ ) {
3577 if (This->updateStateBlock->vsibfBitmap[StartRegister + i] != WINESHADER_CONSTANTI) {
3578 /* the constant for this register isn't a boolean */
3579 return D3DERR_INVALIDCALL;
3583 GET_SHADER_CONSTANT(vertexShaderConstantI, Vector4iCount, 4);
3584 if(showFixmes || TRUE) {
3585 FIXME("(%p) : stub\n", This);
3591 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
3592 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3593 static BOOL showFixmes = TRUE;
3594 #if 0 /* TODO: a bitmasp to say which constant type we should load */
3595 memset(This->updateStateBlock->vsibfBitmap + StartRegister, WINESHADER_CONSTANTF, Vector4fCount);
3597 SET_SHADER_CONSTANT(vertexShaderConstantF, Vector4fCount, 4);
3598 /* clean out the other constants? */
3600 TRACE("(%p) : ConstantF isn't intergrated properly with the other constants.\n", This);
3606 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
3607 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3608 static BOOL showFixmes = TRUE;
3609 #if 0 /* TODO: a bitmap to say which constant type we should load */
3610 for (i = 0; i < Vector4fCount; i++ ) {
3611 if (This->updateStateBlock->vsibfBitmap[StartRegister + i] != WINESHADER_CONSTANTF) {
3612 /* the constant for this register isn't a boolean */
3613 return D3DERR_INVALIDCALL;
3617 GET_SHADER_CONSTANT(vertexShaderConstantF, Vector4fCount, 4);
3619 TRACE("(%p) : ConstantF isn't intergrated properly with the other constants.\n", This);
3625 #undef SET_SHADER_CONSTANT
3626 #undef GET_SHADER_CONSTANT
3629 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
3630 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3631 TRACE("(%p) : stub\n", This);
3635 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3636 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3637 TRACE("(%p) : stub\n", This);
3642 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
3643 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3644 TRACE("(%p) : stub\n", This);
3648 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
3649 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3650 TRACE("(%p) : stub\n", This);
3654 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
3655 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3656 TRACE("(%p) : stub\n", This);
3660 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
3661 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3662 TRACE("(%p) : stub\n", This);
3666 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
3667 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3668 TRACE("(%p) : stub\n", This);
3672 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
3673 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3674 TRACE("(%p) : stub\n", This);
3678 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
3679 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3680 FIXME("(%p) : stub\n", This);
3685 * Apply / Get / Set Texture Stage States
3686 * TODO: Verify against dx9 definitions
3689 /* 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 */
3690 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
3691 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3692 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
3693 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3695 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3697 /* Check that the stage is within limits */
3698 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
3699 TRACE("Attempt to access invalid texture rejected\n");
3706 case WINED3DTSS_ALPHAOP :
3707 case WINED3DTSS_COLOROP :
3708 /* nothing to do as moved to drawprim for now */
3710 case WINED3DTSS_ADDRESSW :
3711 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
3712 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
3713 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3716 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
3717 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
3718 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3719 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3722 case WINED3DTSS_TEXCOORDINDEX :
3724 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3726 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
3727 one flag, you can still specify an index value, which the system uses to
3728 determine the texture wrapping mode.
3729 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3730 means use the vertex position (camera-space) as the input texture coordinates
3731 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
3732 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3733 to the TEXCOORDINDEX value */
3736 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3738 switch (Value & 0xFFFF0000) {
3739 case D3DTSS_TCI_PASSTHRU:
3740 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3741 glDisable(GL_TEXTURE_GEN_S);
3742 glDisable(GL_TEXTURE_GEN_T);
3743 glDisable(GL_TEXTURE_GEN_R);
3744 glDisable(GL_TEXTURE_GEN_Q);
3745 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
3748 case D3DTSS_TCI_CAMERASPACEPOSITION:
3749 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3750 as the input texture coordinates for this stage's texture transformation. This
3751 equates roughly to EYE_LINEAR */
3753 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3754 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3755 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3756 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3757 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3759 glMatrixMode(GL_MODELVIEW);
3762 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3763 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3764 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3765 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3768 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3769 glEnable(GL_TEXTURE_GEN_S);
3770 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3771 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3772 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3773 glEnable(GL_TEXTURE_GEN_T);
3774 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3775 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3776 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3777 glEnable(GL_TEXTURE_GEN_R);
3778 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3779 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3780 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3784 case D3DTSS_TCI_CAMERASPACENORMAL:
3786 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3787 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3788 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3789 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3790 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3791 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
3793 glMatrixMode(GL_MODELVIEW);
3796 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3797 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3798 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3799 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3802 glEnable(GL_TEXTURE_GEN_S);
3803 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3804 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3805 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3806 glEnable(GL_TEXTURE_GEN_T);
3807 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3808 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3809 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3810 glEnable(GL_TEXTURE_GEN_R);
3811 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3812 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3813 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3818 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3820 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3821 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3822 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3823 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3824 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3825 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
3827 glMatrixMode(GL_MODELVIEW);
3830 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3831 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3832 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3833 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3836 glEnable(GL_TEXTURE_GEN_S);
3837 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3838 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3839 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3840 glEnable(GL_TEXTURE_GEN_T);
3841 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3842 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3843 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3844 glEnable(GL_TEXTURE_GEN_R);
3845 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3846 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3847 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3852 /* Unhandled types: */
3855 /* ? disable GL_TEXTURE_GEN_n ? */
3856 glDisable(GL_TEXTURE_GEN_S);
3857 glDisable(GL_TEXTURE_GEN_T);
3858 glDisable(GL_TEXTURE_GEN_R);
3859 glDisable(GL_TEXTURE_GEN_Q);
3860 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
3867 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
3868 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);
3871 case WINED3DTSS_BUMPENVMAT00 :
3872 case WINED3DTSS_BUMPENVMAT01 :
3873 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
3875 case WINED3DTSS_BUMPENVMAT10 :
3876 case WINED3DTSS_BUMPENVMAT11 :
3877 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
3880 case WINED3DTSS_BUMPENVLSCALE :
3881 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3884 case WINED3DTSS_BUMPENVLOFFSET :
3885 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3888 case WINED3DTSS_RESULTARG :
3889 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3893 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3894 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3903 * Get / Set Texture Stage States
3904 * TODO: Verify against dx9 definitions
3906 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3907 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3909 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3911 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3913 /* Reject invalid texture units */
3914 if (Stage >= GL_LIMITS(textures)) {
3915 TRACE("Attempt to access invalid texture rejected\n");
3916 return D3DERR_INVALIDCALL;
3919 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
3920 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
3921 This->updateStateBlock->textureState[Stage][Type] = Value;
3926 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
3927 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3928 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
3929 *pValue = This->updateStateBlock->textureState[Stage][Type];
3936 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
3938 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3939 IWineD3DBaseTexture *oldTexture;
3941 oldTexture = This->updateStateBlock->textures[Stage];
3942 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3944 #if 0 /* TODO: check so vertex textures */
3945 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
3946 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
3951 /* Reject invalid texture units */
3952 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
3953 WARN("Attempt to access invalid texture rejected\n");
3954 return D3DERR_INVALIDCALL;
3957 oldTexture = This->updateStateBlock->textures[Stage];
3958 TRACE("GL_LIMITS %d\n",GL_LIMITS(textures));
3959 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
3961 This->updateStateBlock->set.textures[Stage] = TRUE;
3962 This->updateStateBlock->changed.textures[Stage] = TRUE;
3963 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
3964 This->updateStateBlock->textures[Stage] = pTexture;
3966 /* Handle recording of state blocks */
3967 if (This->isRecordingState) {
3968 TRACE("Recording... not performing anything\n");
3972 /** NOTE: MSDN says that setTexture increases the reference count,
3973 * and the the application nust set the texture back to null (or have a leaky application),
3974 * This means we should pass the refcount upto the parent
3975 *******************************/
3976 if (NULL != This->updateStateBlock->textures[Stage]) {
3977 IUnknown *textureParent;
3978 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[Stage], (IUnknown **)&textureParent);
3979 /** NOTE: GetParent will increase the ref count for me, I won't clean up until the texture is set to NULL **/
3982 if (NULL != oldTexture) {
3983 IUnknown *textureParent;
3984 IWineD3DBaseTexture_GetParent(oldTexture, (IUnknown **)&textureParent);
3985 IUnknown_Release(textureParent);
3986 IUnknown_Release(textureParent); /** NOTE: Twice because GetParent adds a ref **/
3993 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
3994 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3995 TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */) \n", This, Stage, ppTexture);
3997 /* Reject invalid texture units */
3998 if (Stage >= GL_LIMITS(textures)) {
3999 TRACE("Attempt to access invalid texture rejected\n");
4000 return D3DERR_INVALIDCALL;
4002 *ppTexture=This->updateStateBlock->textures[Stage];
4004 IWineD3DBaseTexture_AddRef(*ppTexture);
4006 return D3DERR_INVALIDCALL;
4013 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type,
4014 IWineD3DSurface **ppBackBuffer) {
4015 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4016 IWineD3DSwapChain *swapChain;
4019 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4021 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4023 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4024 IWineD3DSwapChain_Release(swapChain);
4026 *ppBackBuffer = NULL;
4031 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4032 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4033 WARN("(%p) : stub, calling idirect3d for now\n", This);
4034 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4037 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
4038 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4039 IWineD3DSwapChain *swapChain;
4042 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4044 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4045 IWineD3DSwapChain_Release(swapChain);
4047 FIXME("(%p) Error getting display mode\n", This);
4052 * Stateblock related functions
4055 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4056 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4057 IWineD3DStateBlockImpl *object;
4058 TRACE("(%p)", This);
4059 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4060 if (NULL == object ) {
4061 FIXME("(%p)Error allocating memory for stateblock\n", This);
4062 return E_OUTOFMEMORY;
4064 TRACE("(%p) creted object %p\n", This, object);
4065 object->wineD3DDevice= This;
4066 /** FIXME: object->parent = parent; **/
4067 object->parent = NULL;
4068 object->blockType = WINED3DSBT_ALL;
4070 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
4072 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4073 This->updateStateBlock = object;
4074 This->isRecordingState = TRUE;
4076 TRACE("(%p) recording stateblock %p\n",This , object);
4080 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4081 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4083 if (!This->isRecordingState) {
4084 FIXME("(%p) not recording! returning error\n", This);
4085 *ppStateBlock = NULL;
4086 return D3DERR_INVALIDCALL;
4089 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4090 This->isRecordingState = FALSE;
4091 This->updateStateBlock = This->stateBlock;
4092 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4093 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4094 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4099 * Scene related functions
4101 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4102 /* At the moment we have no need for any functionality at the beginning
4104 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4105 TRACE("(%p) : stub\n", This);
4109 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4110 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4111 TRACE("(%p)\n", This);
4113 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4115 checkGLcall("glFlush");
4117 TRACE("End Scene\n");
4118 if(This->renderTarget != NULL) {
4120 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4121 IUnknown *targetContainer = NULL;
4122 if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
4123 || D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
4124 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
4125 /** always dirtify for now. we must find a better way to see that surface have been modified
4126 (Modifications should will only occur via draw-primitive, but we do need better locking
4127 switching to render-to-texture should remove the overhead though.
4129 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4130 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
4131 IWineD3DSurface_PreLoad(This->renderTarget);
4132 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4133 IUnknown_Release(targetContainer);
4136 This->sceneEnded = TRUE;
4141 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4142 CONST RECT* pSourceRect, CONST RECT* pDestRect,
4143 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4144 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4145 IWineD3DSwapChain *swapChain = NULL;
4147 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4149 TRACE("(%p) Presenting the frame\n", This);
4151 for(i = 0 ; i < swapchains ; i ++) {
4153 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4154 TRACE("presentinng chain %d, %p\n", i, swapChain);
4155 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4156 IWineD3DSwapChain_Release(swapChain);
4162 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4163 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4164 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4166 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4167 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4168 when the depth-buffer format does not contain stencil buffer information, this method fails. */
4169 GLbitfield glMask = 0;
4170 GLboolean old_ztest;
4171 GLfloat old_z_clear_value;
4172 GLint old_stencil_clear_value;
4173 GLfloat old_color_clear_value[4];
4175 CONST D3DRECT* curRect;
4177 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4178 Count, pRects, Flags, Z, Stencil);
4182 glEnable(GL_SCISSOR_TEST);
4183 checkGLcall("glEnable GL_SCISSOR_TEST");
4185 if (Count > 0 && pRects) {
4191 /* Only set the values up once, as they are not changing */
4192 if (Flags & D3DCLEAR_STENCIL) {
4193 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4194 glClearStencil(Stencil);
4195 checkGLcall("glClearStencil");
4196 glMask = glMask | GL_STENCIL_BUFFER_BIT;
4197 glStencilMask(0xFFFFFFFF);
4200 if (Flags & D3DCLEAR_ZBUFFER) {
4201 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4202 glDepthMask(GL_TRUE);
4203 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4205 checkGLcall("glClearDepth");
4206 glMask = glMask | GL_DEPTH_BUFFER_BIT;
4209 if (Flags & D3DCLEAR_TARGET) {
4210 TRACE("Clearing screen with glClear to color %lx\n", Color);
4211 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4212 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
4213 ((Color >> 8) & 0xFF) / 255.0f,
4214 ((Color >> 0) & 0xFF) / 255.0f,
4215 ((Color >> 24) & 0xFF) / 255.0f);
4216 checkGLcall("glClearColor");
4218 /* Clear ALL colors! */
4219 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4220 glMask = glMask | GL_COLOR_BUFFER_BIT;
4223 /* Now process each rect in turn */
4224 for (i = 0; i < Count || i == 0; i++) {
4227 /* Note gl uses lower left, width/height */
4228 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4229 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4230 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4231 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4232 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4233 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4234 checkGLcall("glScissor");
4236 glScissor(This->stateBlock->viewport.X,
4237 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
4238 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4239 This->stateBlock->viewport.Width,
4240 This->stateBlock->viewport.Height);
4241 checkGLcall("glScissor");
4244 /* Clear the selected rectangle (or full screen) */
4246 checkGLcall("glClear");
4248 /* Step to the next rectangle */
4249 if (curRect) curRect = curRect + sizeof(D3DRECT);
4252 /* Restore the old values (why..?) */
4253 if (Flags & D3DCLEAR_STENCIL) {
4254 glClearStencil(old_stencil_clear_value);
4255 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4257 if (Flags & D3DCLEAR_ZBUFFER) {
4258 glDepthMask(old_ztest);
4259 glClearDepth(old_z_clear_value);
4261 if (Flags & D3DCLEAR_TARGET) {
4262 glClearColor(old_color_clear_value[0],
4263 old_color_clear_value[1],
4264 old_color_clear_value[2],
4265 old_color_clear_value[3]);
4266 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4267 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4268 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4269 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4272 glDisable(GL_SCISSOR_TEST);
4273 checkGLcall("glDisable");
4282 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4283 UINT PrimitiveCount) {
4285 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4286 This->stateBlock->streamIsUP = FALSE;
4288 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4289 debug_d3dprimitivetype(PrimitiveType),
4290 StartVertex, PrimitiveCount);
4291 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
4292 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
4298 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4299 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4300 D3DPRIMITIVETYPE PrimitiveType,
4301 INT baseVIndex, UINT minIndex,
4302 UINT NumVertices, UINT startIndex, UINT primCount) {
4304 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4306 IWineD3DIndexBuffer *pIB;
4307 D3DINDEXBUFFER_DESC IdxBufDsc;
4309 pIB = This->stateBlock->pIndexData;
4310 This->stateBlock->streamIsUP = FALSE;
4312 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d \n", This,
4313 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4314 minIndex, NumVertices, startIndex, baseVIndex, primCount);
4316 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4317 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4323 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
4324 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
4329 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4330 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4331 UINT VertexStreamZeroStride) {
4332 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4334 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4335 debug_d3dprimitivetype(PrimitiveType),
4336 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4338 if (This->stateBlock->streamSource[0] != NULL) {
4339 IUnknown *vertexBufferParent;
4340 IWineD3DVertexBuffer_GetParent(This->stateBlock->streamSource[0], &vertexBufferParent);
4341 IUnknown_Release(vertexBufferParent);
4342 IUnknown_Release(vertexBufferParent);
4345 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4346 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4347 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4348 This->stateBlock->streamIsUP = TRUE;
4350 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
4351 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
4352 /* stream zero settings set to null at end, as per the msdn
4353 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
4355 This->stateBlock->streamStride[0] = 0;
4356 This->stateBlock->streamSource[0] = NULL;
4358 /*stream zero settings set to null at end, as per the msdn */
4362 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4363 UINT MinVertexIndex, UINT NumVertices,
4364 UINT PrimitiveCount, CONST void* pIndexData,
4365 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4366 UINT VertexStreamZeroStride) {
4368 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4370 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4371 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4372 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
4373 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4375 if (IndexDataFormat == WINED3DFMT_INDEX16) {
4381 if (This->stateBlock->streamSource[0] != NULL) {
4382 IUnknown *vertexBufferParent;
4383 IWineD3DVertexBuffer_GetParent(This->stateBlock->streamSource[0], &vertexBufferParent);
4384 This->stateBlock->streamSource[0] = NULL;
4385 IUnknown_Release(vertexBufferParent);
4386 IUnknown_Release(vertexBufferParent);
4389 if (This->stateBlock->pIndexData) {
4390 IUnknown *indexBufferParent;
4391 IWineD3DIndexBuffer_GetParent(This->stateBlock->pIndexData, &indexBufferParent);
4392 This->stateBlock->pIndexData = NULL;
4393 IUnknown_Release(indexBufferParent);
4394 IUnknown_Release(indexBufferParent);
4397 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4398 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4399 This->stateBlock->streamIsUP = TRUE;
4400 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4402 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
4403 /* stream zero settings set to null at end as per the msdn
4404 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
4407 /* stream zero settings set to null at end as per the msdn */
4408 This->stateBlock->streamSource[0] = NULL;
4409 This->stateBlock->streamStride[0] = 0;
4414 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4415 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
4416 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4417 D3DRESOURCETYPE sourceType;
4418 D3DRESOURCETYPE destinationType;
4419 IWineD3DTextureImpl *pDestTexture = (IWineD3DTextureImpl *)pDestinationTexture;
4420 IWineD3DTextureImpl *pSrcTexture = (IWineD3DTextureImpl *)pSourceTexture;
4423 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
4424 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
4425 if(sourceType != D3DRTYPE_TEXTURE && destinationType != D3DRTYPE_TEXTURE){
4426 FIXME("(%p) Only D3DRTYPE_TEXTURE to D3DRTYPE_TEXTURE supported\n", This);
4427 return D3DERR_INVALIDCALL;
4429 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
4431 /** TODO: Get rid of the casts to IWineD3DBaseTextureImpl
4432 repalce surfaces[x] with GetSurfaceLevel, or GetCubeMapSurface etc..
4433 think about moving the code into texture, and adding a member to base texture to occomplish this **/
4435 /* Make sure that the destination texture is loaded */
4436 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
4437 TRACE("Loading source texture\n");
4439 if(pSrcTexture->surfaces[0] == NULL || pDestTexture->surfaces[0] == NULL){
4440 FIXME("(%p) Texture src %p or dest %p has not surface %p %p\n", This, pSrcTexture, pDestTexture,
4441 pSrcTexture->surfaces[0], pDestTexture->surfaces[0]);
4444 if(((IWineD3DSurfaceImpl *)pSrcTexture->surfaces[0])->resource.pool != D3DPOOL_SYSTEMMEM ||
4445 ((IWineD3DSurfaceImpl *)pDestTexture->surfaces[0])->resource.pool != D3DPOOL_DEFAULT){
4447 FIXME("(%p) source %p must be SYSTEMMEM and dest %p must be DEFAULT\n",This, pSrcTexture, pDestTexture);
4448 return D3DERR_INVALIDCALL;
4450 /** TODO: check that both textures have the same number of levels **/
4452 if(IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) !=IWineD3DBaseTexture_GetLevelCount(pSourceTexture))
4453 return D3DERR_INVALIDCALL;
4455 /** TODO: move this code into baseTexture? device should never touch impl*'s **/
4456 for(i = 0 ; i < IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) ; i++){
4457 IWineD3DDevice_UpdateSurface(iface, pSrcTexture->surfaces[i], NULL, pDestTexture->surfaces[i], NULL);
4463 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
4464 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
4465 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
4466 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4468 TRACE("(%p) : stub\n", This);
4471 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
4472 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4474 TRACE("(%p) : stub\n", This);
4478 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
4479 IWineD3DSwapChain *swapChain;
4481 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4483 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
4484 IWineD3DSwapChain_Release(swapChain);
4489 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4490 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4491 /* return a sensible default */
4493 /* TODO: If the window is minimized then validate device shold return something other than d3d_ok */
4494 FIXME("(%p) : stub\n", This);
4498 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4499 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4501 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4502 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4503 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4504 return D3DERR_INVALIDCALL;
4506 for (j = 0; j < 256; ++j) {
4507 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
4508 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
4509 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
4510 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
4512 TRACE("(%p) : returning\n", This);
4516 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4517 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4519 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4520 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4521 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4522 return D3DERR_INVALIDCALL;
4524 for (j = 0; j < 256; ++j) {
4525 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
4526 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
4527 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
4528 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
4530 TRACE("(%p) : returning\n", This);
4534 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4535 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4536 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4537 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4538 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4539 return D3DERR_INVALIDCALL;
4541 /*TODO: stateblocks */
4542 This->currentPalette = PaletteNumber;
4543 TRACE("(%p) : returning\n", This);
4547 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4548 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4549 if (PaletteNumber == NULL) {
4550 WARN("(%p) : returning Invalid Call\n", This);
4551 return D3DERR_INVALIDCALL;
4553 /*TODO: stateblocks */
4554 *PaletteNumber = This->currentPalette;
4555 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
4559 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4560 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4561 static BOOL showFixmes = TRUE;
4563 FIXME("(%p) : stub\n", This);
4567 This->updateStateBlock->softwareVertexProcessing = bSoftware;
4572 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4573 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4574 static BOOL showFixmes = TRUE;
4576 FIXME("(%p) : stub\n", This);
4579 return This->updateStateBlock->softwareVertexProcessing;
4583 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
4584 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4586 pRasterStatus->InVBlank = TRUE;
4587 pRasterStatus->ScanLine = 0;
4588 FIXME("(%p) : stub\n", This);
4593 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4594 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4595 static BOOL showfixmes = TRUE;
4596 if(nSegments != 0.0f) {
4598 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4605 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4606 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4607 static BOOL showfixmes = TRUE;
4609 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4616 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4617 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4618 /** TODO: remove casts to IWineD3DSurfaceImpl
4619 * NOTE: move code to surface to accomplish this
4620 ****************************************/
4621 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
4622 int srcWidth, srcHeight;
4623 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
4624 WINED3DFORMAT destFormat, srcFormat;
4626 int destLeft, destTop;
4627 D3DPOOL srcPool, destPool;
4629 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
4630 glDescriptor *glDescription = NULL;
4631 GLenum textureDimensions = GL_TEXTURE_2D;
4632 IWineD3DBaseTexture *baseTexture;
4634 WINED3DSURFACE_DESC winedesc;
4636 memset(&winedesc, 0, sizeof(winedesc));
4637 winedesc.Width = &srcSurfaceWidth;
4638 winedesc.Height = &srcSurfaceHeight;
4639 winedesc.Pool = &srcPool;
4640 winedesc.Format = &srcFormat;
4642 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
4644 winedesc.Width = &destSurfaceWidth;
4645 winedesc.Height = &destSurfaceHeight;
4646 winedesc.Pool = &destPool;
4647 winedesc.Format = &destFormat;
4648 winedesc.Size = &destSize;
4650 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
4652 if(srcPool != D3DPOOL_SYSTEMMEM || destPool != D3DPOOL_DEFAULT){
4653 FIXME("source %p must be SYSTEMMEM and dest %p must be DEFAULT\n", pSourceSurface, pDestinationSurface);
4654 return D3DERR_INVALIDCALL;
4656 /* TODO: change this to use bindTexture */
4657 /* Make sure the surface is loaded and upto date */
4658 IWineD3DSurface_PreLoad(pDestinationSurface);
4660 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
4664 /* this needs to be done in lines if the sourceRect != the sourceWidth */
4665 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
4666 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
4667 destLeft = pDestPoint ? pDestPoint->x : 0;
4668 destTop = pDestPoint ? pDestPoint->y : 0;
4671 /* This function doesn't support compressed textures
4672 the pitch is just bytesPerPixel * width */
4674 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
4675 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
4676 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
4677 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
4679 /* TODO DXT formats */
4681 if(pSourceRect != NULL && pSourceRect->top != 0){
4682 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
4684 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
4686 ,glDescription->level
4691 ,glDescription->glFormat
4692 ,glDescription->glType
4693 ,IWineD3DSurface_GetData(pSourceSurface)
4697 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
4698 /* need to lock the surface to get the data */
4699 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
4701 /* TODO: Cube and volume support */
4703 /* not a whole row so we have to do it a line at a time */
4705 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
4706 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
4708 for(j = destTop ; j < (srcHeight + destTop) ; j++){
4710 glTexSubImage2D(glDescription->target
4711 ,glDescription->level
4716 ,glDescription->glFormat
4717 ,glDescription->glType
4718 ,data/* could be quicker using */
4723 } else { /* Full width, so just write out the whole texture */
4725 if (WINED3DFMT_DXT1 == destFormat ||
4726 WINED3DFMT_DXT3 == destFormat ||
4727 WINED3DFMT_DXT5 == destFormat) {
4728 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
4729 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
4730 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
4731 FIXME("Updating part of a compressed texture is not supported at the moment\n");
4732 } if (destFormat != srcFormat) {
4733 FIXME("Updating mixed format compressed texture is not curretly support\n");
4735 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
4736 glDescription->level,
4737 glDescription->glFormatInternal,
4742 IWineD3DSurface_GetData(pSourceSurface));
4745 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
4750 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
4751 to repack the data from pow2Width/Height to expected Width,Height, this makes the
4752 data returned by GetData non-power2 width/height with hardware non-power2
4753 pow2Width/height are set to surface width height, repacking isn't needed so it
4754 doesn't matter which function gets called. */
4755 glTexSubImage2D(glDescription->target
4756 ,glDescription->level
4761 ,glDescription->glFormat
4762 ,glDescription->glType
4763 ,IWineD3DSurface_GetData(pSourceSurface)
4768 checkGLcall("glTexSubImage2D");
4769 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
4770 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
4771 * surface bigger than it needs to be hmm.. */
4772 if (D3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
4773 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
4774 IWineD3DBaseTexture_Release(baseTexture);
4777 glDisable(textureDimensions); /* This needs to be managed better.... */
4783 /* Implementation details at http://developer.nvidia.com/attach/6494
4785 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
4786 hmm.. no longer supported use
4787 OpenGL evaluators or tessellate surfaces within your application.
4790 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
4791 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4792 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4793 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p) \n", This, Handle, pNumSegs, pRectPatchInfo);
4794 FIXME("(%p) : Stub\n", This);
4799 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
4800 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4801 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4802 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p) \n", This, Handle, pNumSegs, pTriPatchInfo);
4803 FIXME("(%p) : Stub\n", This);
4807 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
4808 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4809 TRACE("(%p) Handle(%d)\n", This, Handle);
4810 FIXME("(%p) : Stub\n", This);
4814 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
4815 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
4816 fill a surface with a block of color! */
4817 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4818 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
4819 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
4820 IWineD3DSwapChainImpl *container = NULL;
4821 BOOL isRenderTarget = FALSE;
4822 unsigned int width, height;
4823 unsigned int top, left;
4826 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
4828 if (surface->resource.pool != D3DPOOL_DEFAULT) {
4829 FIXME("call to colorfill with non D3DPOOL_DEFAULT surface\n");
4830 return D3DERR_INVALIDCALL;
4833 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
4834 if (D3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
4835 if (D3DUSAGE_RENDERTARGET & surface->resource.usage) {
4836 /* TODO: make sure we set everything back to the way it was, and context management!
4837 glGetIntegerv(GL_READ_BUFFER, &prev_read);
4838 vcheckGLcall("glIntegerv");
4839 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
4840 vcheckGLcall("glIntegerv");
4842 TRACE("Color fill to render targets may cause some graphics issues\n");
4843 if (pSurface == container->frontBuffer) {
4844 glDrawBuffer(GL_FRONT);
4846 glDrawBuffer(GL_BACK);
4849 if (D3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
4850 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld \n", surface, surface->resource.usage);
4852 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
4854 if (container != NULL) {
4855 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
4857 /* we can use GL_STENCIL_INDEX etc...*/
4860 if (container != NULL) {
4861 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
4863 isRenderTarget = TRUE;
4865 /* TODO: drawing to GL_FRONT and GL_BACK */
4866 /* TODO: see if things can be speeded up by using the correct
4867 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
4868 if (pRect == NULL) {
4871 width = surface->currentDesc.Width;
4872 height = surface->currentDesc.Height;
4876 width = pRect->x2 - left;
4877 height = pRect->y2 - top;
4880 data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
4881 /* Create a 'line' of color color, in the correct format for the surface */
4882 for (u = 0 ; u < width ; u ++) {
4887 if (isRenderTarget == FALSE) {
4888 glDescriptor *glDesc;
4889 IWineD3DSurface_PreLoad(pSurface);
4891 /* draw a block of the coloured line on the sufrace */
4892 IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
4893 for (v = 0 ; v< height;v++) {
4894 glTexSubImage2D(glDesc->target
4895 ,glDesc->level /* level */
4905 checkGLcall("glTexSubImage2D");
4907 glDisable(glDesc->target);
4909 /** FIXME: Using GLClear may be faster **/
4910 glRasterPos2i(left, top);
4911 glPixelZoom((float)width ,(float)height);
4912 glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
4913 checkGLcall("glDrawPixels");
4915 HeapFree(GetProcessHeap(), 0, data);
4921 /* rendertarget and deptth stencil functions */
4922 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
4923 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4925 /* FIXME: Implelent RenderTargetIndex >0 */
4926 if(RenderTargetIndex > 0)
4927 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
4929 *ppRenderTarget = This->renderTarget;
4930 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
4931 /* Note inc ref on returned surface */
4932 if(*ppRenderTarget != NULL)
4933 IWineD3DSurface_AddRef(*ppRenderTarget);
4937 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
4938 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4939 *ppZStencilSurface = This->depthStencilBuffer;
4940 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
4942 if(*ppZStencilSurface != NULL) {
4943 /* Note inc ref on returned surface */
4944 IWineD3DSurface_AddRef(*ppZStencilSurface);
4949 /* internal static helper functions */
4950 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
4951 IWineD3DSurface *RenderSurface);
4953 HRESULT WINAPI static IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain);
4955 HRESULT WINAPI static IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context);
4957 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
4958 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4959 HRESULT hr = D3D_OK;
4960 WINED3DVIEWPORT viewport;
4962 TRACE("(%p) Swapping rendertarget\n",This);
4963 if (RenderTargetIndex > 0) {
4964 FIXME("(%p) Render targets other than the first are not supported\n",This);
4965 RenderTargetIndex = 0;
4968 /* MSDN says that null disables the render target
4969 but a device must always be associated with a render target
4970 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
4972 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
4975 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
4976 FIXME("Trying to set render target 0 to NULL\n");
4977 return D3DERR_INVALIDCALL;
4979 /* TODO: replace Impl* usage with interface usage */
4980 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & D3DUSAGE_RENDERTARGET) {
4981 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);
4982 return D3DERR_INVALIDCALL;
4984 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
4985 * builds, but I think wine counts as a 'debug' build for now.
4986 ******************************/
4987 /* If we are trying to set what we already have, don't bother */
4988 if (pRenderTarget == This->renderTarget) {
4989 TRACE("Trying to do a NOP SetRenderTarget operation\n");
4991 /* Otherwise, set the render target up */
4993 if (FALSE == This->sceneEnded) {
4994 IWineD3DDevice_EndScene(iface);
4996 TRACE("clearing renderer\n");
4997 /* IWineD3DDeviceImpl_CleanRender(iface); */
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 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
5006 if (SUCCEEDED(hr)) {
5007 /* Finally, reset the viewport as the MSDN states. */
5008 /* TODO: Replace impl usage */
5009 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
5010 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
5013 viewport.MaxZ = 1.0f;
5014 viewport.MinZ = 0.0f;
5015 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
5017 FIXME("Unknown error setting the render target\n");
5019 This->sceneEnded = FALSE;
5023 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
5024 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5025 HRESULT hr = D3D_OK;
5026 IWineD3DSurface *tmp;
5028 TRACE("(%p) Swapping z-buffer\n",This);
5030 if (pNewZStencil == This->stencilBufferTarget) {
5031 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5033 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5034 * depending on the renter target implementation being used.
5035 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5036 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5037 * stencil buffer and incure an extra memory overhead
5038 ******************************************************/
5041 tmp = This->stencilBufferTarget;
5042 This->stencilBufferTarget = pNewZStencil;
5043 /* should we be calling the parent or the wined3d surface? */
5044 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
5045 if (NULL != tmp) IWineD3DSurface_Release(tmp);
5047 /** TODO: glEnable/glDisable on depth/stencil depending on
5048 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
5049 **********************************************************/
5056 /* Internal functions not in DirectX */
5057 /** TODO: move this off to the opengl context manager
5058 *(the swapchain doesn't need to know anything about offscreen rendering!)
5059 ****************************************************/
5061 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
5063 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5065 TRACE("(%p), %p\n", This, swapchain);
5067 if (swapchain->win != swapchain->drawable) {
5068 /* Set everything back the way it ws */
5069 swapchain->render_ctx = swapchain->glCtx;
5070 swapchain->drawable = swapchain->win;
5075 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
5076 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
5077 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5080 unsigned int height;
5081 WINED3DFORMAT format;
5082 WINED3DSURFACE_DESC surfaceDesc;
5083 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5084 surfaceDesc.Width = &width;
5085 surfaceDesc.Height = &height;
5086 surfaceDesc.Format = &format;
5087 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5089 /* I need a get width/height function (and should do something with the format) */
5090 for (i = 0; i < CONTEXT_CACHE; ++i) {
5091 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
5092 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
5093 the pSurface can be set to 0 allowing it to be reused from cache **/
5094 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
5095 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
5096 *context = &This->contextCache[i];
5099 if (This->contextCache[i].Width == 0) {
5100 This->contextCache[i].pSurface = pSurface;
5101 This->contextCache[i].Width = width;
5102 This->contextCache[i].Height = height;
5103 *context = &This->contextCache[i];
5107 if (i == CONTEXT_CACHE) {
5108 int minUsage = 0x7FFFFFFF; /* MAX_INT */
5109 glContext *dropContext = 0;
5110 for (i = 0; i < CONTEXT_CACHE; i++) {
5111 if (This->contextCache[i].usedcount < minUsage) {
5112 dropContext = &This->contextCache[i];
5113 minUsage = This->contextCache[i].usedcount;
5116 /* clean up the context (this doesn't work for ATI at the moment */
5118 glXDestroyContext(swapchain->display, dropContext->context);
5119 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
5122 dropContext->Width = 0;
5123 dropContext->pSurface = pSurface;
5124 *context = dropContext;
5126 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
5127 for (i = 0; i < CONTEXT_CACHE; i++) {
5128 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
5132 if (*context != NULL)
5135 return E_OUTOFMEMORY;
5138 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
5139 * the functionality needs splitting up so that we don't do more than we should do.
5140 * this only seems to impact performance a little.
5141 ******************************/
5142 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5143 IWineD3DSurface *RenderSurface) {
5144 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5146 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
5147 HRESULT ret = D3DERR_INVALIDCALL;
5148 IWineD3DSurface *tmp;
5150 * Currently only active for GLX >= 1.3
5151 * for others versions we'll have to use GLXPixmaps
5153 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
5154 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
5155 * so only check OpenGL version
5156 * ..........................
5157 * I don't believe that it is a problem with NVidia headers,
5158 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
5159 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
5161 * Your application will report GLX version 1.2 on glXQueryVersion.
5162 * However, it is safe to call the GLX 1.3 functions as described below.
5164 #if defined(GL_VERSION_1_3)
5166 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
5167 GLXFBConfig* cfgs = NULL;
5171 IWineD3DSwapChain *currentSwapchain;
5172 IWineD3DSwapChainImpl *swapchain;
5173 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
5174 * but switch them off if the StencilSurface is set to NULL
5175 ** *********************************************************/
5176 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
5177 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
5180 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
5181 it StencilSurface != NULL && zBufferTarget == NULL switch it on
5184 #define PUSH1(att) attribs[nAttribs++] = (att);
5185 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
5187 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
5189 /** TODO: remove the reff to Impl (context manager should fix this!) **/
5190 IWineD3DSwapChainImpl *impSwapChain;
5191 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
5192 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
5193 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
5198 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
5199 PUSH2(GLX_X_RENDERABLE, TRUE);
5200 PUSH2(GLX_DOUBLEBUFFER, TRUE);
5201 TRACE("calling makeglcfg\n");
5202 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
5205 TRACE("calling chooseFGConfig\n");
5206 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5209 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
5210 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
5211 why we failed and only show this message once! */
5212 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"); /**/
5214 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
5215 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
5216 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
5217 PUSH2(GLX_DOUBLEBUFFER, FALSE);
5218 TRACE("calling makeglcfg\n");
5219 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
5221 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5228 for (i = 0; i < nCfgs; ++i) {
5229 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
5230 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
5231 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
5234 if (NULL != This->renderTarget) {
5236 vcheckGLcall("glFlush");
5237 /** This is only useful if the old render target was a swapchain,
5238 * we need to supercede this with a function that displays
5239 * the current buffer on the screen. This is easy to do in glx1.3 but
5240 * we need to do copy-write pixels in glx 1.2.
5241 ************************************************/
5242 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
5244 printf("Hit Enter to get next frame ...\n");
5250 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain) != D3D_OK) {
5251 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
5252 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
5256 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
5257 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
5258 **********************************************************************/
5259 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == D3D_OK) {
5260 /* We also need to make sure that the lights &co are also in the context of the swapchains */
5261 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
5262 TRACE("making swapchain active\n");
5263 if (RenderSurface != This->renderTarget) {
5264 if (RenderSurface == swapchain->backBuffer) {
5266 /* This could be flagged so that some operations work directly with the front buffer */
5267 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
5269 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
5271 TRACE("Error in setting current context: context %p drawable %ld !\n",
5272 impSwapChain->glCtx, impSwapChain->win);
5275 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5277 checkGLcall("glXMakeContextCurrent");
5279 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5281 else if (pbuffer_support == TRUE && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
5283 /** ********************************************************************
5284 * This is a quickly hacked out implementation of offscreen textures.
5285 * It will work in most cases but there may be problems if the client
5286 * modifies the texture directly, or expects the contents of the rendertarget
5289 * There are some real speed vs compatibility issues here:
5290 * we should really use a new context for every texture, but that eats ram.
5291 * we should also be restoring the texture to the pbuffer but that eats CPU
5292 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
5293 * but if this means reusing the display backbuffer then we need to make sure that
5294 * states are correctly preserved.
5295 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
5296 * and gain a good performance increase at the cost of compatibility.
5297 * I would suggest that, when this is the case, a user configurable flag be made
5298 * available, allowing the user to choose the best emulated experience for them.
5299 *********************************************************************/
5301 XVisualInfo *visinfo;
5302 glContext *newContext;
5304 /* Here were using a shared context model */
5305 if (D3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
5306 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5309 /* If the context doesn't exist then create a new one */
5310 /* TODO: This should really be part of findGlContext */
5311 if (NULL == newContext->context) {
5313 TRACE("making new buffer\n");
5315 PUSH2(GLX_PBUFFER_WIDTH, newContext->Width);
5316 PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
5319 newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
5321 /** ****************************************
5322 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
5324 * In future releases, we may provide the calls glXCreateNewContext,
5325 * glXQueryDrawable and glXMakeContextCurrent.
5326 * so until then we have to use glXGetVisualFromFBConfig &co..
5327 ********************************************/
5330 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
5332 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
5334 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
5338 if (NULL == newContext || NULL == newContext->context) {
5339 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5341 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
5342 if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
5343 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
5346 /* Clean up the old context */
5347 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5348 /* Set the current context of the swapchain to the new context */
5349 impSwapChain->drawable = newContext->drawable;
5350 impSwapChain->render_ctx = newContext->context;
5354 #if 1 /* Apply the stateblock to the new context
5355 FIXME: This is a bit of a hack, each context should know it's own state,
5356 the directX current directX state should then be applied to the context */
5359 IWineD3DStateBlockImpl *oldUpdateStateBlock;
5360 oldUpdateStateBlock = This->updateStateBlock;
5361 oldRecording= This->isRecordingState;
5362 This->isRecordingState = FALSE;
5363 This->updateStateBlock = This->stateBlock;
5364 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
5366 This->isRecordingState = oldRecording;
5367 This->updateStateBlock = oldUpdateStateBlock;
5372 /* clean up the current rendertargets swapchain (if it belonged to one) */
5373 if (currentSwapchain != NULL) {
5374 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
5377 /* Were done with the opengl context management, setup the rendertargets */
5379 tmp = This->renderTarget;
5380 This->renderTarget = RenderSurface;
5381 IWineD3DSurface_AddRef(This->renderTarget);
5382 IWineD3DSurface_Release(tmp);
5388 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
5389 /* Check that the container is not a swapchain member */
5391 IWineD3DSwapChain *tmpSwapChain;
5392 if (D3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
5393 This->renderUpsideDown = TRUE;
5395 This->renderUpsideDown = FALSE;
5396 IWineD3DSwapChain_Release(tmpSwapChain);
5398 /* Force updating the cull mode */
5399 TRACE("setting render state\n");
5400 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
5401 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
5403 /* Force updating projection matrix */
5404 This->last_was_rhw = FALSE;
5405 This->proj_valid = FALSE;
5413 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
5414 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
5419 if ( NULL != impSwapChain) {
5420 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
5428 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
5429 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
5430 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5431 /* TODO: the use of Impl is deprecated. */
5432 /* some basic validation checks */
5433 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
5435 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
5437 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
5438 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
5439 return D3DERR_INVALIDCALL;
5441 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
5442 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
5443 return D3DERR_INVALIDCALL;
5445 /* TODO: make the cursor 'real' */
5447 This->xHotSpot = XHotSpot;
5448 This->yHotSpot = YHotSpot;
5453 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
5454 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5455 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
5457 This->xScreenSpace = XScreenSpace;
5458 This->yScreenSpace = YScreenSpace;
5464 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
5465 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5466 TRACE("(%p) : visible(%d)\n", This, bShow);
5468 This->bCursorVisible = bShow;
5473 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
5474 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5475 FIXME("(%p) : stub\n", This); /* No way of notifying yet! */
5480 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
5481 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5482 /** FIXME: Resource tracking needs to be done,
5483 * The closes we can do to this is set the priorities of all managed textures low
5484 * and then reset them.
5485 ***********************************************************/
5486 FIXME("(%p) : stub\n", This);
5490 HRESULT WINAPI IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
5491 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5492 /** FIXME: Resource trascking needs to be done.
5493 * in effect this pulls all non only default
5494 * textures out of video memory and deletes all glTextures (glDeleteTextures)
5495 * and should clear down the context and set it up according to pPresentationParameters
5496 ***********************************************************/
5497 FIXME("(%p) : stub\n", This);
5501 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
5502 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5503 /** FIXME: always true at the moment **/
5504 if(bEnableDialogs == FALSE) {
5505 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
5511 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
5512 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5514 FIXME("(%p) : stub\n", This);
5515 /* Setup some reasonable defaults */
5516 pParameters->AdapterOrdinal = 0; /* always for now */
5517 pParameters->DeviceType = D3DDEVTYPE_HAL; /* always for now */
5518 pParameters->hFocusWindow = 0;
5519 pParameters->BehaviorFlags =0;
5523 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
5524 IWineD3DSwapChain *swapchain;
5525 HRESULT hrc = D3D_OK;
5527 TRACE("Relaying to swapchain\n");
5529 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
5530 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (D3DGAMMARAMP *)pRamp);
5531 IWineD3DSwapChain_Release(swapchain);
5536 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
5537 IWineD3DSwapChain *swapchain;
5538 HRESULT hrc = D3D_OK;
5540 TRACE("Relaying to swapchain\n");
5542 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
5543 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
5544 IWineD3DSwapChain_Release(swapchain);
5550 /** ********************************************************
5551 * Notification functions
5552 ** ********************************************************/
5553 /** This function must be called in the release of a resource when ref == 0,
5554 * the contents of resource must still be correct,
5555 * any handels to other resource held by the caller must be closed
5556 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
5557 *****************************************************/
5558 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5559 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5560 ResourceList* resourceList;
5562 TRACE("(%p) : resource %p\n", This, resource);
5564 EnterCriticalSection(&resourceStoreCriticalSection);
5566 /* add a new texture to the frot of the linked list */
5567 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
5568 resourceList->resource = resource;
5570 /* Get the old head */
5571 resourceList->next = This->resources;
5573 This->resources = resourceList;
5574 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
5577 LeaveCriticalSection(&resourceStoreCriticalSection);
5582 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5583 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5584 ResourceList* resourceList = NULL;
5585 ResourceList* previousResourceList = NULL;
5587 TRACE("(%p) : resource %p\n", This, resource);
5590 EnterCriticalSection(&resourceStoreCriticalSection);
5592 resourceList = This->resources;
5594 while (resourceList != NULL) {
5595 if(resourceList->resource == resource) break;
5596 previousResourceList = resourceList;
5597 resourceList = resourceList->next;
5600 if (resourceList == NULL) {
5601 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
5603 LeaveCriticalSection(&resourceStoreCriticalSection);
5607 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
5609 /* make sure we don't leave a hole in the list */
5610 if (previousResourceList != NULL) {
5611 previousResourceList->next = resourceList->next;
5613 This->resources = resourceList->next;
5617 LeaveCriticalSection(&resourceStoreCriticalSection);
5623 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
5624 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5627 TRACE("(%p) : resource %p\n", This, resource);
5628 switch(IWineD3DResource_GetType(resource)){
5629 case D3DRTYPE_SURFACE:
5630 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
5632 case D3DRTYPE_TEXTURE:
5633 case D3DRTYPE_CUBETEXTURE:
5634 case D3DRTYPE_VOLUMETEXTURE:
5635 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
5636 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5637 IUnknown *textureParent;
5638 IWineD3DBaseTexture_GetParent(This->stateBlock->textures[counter], &textureParent);
5639 /* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
5640 FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter, resource, textureParent);
5641 IUnknown_Release(textureParent);
5642 This->stateBlock->textures[counter] = NULL;
5644 if (This->updateStateBlock != This->stateBlock ){
5645 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5646 IUnknown *textureParent;
5647 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[counter], &textureParent);
5648 /* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
5649 FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter, resource, textureParent);
5650 IUnknown_Release(textureParent);
5651 This->updateStateBlock->textures[counter] = NULL;
5656 case D3DRTYPE_VOLUME:
5657 /* TODO: nothing really? */
5659 case D3DRTYPE_VERTEXBUFFER:
5660 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
5663 TRACE("Cleaning up stream pointers\n");
5665 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
5666 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
5667 FINDOUT: should changes.streamSource[StreamNumber] be set ?
5669 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5670 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
5671 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
5672 This->updateStateBlock->streamSource[streamNumber] = 0;
5673 /* Set changed flag? */
5676 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) */
5677 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
5678 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
5679 This->stateBlock->streamSource[streamNumber] = 0;
5682 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
5683 else { /* This shouldn't happen */
5684 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
5691 case D3DRTYPE_INDEXBUFFER:
5692 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
5693 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5694 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5695 This->updateStateBlock->pIndexData = NULL;
5698 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
5699 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5700 This->stateBlock->pIndexData = NULL;
5706 FIXME("(%p) unknown resource type %p %u \n", This, resource, IWineD3DResource_GetType(resource));
5711 /* Remove the resoruce from the resourceStore */
5712 IWineD3DDeviceImpl_RemoveResource(iface, resource);
5714 TRACE("Resource released\n");
5719 /** This function is to be called by the swapchain when it is released and it's ref = 0
5720 *****************************************************/
5721 void WINAPI IWineD3DDeviceImpl_SwapChainReleased(IWineD3DDevice *iface, IWineD3DSwapChain *swapChain){
5722 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5723 SwapChainList **nextSwapchain;
5724 nextSwapchain = &This->swapchains;
5726 /* Check to see if the swapchian is being used as the render target */
5727 if (This->renderTarget != NULL) {
5728 IWineD3DSurface *swapchainBackBuffer;
5730 IWineD3DSwapChain_GetBackBuffer(swapChain, 0 ,( D3DBACKBUFFER_TYPE) 0, &swapchainBackBuffer);
5731 if (This->renderTarget == swapchainBackBuffer) {
5732 /* Don't know what to do, so warn and carry on as usual (which in this case leaves the renderterget in limbo) */
5733 FIXME("Atempting to release a swapchain that is currently beuing used as a render target, behaviour is undefined\n");
5737 /* Go through the swapchain list and try to find the swapchain being released */
5738 while(*nextSwapchain != NULL && (*nextSwapchain)->swapchain != swapChain) {
5739 nextSwapchain = &(*nextSwapchain)->next;
5742 /* Check to see if we found the swapchain */
5743 if (NULL != *nextSwapchain) {
5744 /* We found the swapchain so remove it from the list */
5745 TRACE("(%p) releasing swapchain(%p)\n", iface, swapChain);
5746 HeapFree(GetProcessHeap(), 0 , *nextSwapchain);
5747 *nextSwapchain = (*nextSwapchain)->next;
5749 /* We didn't find the swapchain on the list, this can only heppen because of a programming error in wined3d */
5750 FIXME("(%p) Attempting to release a swapchain (%p) that hasn't been stored\n", iface, swapChain);
5753 TRACE("swapchain (%p) released\n", swapChain);
5757 /**********************************************************
5758 * IWineD3DDevice VTbl follows
5759 **********************************************************/
5761 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
5763 /*** IUnknown methods ***/
5764 IWineD3DDeviceImpl_QueryInterface,
5765 IWineD3DDeviceImpl_AddRef,
5766 IWineD3DDeviceImpl_Release,
5767 /*** IWineD3DDevice methods ***/
5768 IWineD3DDeviceImpl_GetParent,
5769 /*** Creation methods**/
5770 IWineD3DDeviceImpl_CreateVertexBuffer,
5771 IWineD3DDeviceImpl_CreateIndexBuffer,
5772 IWineD3DDeviceImpl_CreateStateBlock,
5773 IWineD3DDeviceImpl_CreateSurface,
5774 IWineD3DDeviceImpl_CreateTexture,
5775 IWineD3DDeviceImpl_CreateVolumeTexture,
5776 IWineD3DDeviceImpl_CreateVolume,
5777 IWineD3DDeviceImpl_CreateCubeTexture,
5778 IWineD3DDeviceImpl_CreateQuery,
5779 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
5780 IWineD3DDeviceImpl_CreateVertexDeclaration,
5781 IWineD3DDeviceImpl_CreateVertexShader,
5782 IWineD3DDeviceImpl_CreatePixelShader,
5783 /*** Odd functions **/
5784 IWineD3DDeviceImpl_EvictManagedResources,
5785 IWineD3DDeviceImpl_GetAvailableTextureMem,
5786 IWineD3DDeviceImpl_GetBackBuffer,
5787 IWineD3DDeviceImpl_GetCreationParameters,
5788 IWineD3DDeviceImpl_GetDeviceCaps,
5789 IWineD3DDeviceImpl_GetDirect3D,
5790 IWineD3DDeviceImpl_GetDisplayMode,
5791 IWineD3DDeviceImpl_GetNumberOfSwapChains,
5792 IWineD3DDeviceImpl_GetRasterStatus,
5793 IWineD3DDeviceImpl_GetSwapChain,
5794 IWineD3DDeviceImpl_Reset,
5795 IWineD3DDeviceImpl_SetDialogBoxMode,
5796 IWineD3DDeviceImpl_SetCursorProperties,
5797 IWineD3DDeviceImpl_SetCursorPosition,
5798 IWineD3DDeviceImpl_ShowCursor,
5799 IWineD3DDeviceImpl_TestCooperativeLevel,
5800 /*** Getters and setters **/
5801 IWineD3DDeviceImpl_SetClipPlane,
5802 IWineD3DDeviceImpl_GetClipPlane,
5803 IWineD3DDeviceImpl_SetClipStatus,
5804 IWineD3DDeviceImpl_GetClipStatus,
5805 IWineD3DDeviceImpl_SetCurrentTexturePalette,
5806 IWineD3DDeviceImpl_GetCurrentTexturePalette,
5807 IWineD3DDeviceImpl_SetDepthStencilSurface,
5808 IWineD3DDeviceImpl_GetDepthStencilSurface,
5809 IWineD3DDeviceImpl_SetFVF,
5810 IWineD3DDeviceImpl_GetFVF,
5811 IWineD3DDeviceImpl_SetGammaRamp,
5812 IWineD3DDeviceImpl_GetGammaRamp,
5813 IWineD3DDeviceImpl_SetIndices,
5814 IWineD3DDeviceImpl_GetIndices,
5815 IWineD3DDeviceImpl_SetLight,
5816 IWineD3DDeviceImpl_GetLight,
5817 IWineD3DDeviceImpl_SetLightEnable,
5818 IWineD3DDeviceImpl_GetLightEnable,
5819 IWineD3DDeviceImpl_SetMaterial,
5820 IWineD3DDeviceImpl_GetMaterial,
5821 IWineD3DDeviceImpl_SetNPatchMode,
5822 IWineD3DDeviceImpl_GetNPatchMode,
5823 IWineD3DDeviceImpl_SetPaletteEntries,
5824 IWineD3DDeviceImpl_GetPaletteEntries,
5825 IWineD3DDeviceImpl_SetPixelShader,
5826 IWineD3DDeviceImpl_GetPixelShader,
5827 IWineD3DDeviceImpl_SetPixelShaderConstantB,
5828 IWineD3DDeviceImpl_GetPixelShaderConstantB,
5829 IWineD3DDeviceImpl_SetPixelShaderConstantI,
5830 IWineD3DDeviceImpl_GetPixelShaderConstantI,
5831 IWineD3DDeviceImpl_SetPixelShaderConstantF,
5832 IWineD3DDeviceImpl_GetPixelShaderConstantF,
5833 IWineD3DDeviceImpl_SetRenderState,
5834 IWineD3DDeviceImpl_GetRenderState,
5835 IWineD3DDeviceImpl_SetRenderTarget,
5836 IWineD3DDeviceImpl_GetRenderTarget,
5837 IWineD3DDeviceImpl_SetSamplerState,
5838 IWineD3DDeviceImpl_GetSamplerState,
5839 IWineD3DDeviceImpl_SetScissorRect,
5840 IWineD3DDeviceImpl_GetScissorRect,
5841 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
5842 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
5843 IWineD3DDeviceImpl_SetStreamSource,
5844 IWineD3DDeviceImpl_GetStreamSource,
5845 IWineD3DDeviceImpl_SetStreamSourceFreq,
5846 IWineD3DDeviceImpl_GetStreamSourceFreq,
5847 IWineD3DDeviceImpl_SetTexture,
5848 IWineD3DDeviceImpl_GetTexture,
5849 IWineD3DDeviceImpl_SetTextureStageState,
5850 IWineD3DDeviceImpl_GetTextureStageState,
5851 IWineD3DDeviceImpl_SetTransform,
5852 IWineD3DDeviceImpl_GetTransform,
5853 IWineD3DDeviceImpl_SetVertexDeclaration,
5854 IWineD3DDeviceImpl_GetVertexDeclaration,
5855 IWineD3DDeviceImpl_SetVertexShader,
5856 IWineD3DDeviceImpl_GetVertexShader,
5857 IWineD3DDeviceImpl_SetVertexShaderConstantB,
5858 IWineD3DDeviceImpl_GetVertexShaderConstantB,
5859 IWineD3DDeviceImpl_SetVertexShaderConstantI,
5860 IWineD3DDeviceImpl_GetVertexShaderConstantI,
5861 IWineD3DDeviceImpl_SetVertexShaderConstantF,
5862 IWineD3DDeviceImpl_GetVertexShaderConstantF,
5863 IWineD3DDeviceImpl_SetViewport,
5864 IWineD3DDeviceImpl_GetViewport,
5865 IWineD3DDeviceImpl_MultiplyTransform,
5866 IWineD3DDeviceImpl_ValidateDevice,
5867 IWineD3DDeviceImpl_ProcessVertices,
5868 /*** State block ***/
5869 IWineD3DDeviceImpl_BeginStateBlock,
5870 IWineD3DDeviceImpl_EndStateBlock,
5871 /*** Scene management ***/
5872 IWineD3DDeviceImpl_BeginScene,
5873 IWineD3DDeviceImpl_EndScene,
5874 IWineD3DDeviceImpl_Present,
5875 IWineD3DDeviceImpl_Clear,
5877 IWineD3DDeviceImpl_DrawPrimitive,
5878 IWineD3DDeviceImpl_DrawIndexedPrimitive,
5879 IWineD3DDeviceImpl_DrawPrimitiveUP,
5880 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
5881 IWineD3DDeviceImpl_DrawRectPatch,
5882 IWineD3DDeviceImpl_DrawTriPatch,
5883 IWineD3DDeviceImpl_DeletePatch,
5884 IWineD3DDeviceImpl_ColorFill,
5885 IWineD3DDeviceImpl_UpdateTexture,
5886 IWineD3DDeviceImpl_UpdateSurface,
5887 IWineD3DDeviceImpl_StretchRect,
5888 IWineD3DDeviceImpl_GetRenderTargetData,
5889 IWineD3DDeviceImpl_GetFrontBufferData,
5890 /*** Internal use IWineD3DDevice methods ***/
5891 IWineD3DDeviceImpl_SetupTextureStates,
5892 /*** object tracking ***/
5893 IWineD3DDeviceImpl_SwapChainReleased,
5894 IWineD3DDeviceImpl_ResourceReleased
5898 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
5899 WINED3DRS_ALPHABLENDENABLE ,
5900 WINED3DRS_ALPHAFUNC ,
5901 WINED3DRS_ALPHAREF ,
5902 WINED3DRS_ALPHATESTENABLE ,
5904 WINED3DRS_COLORWRITEENABLE ,
5905 WINED3DRS_DESTBLEND ,
5906 WINED3DRS_DITHERENABLE ,
5907 WINED3DRS_FILLMODE ,
5908 WINED3DRS_FOGDENSITY ,
5910 WINED3DRS_FOGSTART ,
5911 WINED3DRS_LASTPIXEL ,
5912 WINED3DRS_SHADEMODE ,
5913 WINED3DRS_SRCBLEND ,
5914 WINED3DRS_STENCILENABLE ,
5915 WINED3DRS_STENCILFAIL ,
5916 WINED3DRS_STENCILFUNC ,
5917 WINED3DRS_STENCILMASK ,
5918 WINED3DRS_STENCILPASS ,
5919 WINED3DRS_STENCILREF ,
5920 WINED3DRS_STENCILWRITEMASK ,
5921 WINED3DRS_STENCILZFAIL ,
5922 WINED3DRS_TEXTUREFACTOR ,
5933 WINED3DRS_ZWRITEENABLE
5936 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
5937 WINED3DTSS_ADDRESSW ,
5938 WINED3DTSS_ALPHAARG0 ,
5939 WINED3DTSS_ALPHAARG1 ,
5940 WINED3DTSS_ALPHAARG2 ,
5941 WINED3DTSS_ALPHAOP ,
5942 WINED3DTSS_BUMPENVLOFFSET ,
5943 WINED3DTSS_BUMPENVLSCALE ,
5944 WINED3DTSS_BUMPENVMAT00 ,
5945 WINED3DTSS_BUMPENVMAT01 ,
5946 WINED3DTSS_BUMPENVMAT10 ,
5947 WINED3DTSS_BUMPENVMAT11 ,
5948 WINED3DTSS_COLORARG0 ,
5949 WINED3DTSS_COLORARG1 ,
5950 WINED3DTSS_COLORARG2 ,
5951 WINED3DTSS_COLOROP ,
5952 WINED3DTSS_RESULTARG ,
5953 WINED3DTSS_TEXCOORDINDEX ,
5954 WINED3DTSS_TEXTURETRANSFORMFLAGS
5957 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
5958 WINED3DSAMP_ADDRESSU ,
5959 WINED3DSAMP_ADDRESSV ,
5960 WINED3DSAMP_ADDRESSW ,
5961 WINED3DSAMP_BORDERCOLOR ,
5962 WINED3DSAMP_MAGFILTER ,
5963 WINED3DSAMP_MINFILTER ,
5964 WINED3DSAMP_MIPFILTER ,
5965 WINED3DSAMP_MIPMAPLODBIAS ,
5966 WINED3DSAMP_MAXMIPLEVEL ,
5967 WINED3DSAMP_MAXANISOTROPY ,
5968 WINED3DSAMP_SRGBTEXTURE ,
5969 WINED3DSAMP_ELEMENTINDEX
5972 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
5974 WINED3DRS_AMBIENTMATERIALSOURCE ,
5975 WINED3DRS_CLIPPING ,
5976 WINED3DRS_CLIPPLANEENABLE ,
5977 WINED3DRS_COLORVERTEX ,
5978 WINED3DRS_DIFFUSEMATERIALSOURCE ,
5979 WINED3DRS_EMISSIVEMATERIALSOURCE ,
5980 WINED3DRS_FOGDENSITY ,
5982 WINED3DRS_FOGSTART ,
5983 WINED3DRS_FOGTABLEMODE ,
5984 WINED3DRS_FOGVERTEXMODE ,
5985 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
5986 WINED3DRS_LIGHTING ,
5987 WINED3DRS_LOCALVIEWER ,
5988 WINED3DRS_MULTISAMPLEANTIALIAS ,
5989 WINED3DRS_MULTISAMPLEMASK ,
5990 WINED3DRS_NORMALIZENORMALS ,
5991 WINED3DRS_PATCHEDGESTYLE ,
5992 WINED3DRS_POINTSCALE_A ,
5993 WINED3DRS_POINTSCALE_B ,
5994 WINED3DRS_POINTSCALE_C ,
5995 WINED3DRS_POINTSCALEENABLE ,
5996 WINED3DRS_POINTSIZE ,
5997 WINED3DRS_POINTSIZE_MAX ,
5998 WINED3DRS_POINTSIZE_MIN ,
5999 WINED3DRS_POINTSPRITEENABLE ,
6000 WINED3DRS_RANGEFOGENABLE ,
6001 WINED3DRS_SPECULARMATERIALSOURCE ,
6002 WINED3DRS_TWEENFACTOR ,
6003 WINED3DRS_VERTEXBLEND
6006 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
6007 WINED3DTSS_TEXCOORDINDEX ,
6008 WINED3DTSS_TEXTURETRANSFORMFLAGS
6011 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
6012 WINED3DSAMP_DMAPOFFSET