2 * IWineD3DDevice implementation
4 * Copyright 2002 Lionel Ulmer
5 * Copyright 2002-2005 Jason Edmeades
6 * Copyright 2003-2004 Raphael Junqueira
7 * Copyright 2004 Christian Costa
8 * Copyright 2005 Oliver Stieber
9 * Copyright 2006 Stefan Dösinger for CodeWeavers
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #include "wined3d_private.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
33 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
35 /* x11drv GDI escapes */
36 #define X11DRV_ESCAPE 6789
37 enum x11drv_escape_codes
39 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
40 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
41 X11DRV_GET_FONT, /* get current X font for a DC */
44 /* retrieve the X display to use on a given DC */
45 inline static Display *get_display( HDC hdc )
48 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
50 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
51 sizeof(display), (LPSTR)&display )) display = NULL;
55 /* Memory tracking and object counting */
56 static unsigned int emulated_textureram = 64*1024*1024;
58 /* TODO: setup some flags in the regestry to enable, disable pbuffer support */
59 /* enable pbuffer support for offscreen textures */
60 BOOL pbuffer_support = FALSE;
61 /* allocate one pbuffer per surface */
62 BOOL pbuffer_per_surface = FALSE;
64 /* static function declarations */
65 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
67 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type);
70 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return WINED3DERR_OUTOFVIDEOMEMORY;}
72 #define D3DCREATEOBJECTINSTANCE(object, type) { \
73 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
74 D3DMEMCHECK(object, pp##type); \
75 object->lpVtbl = &IWineD3D##type##_Vtbl; \
76 object->wineD3DDevice = This; \
77 object->parent = parent; \
79 *pp##type = (IWineD3D##type *) object; \
82 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
83 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
84 D3DMEMCHECK(object, pp##type); \
85 object->lpVtbl = &IWineD3D##type##_Vtbl; \
86 object->resource.wineD3DDevice = This; \
87 object->resource.parent = parent; \
88 object->resource.resourceType = d3dtype; \
89 object->resource.ref = 1; \
90 object->resource.pool = Pool; \
91 object->resource.format = Format; \
92 object->resource.usage = Usage; \
93 object->resource.size = _size; \
94 /* Check that we have enough video ram left */ \
95 if (Pool == WINED3DPOOL_DEFAULT) { \
96 if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
97 WARN("Out of 'bogus' video memory\n"); \
98 HeapFree(GetProcessHeap(), 0, object); \
100 return WINED3DERR_OUTOFVIDEOMEMORY; \
102 globalChangeGlRam(_size); \
104 object->resource.allocatedMemory = (0 == _size ? NULL : Pool == WINED3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
105 if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != WINED3DPOOL_DEFAULT) { \
106 FIXME("Out of memory!\n"); \
107 HeapFree(GetProcessHeap(), 0, object); \
109 return WINED3DERR_OUTOFVIDEOMEMORY; \
111 *pp##type = (IWineD3D##type *) object; \
112 IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
113 TRACE("(%p) : Created resource %p\n", This, object); \
116 #define D3DINITIALIZEBASETEXTURE(_basetexture) { \
117 _basetexture.levels = Levels; \
118 _basetexture.filterType = (Usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE; \
119 _basetexture.LOD = 0; \
120 _basetexture.dirty = TRUE; \
123 /**********************************************************
124 * Global variable / Constants follow
125 **********************************************************/
126 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
128 /**********************************************************
129 * Utility functions follow
130 **********************************************************/
131 /* Convert the D3DLIGHT properties into equivalent gl lights */
132 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
135 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
136 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
138 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
139 glMatrixMode(GL_MODELVIEW);
141 glLoadMatrixf((float *)&This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
144 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
145 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
146 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
147 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
148 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
149 checkGLcall("glLightfv");
152 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
153 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
154 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
155 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
156 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
157 checkGLcall("glLightfv");
160 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
161 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
162 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
163 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
164 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
165 checkGLcall("glLightfv");
167 /* Attenuation - Are these right? guessing... */
168 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
169 checkGLcall("glLightf");
170 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
171 checkGLcall("glLightf");
173 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
174 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
176 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
179 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
180 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
181 checkGLcall("glLightf");
183 switch (lightInfo->OriginalParms.Type) {
186 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
187 checkGLcall("glLightfv");
188 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
189 checkGLcall("glLightf");
195 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
196 checkGLcall("glLightfv");
198 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
199 checkGLcall("glLightfv");
200 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
201 checkGLcall("glLightf");
202 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
203 checkGLcall("glLightf");
207 case D3DLIGHT_DIRECTIONAL:
209 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
210 checkGLcall("glLightfv");
211 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
212 checkGLcall("glLightf");
213 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
214 checkGLcall("glLightf");
218 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
221 /* Restore the modelview matrix */
225 /* Apply the current values to the specified texture stage */
226 void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Sampler, DWORD Flags) {
227 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
235 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
236 clamping, MIPLOD, etc. This will work for up to 16 samplers.
239 if (Sampler >= GL_LIMITS(samplers)) {
240 FIXME("Trying to set the state of more samplers %ld than are supported %d by this openGL implementation\n", Sampler, GL_LIMITS(samplers));
243 VTRACE(("Activating appropriate texture state %ld\n", Sampler));
244 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
246 GLACTIVETEXTURE(Sampler);
248 /* Could we use bindTexture and then apply the states instead of GLACTIVETEXTURE */
249 } else if (Sampler > 0) {
250 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
254 /* TODO: change this to a lookup table
255 LOOKUP_TEXTURE_STATES lists all texture states that should be applied.
256 LOOKUP_CONTEXT_SATES list all context applicable states that can be applied
257 etc.... it's a lot cleaner, quicker and possibly easier to maintain than running a switch and setting a skip flag...
258 especially when there are a number of groups of states. */
260 TRACE("-----------------------> Updating the texture at Sampler %ld to have new texture state information\n", Sampler);
262 /* 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 */
263 #define APPLY_STATE(_state) IWineD3DDeviceImpl_ApplyTextureUnitState(iface, Sampler, _state)
264 /* these are the only two supported states that need to be applied */
265 APPLY_STATE(WINED3DTSS_TEXCOORDINDEX);
266 APPLY_STATE(WINED3DTSS_TEXTURETRANSFORMFLAGS);
267 #if 0 /* not supported at the moment */
268 APPLY_STATE(WINED3DTSS_BUMPENVMAT00);
269 APPLY_STATE(WINED3DTSS_BUMPENVMAT01);
270 APPLY_STATE(WINED3DTSS_BUMPENVMAT10);
271 APPLY_STATE(WINED3DTSS_BUMPENVMAT11);
272 APPLY_STATE(WINED3DTSS_BUMPENVLSCALE);
273 APPLY_STATE(WINED3DTSS_BUMPENVLOFFSET);
274 APPLY_STATE(WINED3DTSS_RESULTARG);
275 APPLY_STATE(WINED3DTSS_CONSTANT);
277 /* a quick sanity check in case someone forgot to update this function */
278 if (WINED3D_HIGHEST_TEXTURE_STATE > WINED3DTSS_CONSTANT) {
279 FIXME("(%p) : There are more texture states than expected, update device.c to match\n", This);
283 /* apply any sampler states that always need applying */
284 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
285 tmpvalue.d = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPMAPLODBIAS];
286 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
287 GL_TEXTURE_LOD_BIAS_EXT,
289 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
292 /* Note the D3DRS value applies to all textures, but GL has one
293 * per texture, so apply it now ready to be used!
295 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
296 /* Set the default alpha blend color */
297 glBlendColor(col[0], col[1], col[2], col[3]);
298 checkGLcall("glBlendColor");
300 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
301 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
302 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
304 /* TODO: NV_POINT_SPRITE */
305 if (GL_SUPPORT(ARB_POINT_SPRITE)) {
306 if (This->stateBlock->renderState[WINED3DRS_POINTSPRITEENABLE] != FALSE) {
307 /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
308 glDisable(GL_POINT_SMOOTH);
310 /* Centre the texture on the vertex */
311 VTRACE(("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n"));
312 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
314 VTRACE(("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n"));
315 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
316 checkGLcall("glTexEnvf(...)");
317 VTRACE(("glEnable( GL_POINT_SPRITE_ARB )\n"));
318 glEnable( GL_POINT_SPRITE_ARB );
319 checkGLcall("glEnable(...)");
321 VTRACE(("glDisable( GL_POINT_SPRITE_ARB )\n"));
322 glDisable( GL_POINT_SPRITE_ARB );
323 checkGLcall("glEnable(...)");
327 TRACE("-----------------------> Updated the texture at Sampler %ld to have new texture state information\n", Sampler);
330 /**********************************************************
331 * IUnknown parts follows
332 **********************************************************/
334 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
336 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
338 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
339 if (IsEqualGUID(riid, &IID_IUnknown)
340 || IsEqualGUID(riid, &IID_IWineD3DBase)
341 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
342 IUnknown_AddRef(iface);
347 return E_NOINTERFACE;
350 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
351 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
352 ULONG refCount = InterlockedIncrement(&This->ref);
354 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
358 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
359 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
360 ULONG refCount = InterlockedDecrement(&This->ref);
362 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
365 /* TODO: Clean up all the surfaces and textures! */
366 /* NOTE: You must release the parent if the object was created via a callback
367 ** ***************************/
369 /* Release the update stateblock */
370 if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){
371 if(This->updateStateBlock != This->stateBlock)
372 FIXME("(%p) Something's still holding the Update stateblock\n",This);
374 This->updateStateBlock = NULL;
375 { /* because were not doing proper internal refcounts releasing the primary state block
376 causes recursion with the extra checks in ResourceReleased, to avoid this we have
377 to set this->stateBlock = NULL; first */
378 IWineD3DStateBlock *stateBlock = (IWineD3DStateBlock *)This->stateBlock;
379 This->stateBlock = NULL;
381 /* Release the stateblock */
382 if(IWineD3DStateBlock_Release(stateBlock) > 0){
383 FIXME("(%p) Something's still holding the Update stateblock\n",This);
387 if (This->resources != NULL ) {
388 FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This);
389 dumpResources(This->resources);
393 IWineD3D_Release(This->wineD3D);
394 This->wineD3D = NULL;
395 HeapFree(GetProcessHeap(), 0, This);
396 TRACE("Freed device %p\n", This);
402 /**********************************************************
403 * IWineD3DDevice implementation follows
404 **********************************************************/
405 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
406 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
407 *pParent = This->parent;
408 IUnknown_AddRef(This->parent);
412 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
413 DWORD FVF, WINED3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
415 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
416 IWineD3DVertexBufferImpl *object;
417 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
418 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, WINED3DRTYPE_VERTEXBUFFER, Size)
421 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
422 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
426 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
427 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
432 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
433 WINED3DFORMAT Format, WINED3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
434 HANDLE *sharedHandle, IUnknown *parent) {
435 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
436 IWineD3DIndexBufferImpl *object;
437 TRACE("(%p) Creating index buffer\n", This);
439 /* Allocate the storage for the device */
440 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,WINED3DRTYPE_INDEXBUFFER, Length)
443 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
444 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
447 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
448 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
449 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
454 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
456 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
457 IWineD3DStateBlockImpl *object;
460 D3DCREATEOBJECTINSTANCE(object, StateBlock)
461 object->blockType = Type;
463 /* Special case - Used during initialization to produce a placeholder stateblock
464 so other functions called can update a state block */
465 if (Type == WINED3DSBT_INIT) {
466 /* Don't bother increasing the reference count otherwise a device will never
467 be freed due to circular dependencies */
471 /* Otherwise, might as well set the whole state block to the appropriate values */
472 if ( This->stateBlock != NULL) {
473 memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
475 memset(object->streamFreq, 1, sizeof(object->streamFreq));
478 /* Reset the ref and type after kludging it */
479 object->wineD3DDevice = This;
481 object->blockType = Type;
483 TRACE("Updating changed flags appropriate for type %d\n", Type);
485 if (Type == WINED3DSBT_ALL) {
487 TRACE("ALL => Pretend everything has changed\n");
488 memset(&object->changed, TRUE, sizeof(This->stateBlock->changed));
489 } else if (Type == WINED3DSBT_PIXELSTATE) {
491 TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
492 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
494 object->changed.pixelShader = TRUE;
496 /* Pixel Shader Constants */
497 for (i = 0; i < MAX_PSHADER_CONSTANTS; ++i) {
498 object->changed.pixelShaderConstants[i] = TRUE;
500 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
501 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
503 for (j = 0; j < GL_LIMITS(textures); j++) {
504 for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
505 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
508 for (j = 0 ; j < 16; j++) {
509 for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
511 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
515 } else if (Type == WINED3DSBT_VERTEXSTATE) {
517 TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
518 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
520 object->changed.vertexShader = TRUE;
522 /* Vertex Shader Constants */
523 for (i = 0; i < MAX_VSHADER_CONSTANTS; ++i) {
524 object->changed.vertexShaderConstants[i] = TRUE;
526 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
527 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
529 for (j = 0; j < GL_LIMITS(textures); j++) {
530 for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
531 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
534 for (j = 0 ; j < 16; j++){
535 for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
536 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
540 /* Duplicate light chain */
542 PLIGHTINFOEL *src = NULL;
543 PLIGHTINFOEL *dst = NULL;
544 PLIGHTINFOEL *newEl = NULL;
545 src = This->stateBlock->lights;
546 object->lights = NULL;
550 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
551 if (newEl == NULL) return WINED3DERR_OUTOFVIDEOMEMORY;
552 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
554 newEl->changed = TRUE;
555 newEl->enabledChanged = TRUE;
557 object->lights = newEl;
568 FIXME("Unrecognized state block type %d\n", Type);
571 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
576 /* ************************************
578 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
581 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
583 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.
585 ******************************** */
587 HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height, WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **ppSurface,WINED3DRESOURCETYPE Type, DWORD Usage, WINED3DPOOL Pool, WINED3DMULTISAMPLE_TYPE MultiSample ,DWORD MultisampleQuality, HANDLE* pSharedHandle, WINED3DSURFTYPE Impl, IUnknown *parent) {
588 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
589 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
590 unsigned int pow2Width, pow2Height;
591 unsigned int Size = 1;
592 TRACE("(%p) Create surface\n",This);
594 /** FIXME: Check ranges on the inputs are valid
597 * [in] Quality level. The valid range is between zero and one less than the level
598 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
599 * Passing a larger value returns the error WINED3DERR_INVALIDCALL. The MultisampleQuality
600 * values of paired render targets, depth stencil surfaces, and the MultiSample type
602 *******************************/
607 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
609 * If this flag is set, the contents of the depth stencil buffer will be
610 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
611 * with a different depth surface.
613 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
614 ***************************/
616 if(MultisampleQuality < 0) {
617 FIXME("Invalid multisample level %ld\n", MultisampleQuality);
618 return WINED3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
621 if(MultisampleQuality > 0) {
622 FIXME("MultisampleQuality set to %ld, substituting 0\n", MultisampleQuality);
623 MultisampleQuality=0;
626 /** FIXME: Check that the format is supported
628 *******************************/
630 /* Non-power2 support */
632 /* Find the nearest pow2 match */
633 pow2Width = pow2Height = 1;
634 while (pow2Width < Width) pow2Width <<= 1;
635 while (pow2Height < Height) pow2Height <<= 1;
637 if (pow2Width > Width || pow2Height > Height) {
638 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
639 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
640 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
641 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
642 This, Width, Height);
643 return WINED3DERR_NOTAVAILABLE;
647 /** Check against the maximum texture sizes supported by the video card **/
648 if (pow2Width > GL_LIMITS(texture_size) || pow2Height > GL_LIMITS(texture_size)) {
649 /* one of three options
650 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)
651 2: Set the texture to the maxium size (bad idea)
652 3: WARN and return WINED3DERR_NOTAVAILABLE;
654 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));
655 return WINED3DERR_NOTAVAILABLE;
660 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
661 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
663 *********************************/
664 if (WINED3DFMT_UNKNOWN == Format) {
666 } else if (Format == WINED3DFMT_DXT1) {
667 /* DXT1 is half byte per pixel */
668 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4)) >> 1;
670 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
671 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
672 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4));
674 Size = (pow2Width * D3DFmtGetBpp(This, Format)) * pow2Height;
677 /** Create and initialise the surface resource **/
678 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,WINED3DRTYPE_SURFACE, Size)
679 /* "Standalone" surface */
680 IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL);
682 object->currentDesc.Width = Width;
683 object->currentDesc.Height = Height;
684 object->currentDesc.MultiSampleType = MultiSample;
685 object->currentDesc.MultiSampleQuality = MultisampleQuality;
687 /* Setup some glformat defaults */
688 if (WINED3DFMT_UNKNOWN != Format) {
689 object->glDescription.glFormat = D3DFmt2GLFmt(This, object->resource.format);
690 object->glDescription.glFormatInternal = D3DFmt2GLIntFmt(This, object->resource.format);
691 object->glDescription.glType = D3DFmt2GLType(This, object->resource.format);
693 object->glDescription.glFormat = 0;
694 object->glDescription.glFormatInternal = 0;
695 object->glDescription.glType = 0;
698 object->glDescription.textureName = 0;
699 object->glDescription.level = Level;
700 object->glDescription.target = GL_TEXTURE_2D;
703 object->pow2Width = pow2Width;
704 object->pow2Height = pow2Height;
707 object->Flags = 0; /* We start without flags set */
708 object->Flags |= (pow2Width != Width || pow2Height != Height) ? SFLAG_NONPOW2 : 0;
709 object->Flags |= Discard ? SFLAG_DISCARD : 0;
710 object->Flags |= (WINED3DFMT_D16_LOCKABLE == Format) ? SFLAG_LOCKABLE : 0;
711 object->Flags |= Lockable ? SFLAG_LOCKABLE : 0;
714 if (WINED3DFMT_UNKNOWN != Format) {
715 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
716 object->pow2Size = (pow2Width * object->bytesPerPixel) * pow2Height;
718 object->bytesPerPixel = 0;
719 object->pow2Size = 0;
722 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
724 TRACE("Pool %d %d %d %d",Pool, WINED3DPOOL_DEFAULT, WINED3DPOOL_MANAGED, WINED3DPOOL_SYSTEMMEM);
726 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
727 * this function is too deap to need to care about things like this.
728 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
729 * ****************************************/
731 case WINED3DPOOL_SCRATCH:
732 if(Lockable == FALSE)
733 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
734 which are mutually exclusive, setting lockable to true\n");
737 case WINED3DPOOL_SYSTEMMEM:
738 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
739 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
740 case WINED3DPOOL_MANAGED:
741 if(Usage == WINED3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
742 Usage of DYNAMIC which are mutually exclusive, not doing \
743 anything just telling you.\n");
745 case WINED3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
746 if(!(Usage & WINED3DUSAGE_DYNAMIC) && !(Usage & WINED3DUSAGE_RENDERTARGET)
747 && !(Usage && WINED3DUSAGE_DEPTHSTENCIL ) && Lockable == TRUE)
748 FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
751 FIXME("(%p) Unknown pool %d\n", This, Pool);
755 if (Usage & WINED3DUSAGE_RENDERTARGET && Pool != WINED3DPOOL_DEFAULT) {
756 FIXME("Trying to create a render target that isn't in the default pool\n");
759 /* mark the texture as dirty so that it get's loaded first time around*/
760 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
761 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
762 This, Width, Height, Format, debug_d3dformat(Format),
763 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
768 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
769 DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
770 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
771 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
773 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
774 IWineD3DTextureImpl *object;
779 unsigned int pow2Width = Width;
780 unsigned int pow2Height = Height;
783 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) ....\n", This, Width, Height, Levels, Usage);
785 /* TODO: It should only be possible to create textures for formats
786 that are reported as supported */
787 if (WINED3DFMT_UNKNOWN >= Format) {
788 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
789 return WINED3DERR_INVALIDCALL;
792 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, WINED3DRTYPE_TEXTURE, 0);
793 D3DINITIALIZEBASETEXTURE(object->baseTexture);
794 object->width = Width;
795 object->height = Height;
797 /** Non-power2 support **/
798 /* Find the nearest pow2 match */
799 pow2Width = pow2Height = 1;
800 while (pow2Width < Width) pow2Width <<= 1;
801 while (pow2Height < Height) pow2Height <<= 1;
803 /** FIXME: add support for real non-power-two if it's provided by the video card **/
804 /* Precalculated scaling for 'faked' non power of two texture coords */
805 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
806 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
807 TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
809 /* Calculate levels for mip mapping */
811 TRACE("calculating levels %d\n", object->baseTexture.levels);
812 object->baseTexture.levels++;
815 while (tmpW > 1 || tmpH > 1) {
816 tmpW = max(1, tmpW >> 1);
817 tmpH = max(1, tmpH >> 1);
818 object->baseTexture.levels++;
820 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
823 /* Generate all the surfaces */
826 for (i = 0; i < object->baseTexture.levels; i++)
828 /* use the callback to create the texture surface */
829 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
830 if (hr!= WINED3D_OK) {
832 FIXME("Failed to create surface %p\n", object);
834 for (j = 0 ; j < i ; j++) {
835 IWineD3DSurface_Release(object->surfaces[j]);
837 /* heap free object */
838 HeapFree(GetProcessHeap(), 0, object);
844 IWineD3DSurface_SetContainer(object->surfaces[i], (IWineD3DBase *)object);
845 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
846 /* calculate the next mipmap level */
847 tmpW = max(1, tmpW >> 1);
848 tmpH = max(1, tmpH >> 1);
851 TRACE("(%p) : Created texture %p\n", This, object);
855 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
856 UINT Width, UINT Height, UINT Depth,
857 UINT Levels, DWORD Usage,
858 WINED3DFORMAT Format, WINED3DPOOL Pool,
859 IWineD3DVolumeTexture **ppVolumeTexture,
860 HANDLE *pSharedHandle, IUnknown *parent,
861 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
863 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
864 IWineD3DVolumeTextureImpl *object;
870 /* TODO: It should only be possible to create textures for formats
871 that are reported as supported */
872 if (WINED3DFMT_UNKNOWN >= Format) {
873 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
874 return WINED3DERR_INVALIDCALL;
877 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, WINED3DRTYPE_VOLUMETEXTURE, 0);
878 D3DINITIALIZEBASETEXTURE(object->baseTexture);
880 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
881 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
883 object->width = Width;
884 object->height = Height;
885 object->depth = Depth;
887 /* Calculate levels for mip mapping */
889 object->baseTexture.levels++;
893 while (tmpW > 1 || tmpH > 1 || tmpD > 1) {
894 tmpW = max(1, tmpW >> 1);
895 tmpH = max(1, tmpH >> 1);
896 tmpD = max(1, tmpD >> 1);
897 object->baseTexture.levels++;
899 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
902 /* Generate all the surfaces */
907 for (i = 0; i < object->baseTexture.levels; i++)
909 /* Create the volume */
910 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
911 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
913 /* Set it's container to this object */
914 IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)object);
916 /* calcualte the next mipmap level */
917 tmpW = max(1, tmpW >> 1);
918 tmpH = max(1, tmpH >> 1);
919 tmpD = max(1, tmpD >> 1);
922 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
923 TRACE("(%p) : Created volume texture %p\n", This, object);
927 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
928 UINT Width, UINT Height, UINT Depth,
930 WINED3DFORMAT Format, WINED3DPOOL Pool,
931 IWineD3DVolume** ppVolume,
932 HANDLE* pSharedHandle, IUnknown *parent) {
934 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
935 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
937 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, WINED3DRTYPE_VOLUME, ((Width * D3DFmtGetBpp(This, Format)) * Height * Depth))
939 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
940 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
942 object->currentDesc.Width = Width;
943 object->currentDesc.Height = Height;
944 object->currentDesc.Depth = Depth;
945 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
947 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
948 object->lockable = TRUE;
949 object->locked = FALSE;
950 memset(&object->lockedBox, 0, sizeof(WINED3DBOX));
951 object->dirty = TRUE;
953 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
956 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
957 UINT Levels, DWORD Usage,
958 WINED3DFORMAT Format, WINED3DPOOL Pool,
959 IWineD3DCubeTexture **ppCubeTexture,
960 HANDLE *pSharedHandle, IUnknown *parent,
961 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
963 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
964 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
968 unsigned int pow2EdgeLength = EdgeLength;
970 /* TODO: It should only be possible to create textures for formats
971 that are reported as supported */
972 if (WINED3DFMT_UNKNOWN >= Format) {
973 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
974 return WINED3DERR_INVALIDCALL;
977 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, WINED3DRTYPE_CUBETEXTURE, 0);
978 D3DINITIALIZEBASETEXTURE(object->baseTexture);
980 TRACE("(%p) Create Cube Texture\n", This);
982 /** Non-power2 support **/
984 /* Find the nearest pow2 match */
986 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
988 object->edgeLength = EdgeLength;
989 /* TODO: support for native non-power 2 */
990 /* Precalculated scaling for 'faked' non power of two texture coords */
991 object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
993 /* Calculate levels for mip mapping */
995 object->baseTexture.levels++;
998 tmpW = max(1, tmpW >> 1);
999 object->baseTexture.levels++;
1001 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1004 /* Generate all the surfaces */
1006 for (i = 0; i < object->baseTexture.levels; i++) {
1008 /* Create the 6 faces */
1009 for (j = 0; j < 6; j++) {
1011 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
1012 i /* Level */, &object->surfaces[j][i],pSharedHandle);
1014 if(hr!= WINED3D_OK) {
1018 for (l = 0; l < j; l++) {
1019 IWineD3DSurface_Release(object->surfaces[j][i]);
1021 for (k = 0; k < i; k++) {
1022 for (l = 0; l < 6; l++) {
1023 IWineD3DSurface_Release(object->surfaces[l][j]);
1027 FIXME("(%p) Failed to create surface\n",object);
1028 HeapFree(GetProcessHeap(),0,object);
1029 *ppCubeTexture = NULL;
1032 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IWineD3DBase *)object);
1033 TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1035 tmpW = max(1, tmpW >> 1);
1038 TRACE("(%p) : Created Cube Texture %p\n", This, object);
1039 *ppCubeTexture = (IWineD3DCubeTexture *) object;
1043 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1044 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1045 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1047 if (NULL == ppQuery) {
1048 /* Just a check to see if we support this type of query */
1049 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1051 case WINED3DQUERYTYPE_OCCLUSION:
1052 TRACE("(%p) occlusion query\n", This);
1053 if (GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY))
1056 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1058 case WINED3DQUERYTYPE_VCACHE:
1059 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1060 case WINED3DQUERYTYPE_VERTEXSTATS:
1061 case WINED3DQUERYTYPE_EVENT:
1062 case WINED3DQUERYTYPE_TIMESTAMP:
1063 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1064 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1065 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1066 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1067 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1068 case WINED3DQUERYTYPE_PIXELTIMINGS:
1069 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1070 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1072 FIXME("(%p) Unhandled query type %d\n", This, Type);
1077 D3DCREATEOBJECTINSTANCE(object, Query)
1078 object->type = Type;
1079 /* allocated the 'extended' data based on the type of query requested */
1081 case D3DQUERYTYPE_OCCLUSION:
1082 if(GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY)) {
1083 TRACE("(%p) Allocating data for an occlusion query\n", This);
1084 object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1087 case D3DQUERYTYPE_VCACHE:
1088 case D3DQUERYTYPE_RESOURCEMANAGER:
1089 case D3DQUERYTYPE_VERTEXSTATS:
1090 case D3DQUERYTYPE_EVENT:
1091 case D3DQUERYTYPE_TIMESTAMP:
1092 case D3DQUERYTYPE_TIMESTAMPDISJOINT:
1093 case D3DQUERYTYPE_TIMESTAMPFREQ:
1094 case D3DQUERYTYPE_PIPELINETIMINGS:
1095 case D3DQUERYTYPE_INTERFACETIMINGS:
1096 case D3DQUERYTYPE_VERTEXTIMINGS:
1097 case D3DQUERYTYPE_PIXELTIMINGS:
1098 case D3DQUERYTYPE_BANDWIDTHTIMINGS:
1099 case D3DQUERYTYPE_CACHEUTILIZATION:
1101 object->extendedData = 0;
1102 FIXME("(%p) Unhandled query type %d\n",This , Type);
1104 TRACE("(%p) : Created Query %p\n", This, object);
1108 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1109 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1111 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1112 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1113 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1116 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1118 XVisualInfo template;
1119 GLXContext oldContext;
1120 Drawable oldDrawable;
1121 HRESULT hr = WINED3D_OK;
1123 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1125 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1126 * does a device hold a reference to a swap chain giving them a lifetime of the device
1127 * or does the swap chain notify the device of its destruction.
1128 *******************************/
1130 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1132 /* Initialize other useful values */
1133 object->presentParms.BackBufferCount = 1; /* TODO:? support for gl_aux buffers */
1135 /*********************
1136 * Lookup the window Handle and the relating X window handle
1137 ********************/
1139 /* Setup hwnd we are using, plus which display this equates to */
1140 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1141 if (!object->win_handle) {
1142 object->win_handle = This->createParms.hFocusWindow;
1145 object->win_handle = GetAncestor(object->win_handle, GA_ROOT);
1146 if ( !( object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window") ) ) {
1147 ERR("Can't get drawable (window), HWND:%p doesn't have the property __wine_x11_whole_window\n", object->win_handle);
1148 return WINED3DERR_NOTAVAILABLE;
1150 hDc = GetDC(object->win_handle);
1151 object->display = get_display(hDc);
1152 ReleaseDC(object->win_handle, hDc);
1153 TRACE("Using a display of %p %p\n", object->display, hDc);
1155 if (NULL == object->display || NULL == hDc) {
1156 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1157 return WINED3DERR_NOTAVAILABLE;
1160 if (object->win == 0) {
1161 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1162 return WINED3DERR_NOTAVAILABLE;
1165 * Create an opengl context for the display visual
1166 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1167 * use different properties after that point in time. FIXME: How to handle when requested format
1168 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1169 * it chooses is identical to the one already being used!
1170 **********************************/
1172 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1175 /* Create a new context for this swapchain */
1176 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1177 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1178 (or the best possible if none is requested) */
1179 TRACE("Found x visual ID : %ld\n", template.visualid);
1181 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1182 if (NULL == object->visInfo) {
1183 ERR("cannot really get XVisual\n");
1185 return WINED3DERR_NOTAVAILABLE;
1188 /* Write out some debug info about the visual/s */
1189 TRACE("Using x visual ID : %ld\n", template.visualid);
1190 TRACE(" visual info: %p\n", object->visInfo);
1191 TRACE(" num items : %d\n", num);
1192 for (n = 0;n < num; n++) {
1193 TRACE("=====item=====: %d\n", n + 1);
1194 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1195 TRACE(" screen : %d\n", object->visInfo[n].screen);
1196 TRACE(" depth : %u\n", object->visInfo[n].depth);
1197 TRACE(" class : %d\n", object->visInfo[n].class);
1198 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1199 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1200 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1201 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1202 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1203 /* log some extra glx info */
1204 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1205 TRACE(" gl_aux_buffers : %d\n", value);
1206 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1207 TRACE(" gl_buffer_size : %d\n", value);
1208 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1209 TRACE(" gl_red_size : %d\n", value);
1210 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1211 TRACE(" gl_green_size : %d\n", value);
1212 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1213 TRACE(" gl_blue_size : %d\n", value);
1214 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1215 TRACE(" gl_alpha_size : %d\n", value);
1216 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1217 TRACE(" gl_depth_size : %d\n", value);
1218 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1219 TRACE(" gl_stencil_size : %d\n", value);
1221 /* Now choose a simila visual ID*/
1223 #ifdef USE_CONTEXT_MANAGER
1225 /** TODO: use a context mamager **/
1229 IWineD3DSwapChain *implSwapChain;
1230 if (WINED3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1231 /* The first time around we create the context that is shared with all other swapchains and render targets */
1232 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1233 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1236 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1237 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1238 /* and create a new context with the implicit swapchains context as the shared context */
1239 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1240 IWineD3DSwapChain_Release(implSwapChain);
1245 XFree(object->visInfo);
1246 object->visInfo = NULL;
1248 if (NULL == object->glCtx) {
1249 ERR("cannot create glxContext\n");
1251 return WINED3DERR_NOTAVAILABLE;
1255 if (object->glCtx == NULL) {
1256 ERR("Error in context creation !\n");
1257 return WINED3DERR_INVALIDCALL;
1259 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1260 object->win_handle, object->glCtx, object->win, object->visInfo);
1263 /*********************
1264 * Windowed / Fullscreen
1265 *******************/
1268 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1269 * so we should really check to see if there is a fullscreen swapchain already
1270 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1271 **************************************/
1273 if (!*(pPresentationParameters->Windowed)) {
1279 /* Get info on the current display setup */
1280 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1281 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1284 /* Change the display settings */
1285 memset(&devmode, 0, sizeof(DEVMODEW));
1286 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1287 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1288 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1289 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1290 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1291 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1293 /* Make popup window */
1294 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1295 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1296 *(pPresentationParameters->BackBufferWidth),
1297 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1303 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1304 * then the corresponding dimension of the client area of the hDeviceWindow
1305 * (or the focus window, if hDeviceWindow is NULL) is taken.
1306 **********************/
1308 if (*(pPresentationParameters->Windowed) &&
1309 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1310 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1313 GetClientRect(object->win_handle, &Rect);
1315 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1316 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1317 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1319 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1320 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1321 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1325 /*********************
1326 * finish off parameter initialization
1327 *******************/
1329 /* Put the correct figures in the presentation parameters */
1330 TRACE("Coppying accross presentaion paraneters\n");
1331 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1332 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1333 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1334 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1335 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1336 object->presentParms.MultiSampleQuality = NULL == pPresentationParameters->MultiSampleQuality ? 0 : *(pPresentationParameters->MultiSampleQuality);
1337 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1338 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1339 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1340 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1341 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1342 object->presentParms.Flags = *(pPresentationParameters->Flags);
1343 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1344 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1347 /*********************
1348 * Create the back, front and stencil buffers
1349 *******************/
1350 TRACE("calling rendertarget CB\n");
1351 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1352 object->presentParms.BackBufferWidth,
1353 object->presentParms.BackBufferHeight,
1354 object->presentParms.BackBufferFormat,
1355 object->presentParms.MultiSampleType,
1356 object->presentParms.MultiSampleQuality,
1357 TRUE /* Lockable */,
1358 &object->frontBuffer,
1359 NULL /* pShared (always null)*/);
1360 if (object->frontBuffer != NULL)
1361 IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
1362 TRACE("calling rendertarget CB\n");
1363 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1364 object->presentParms.BackBufferWidth,
1365 object->presentParms.BackBufferHeight,
1366 object->presentParms.BackBufferFormat,
1367 object->presentParms.MultiSampleType,
1368 object->presentParms.MultiSampleQuality,
1369 TRUE /* Lockable */,
1370 &object->backBuffer,
1371 NULL /* pShared (always null)*/);
1372 if (object->backBuffer != NULL)
1373 IWineD3DSurface_SetContainer(object->backBuffer, (IWineD3DBase *)object);
1375 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1376 if (pPresentationParameters->EnableAutoDepthStencil) {
1377 TRACE("Creating depth stencil buffer\n");
1378 if (This->depthStencilBuffer == NULL ) {
1379 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1380 object->presentParms.BackBufferWidth,
1381 object->presentParms.BackBufferHeight,
1382 object->presentParms.AutoDepthStencilFormat,
1383 object->presentParms.MultiSampleType,
1384 object->presentParms.MultiSampleQuality,
1385 FALSE /* FIXME: Discard */,
1386 &This->depthStencilBuffer,
1387 NULL /* pShared (always null)*/ );
1388 if (This->depthStencilBuffer != NULL)
1389 IWineD3DSurface_SetContainer(This->depthStencilBuffer, 0);
1392 /** TODO: A check on width, height and multisample types
1393 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1394 ****************************/
1395 object->wantsDepthStencilBuffer = TRUE;
1397 object->wantsDepthStencilBuffer = FALSE;
1400 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1403 /*********************
1404 * init the default renderTarget management
1405 *******************/
1406 object->drawable = object->win;
1407 object->render_ctx = object->glCtx;
1409 if (hr == WINED3D_OK) {
1410 /*********************
1411 * Setup some defaults and clear down the buffers
1412 *******************/
1414 /** save current context and drawable **/
1415 oldContext = glXGetCurrentContext();
1416 oldDrawable = glXGetCurrentDrawable();
1418 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1419 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1420 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1422 checkGLcall("glXMakeCurrent");
1424 TRACE("Setting up the screen\n");
1425 /* Clear the screen */
1426 glClearColor(1.0, 0.0, 0.0, 0.0);
1427 checkGLcall("glClearColor");
1430 glClearStencil(0xffff);
1432 checkGLcall("glClear");
1434 glColor3f(1.0, 1.0, 1.0);
1435 checkGLcall("glColor3f");
1437 glEnable(GL_LIGHTING);
1438 checkGLcall("glEnable");
1440 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1441 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1443 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1444 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1446 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1447 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1449 /* switch back to the original context (if there was one)*/
1450 if (This->swapchains != NULL) {
1451 /** TODO: restore the context and drawable **/
1452 glXMakeCurrent(object->display, oldDrawable, oldContext);
1457 { /* Finally add the swapchain to the end of the devices' swapchain list */
1458 SwapChainList **nextSwapchain;
1459 nextSwapchain = &This->swapchains;
1460 while (*nextSwapchain != NULL) {
1461 nextSwapchain = &((*nextSwapchain)->next);
1463 (*nextSwapchain) = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->swapchains));
1464 (*nextSwapchain)->swapchain = (IWineD3DSwapChain *)object;
1466 TRACE("Set swapchain to %p\n", object);
1467 } else { /* something went wrong so clean up */
1468 IUnknown* bufferParent;
1469 if (object->frontBuffer) {
1471 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1472 IUnknown_Release(bufferParent); /* once for the get parent */
1473 if (IUnknown_Release(bufferParent) > 0) {
1474 FIXME("(%p) Something's still holding the front buffer\n",This);
1477 if (object->backBuffer) {
1478 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1479 IUnknown_Release(bufferParent); /* once for the get parent */
1480 if (IUnknown_Release(bufferParent) > 0) {
1481 FIXME("(%p) Something's still holding the back buffer\n",This);
1484 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1485 /* Clean up the context */
1486 /* check that we are the current context first (we shouldn't be though!) */
1487 if (object->glCtx != 0) {
1488 if(glXGetCurrentContext() == object->glCtx) {
1489 glXMakeCurrent(object->display, None, NULL);
1491 glXDestroyContext(object->display, object->glCtx);
1493 HeapFree(GetProcessHeap(), 0, object);
1500 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1501 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1502 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1503 unsigned int numberOfSwapChains = 0;
1504 SwapChainList *swapchain;
1506 swapchain = This->swapchains;
1507 /* itterate through the list to get a count */
1508 while (swapchain != NULL) {
1509 swapchain = swapchain->next;
1510 numberOfSwapChains++;
1513 TRACE("(%p) returning %d\n", This, numberOfSwapChains);
1514 return numberOfSwapChains;
1517 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1518 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1519 SwapChainList *swapchain;
1521 HRESULT hr = WINED3DERR_INVALIDCALL;
1522 swapchain = This->swapchains;
1523 TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1526 TRACE("(%p) Finding swapchain %d\n", This, iSwapChain);
1527 while (i > 0 && swapchain != NULL) {
1528 swapchain = swapchain->next;
1533 FIXME("(%p) Unable to find swapchain %d\n", This, iSwapChain);
1535 } else if (swapchain != NULL) {
1536 /** TODO: move off to a linkesList implementation **/
1537 *pSwapChain = swapchain->swapchain;
1538 IWineD3DSwapChain_AddRef(*pSwapChain);
1542 TRACE("(%p) returning %p\n", This, *pSwapChain);
1547 * Vertex Declaration
1549 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1550 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1551 IWineD3DVertexDeclarationImpl *object = NULL;
1552 HRESULT hr = WINED3D_OK;
1553 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1554 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1557 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1562 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1563 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pDeclaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1564 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1565 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1566 HRESULT hr = WINED3D_OK;
1567 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1568 object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins;
1570 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1572 /* If a vertex declaration has been passed, save it to the vertex shader, this affects d3d8 only. */
1573 /* Further it needs to be set before calling SetFunction as SetFunction needs the declaration. */
1574 if (pDeclaration != NULL) {
1575 IWineD3DVertexDeclaration *vertexDeclaration;
1576 hr = IWineD3DDevice_CreateVertexDeclaration(iface, pDeclaration, &vertexDeclaration ,NULL);
1577 if (WINED3D_OK == hr) {
1578 TRACE("(%p) : Setting vertex declaration to %p\n", This, vertexDeclaration);
1579 object->vertexDeclaration = vertexDeclaration;
1581 FIXME("(%p) : Failed to set the declaration, returning WINED3DERR_INVALIDCALL\n", iface);
1582 IWineD3DVertexShader_Release(*ppVertexShader);
1583 return WINED3DERR_INVALIDCALL;
1587 hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1589 if (WINED3D_OK != hr) {
1590 FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface);
1591 IWineD3DVertexShader_Release(*ppVertexShader);
1592 return WINED3DERR_INVALIDCALL;
1595 #if 0 /* TODO: In D3D* SVP is atatched to the shader, in D3D9 it's attached to the device and isn't stored in the stateblock. */
1596 if(Usage == WINED3DUSAGE_SOFTWAREVERTEXPROCESSING) {
1607 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
1608 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1609 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1610 HRESULT hr = WINED3D_OK;
1612 D3DCREATEOBJECTINSTANCE(object, PixelShader)
1613 object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins;
1614 hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
1615 if (WINED3D_OK == hr) {
1616 TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
1618 WARN("(%p) : Failed to create pixel shader\n", This);
1624 HRESULT WINAPI IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice *iface, DWORD Flags, PALETTEENTRY *PalEnt, IWineD3DPalette **Palette, IUnknown *Parent) {
1625 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1626 IWineD3DPaletteImpl *object;
1628 TRACE("(%p)->(%lx, %p, %p, %p)\n", This, Flags, PalEnt, Palette, Parent);
1630 /* Create the new object */
1631 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DPaletteImpl));
1633 ERR("Out of memory when allocating memory for a IWineD3DPalette implementation\n");
1634 return E_OUTOFMEMORY;
1637 object->lpVtbl = &IWineD3DPalette_Vtbl;
1639 object->Flags = Flags;
1640 object->parent = Parent;
1641 object->wineD3DDevice = This;
1642 object->palNumEntries = IWineD3DPaletteImpl_Size(Flags);
1644 object->hpal = CreatePalette((const LOGPALETTE*)&(object->palVersion));
1647 HeapFree( GetProcessHeap(), 0, object);
1648 return E_OUTOFMEMORY;
1651 hr = IWineD3DPalette_SetEntries((IWineD3DPalette *) object, 0, 0, IWineD3DPaletteImpl_Size(Flags), PalEnt);
1653 IWineD3DPalette_Release((IWineD3DPalette *) object);
1657 *Palette = (IWineD3DPalette *) object;
1662 HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) {
1663 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1664 IWineD3DSwapChainImpl *swapchain;
1666 TRACE("(%p)->(%p,%p)\n", This, pPresentationParameters, D3DCB_CreateAdditionalSwapChain);
1667 if(This->d3d_initialized) return WINED3DERR_INVALIDCALL;
1669 /* TODO: Test if OpenGL is compiled in and loaded */
1671 /* Setup the implicit swapchain */
1672 TRACE("Creating implicit swapchain\n");
1673 if (D3D_OK != D3DCB_CreateAdditionalSwapChain((IUnknown *) This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain) || swapchain == NULL) {
1674 WARN("Failed to create implicit swapchain\n");
1675 return WINED3DERR_INVALIDCALL;
1678 if(swapchain->backBuffer) {
1679 TRACE("Setting rendertarget to %p\n", swapchain->backBuffer);
1680 This->renderTarget = swapchain->backBuffer;
1683 TRACE("Setting rendertarget to %p\n", swapchain->frontBuffer);
1684 This->renderTarget = swapchain->frontBuffer;
1686 IWineD3DSurface_AddRef(This->renderTarget);
1687 /* Depth Stencil support */
1688 This->stencilBufferTarget = This->depthStencilBuffer;
1689 if (NULL != This->stencilBufferTarget) {
1690 IWineD3DSurface_AddRef(This->stencilBufferTarget);
1693 /* Set up some starting GL setup */
1696 * Initialize openGL extension related variables
1697 * with Default values
1700 ((IWineD3DImpl *) This->wineD3D)->isGLInfoValid = IWineD3DImpl_FillGLCaps( &((IWineD3DImpl *) This->wineD3D)->gl_info, swapchain->display);
1701 /* Setup all the devices defaults */
1702 IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)This->stateBlock);
1704 IWineD3DImpl_CheckGraphicsMemory();
1708 { /* Set a default viewport */
1712 vp.Width = *(pPresentationParameters->BackBufferWidth);
1713 vp.Height = *(pPresentationParameters->BackBufferHeight);
1716 IWineD3DDevice_SetViewport((IWineD3DDevice *)This, &vp);
1720 /* Initialize the current view state */
1721 This->modelview_valid = 1;
1722 This->proj_valid = 0;
1723 This->view_ident = 1;
1724 This->last_was_rhw = 0;
1725 glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights);
1726 TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This, This);
1728 /* Clear the screen */
1729 IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
1731 This->d3d_initialized = TRUE;
1735 HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface) {
1736 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1738 IUnknown* stencilBufferParent;
1739 IUnknown* swapChainParent;
1740 SwapChainList *nextSwapchain;
1741 TRACE("(%p)\n", This);
1743 if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL;
1745 for(texstage = 0; texstage < GL_LIMITS(textures); texstage++) {
1746 IWineD3DDevice_SetTexture(iface, texstage, NULL);
1749 /* NOTE: You must release the parent if the object was created via a callback
1750 ** ***************************/
1751 /* Release all of the swapchains, except the implicit swapchain */
1753 /* NOTE: Don't release swapchain 0 here, it's 'special' */
1754 TRACE("Finding implicit swapchain\n");
1755 nextSwapchain = This->swapchains;
1756 if (nextSwapchain != NULL) {
1757 nextSwapchain = nextSwapchain->next;
1759 WARN("Expected to find the implicit swapchain\n");
1762 TRACE("Releasing swapchains. nextSwapchain = %p\n", nextSwapchain);
1763 /* release all the other swapchains */
1764 while (nextSwapchain != NULL) {
1765 SwapChainList *prevSwapchain = nextSwapchain;
1766 nextSwapchain = nextSwapchain->next;
1767 TRACE("Releasing swapchain %p\n", prevSwapchain->swapchain);
1768 IWineD3DSwapChain_Release(prevSwapchain->swapchain);
1769 /* NOTE: no need to free the list element, it will be done by the release callback
1770 HeapFree(GetProcessHeap(), 0, prevSwapchain); */
1772 /* Release the buffers (with sanity checks)*/
1773 TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget);
1774 if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
1775 if(This->depthStencilBuffer != This->stencilBufferTarget)
1776 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
1778 This->stencilBufferTarget = NULL;
1780 TRACE("Releasing the render target at %p\n", This->renderTarget);
1781 if(IWineD3DSurface_Release(This->renderTarget) >0){
1782 /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
1784 TRACE("Setting rendertarget to NULL\n");
1785 This->renderTarget = NULL;
1787 IWineD3DSurface_GetParent(This->depthStencilBuffer, &stencilBufferParent);
1788 IUnknown_Release(stencilBufferParent); /* once for the get parent */
1789 if(IUnknown_Release(stencilBufferParent) >0){ /* the second time for when it was created */
1790 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
1792 This->depthStencilBuffer = NULL;
1794 TRACE("Releasing the implicit swapchain\n");
1795 if (This->swapchains != NULL) {
1796 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
1797 IWineD3DSwapChain_GetParent(This->swapchains->swapchain, &swapChainParent);
1798 IUnknown_Release(swapChainParent); /* once for the get parent */
1799 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
1800 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
1803 This->swapchains = NULL;
1805 This->d3d_initialized = FALSE;
1809 HRESULT WINAPI IWineD3DDeviceImpl_EnumDisplayModes(IWineD3DDevice *iface, DWORD Flags, UINT Width, UINT Height, WINED3DFORMAT pixelformat, LPVOID context, D3DCB_ENUMDISPLAYMODESCALLBACK callback) {
1810 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1815 TRACE("(%p)->(%lx,%d,%d,%d,%p,%p)\n", This, Flags, Width, Height, pixelformat, context, callback);
1817 for (i = 0; EnumDisplaySettingsExW(NULL, i, &DevModeW, 0); i++) {
1818 /* Ignore some modes if a description was passed */
1819 if ( (Width > 0) && (Width != DevModeW.dmPelsWidth)) continue;
1820 if ( (Height > 0) && (Height != DevModeW.dmPelsHeight)) continue;
1821 if ( (pixelformat != WINED3DFMT_UNKNOWN) && ( D3DFmtGetBpp(NULL, pixelformat) != DevModeW.dmBitsPerPel) ) continue;
1823 TRACE("Enumerating %ldx%ld@%s\n", DevModeW.dmPelsWidth, DevModeW.dmPelsHeight, debug_d3dformat(pixelformat_for_depth(DevModeW.dmBitsPerPel)));
1825 if (callback((IUnknown *) This, (UINT) DevModeW.dmPelsWidth, (UINT) DevModeW.dmPelsHeight, pixelformat_for_depth(DevModeW.dmBitsPerPel), 60.0, context) == DDENUMRET_CANCEL)
1832 HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
1833 FIXME("This call is a d3d7 merge stub. It will be implemented later\n");
1834 return WINED3DERR_INVALIDCALL;
1837 HRESULT WINAPI IWineD3DDeviceImpl_EnumZBufferFormats(IWineD3DDevice *iface, D3DCB_ENUMPIXELFORMATS Callback, void *Context) {
1838 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1841 WINED3DFORMAT FormatList[] = {
1848 WINED3DFMT_UNKNOWN /* Terminate the list */
1851 TRACE("(%p)->(%p,%p)\n", This, Callback, Context);
1853 while(FormatList[i] != WINED3DFMT_UNKNOWN) {
1854 TRACE("Enumerating %s\n", debug_d3dformat(FormatList[i]));
1855 ret = Callback((IUnknown *) This, FormatList[i], Context);
1856 if(ret != DDENUMRET_OK) {
1857 TRACE("Enumeration cancelled by Application\n");
1863 TRACE("End of Enumeration\n");
1868 HRESULT WINAPI IWineD3DDeviceImpl_EnumTextureFormats(IWineD3DDevice *iface, D3DCB_ENUMPIXELFORMATS Callback, void *Context) {
1869 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1874 * WINED3DFMT_A1R5G5B5 needs to be the first 16 bit format, as some dumb apps depend on this
1876 * Do not enumerate RGBA pixel formats: "some games choose the first 16 bit texture format
1877 * with alpha they find enumerated, others the last one. And both want to have the ARGB one."
1878 * But WineD3D doesn't support RGBA formats anyway...
1881 WINED3DFORMAT FormatList[] = {
1883 WINED3DFMT_A8R8G8B8,
1884 WINED3DFMT_X8R8G8B8,
1888 WINED3DFMT_A1R5G5B5,
1889 WINED3DFMT_A4R4G4B4,
1891 WINED3DFMT_X1R5G5B5,
1899 /* Terminate the list */
1903 TRACE("(%p)->(%p,%p)\n", This, Callback, Context);
1905 while(FormatList[i] != WINED3DFMT_UNKNOWN) {
1906 TRACE("Enumerating %s\n", debug_d3dformat(FormatList[i]));
1907 ret = Callback((IUnknown *) This, FormatList[i], Context);
1908 if(ret != DDENUMRET_OK) {
1909 TRACE("Enumeration cancelled by Application\n");
1915 TRACE("End of Enumeration\n");
1920 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
1921 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1922 *ppD3D= This->wineD3D;
1923 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1924 IWineD3D_AddRef(*ppD3D);
1928 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1929 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1930 * Into the video ram as possible and seeing how many fit
1931 * you can also get the correct initial value from via X and ATI's driver
1932 *******************/
1933 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1934 static BOOL showfixmes = TRUE;
1936 FIXME("(%p) : stub, emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1937 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1940 TRACE("(%p) : emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1941 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1942 /* videomemory is simulated videomemory + AGP memory left */
1943 return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1951 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1952 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1953 HRESULT hr = WINED3D_OK;
1955 /* Update the current state block */
1956 This->updateStateBlock->fvf = fvf;
1957 This->updateStateBlock->changed.fvf = TRUE;
1958 This->updateStateBlock->set.fvf = TRUE;
1960 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1963 /* clear down the vertex declaration
1964 NOTE: Axis and Allies doesn't work properly otherwise
1965 (may be a stateblock problem though!)
1967 hr = IWineD3DDevice_SetVertexDeclaration(iface, NULL);
1974 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1975 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1976 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1977 *pfvf = This->stateBlock->fvf;
1982 * Get / Set Stream Source
1984 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1985 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1986 IWineD3DVertexBuffer *oldSrc;
1988 /**TODO: instance and index data, see
1989 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1991 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
1994 /* D3d9 only, but shouldn't hurt d3d8 */
1997 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1999 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2000 FIXME("stream index data not supported\n");
2002 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2003 FIXME("stream instance data not supported\n");
2007 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2009 if (StreamNumber >= MAX_STREAMS) {
2010 WARN("Stream out of range %d\n", StreamNumber);
2011 return WINED3DERR_INVALIDCALL;
2014 oldSrc = This->stateBlock->streamSource[StreamNumber];
2015 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
2017 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
2018 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
2019 This->updateStateBlock->streamStride[StreamNumber] = Stride;
2020 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
2021 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
2022 This->updateStateBlock->streamFlags[StreamNumber] = streamFlags;
2024 /* Handle recording of state blocks */
2025 if (This->isRecordingState) {
2026 TRACE("Recording... not performing anything\n");
2030 /* Not recording... */
2031 /* Need to do a getParent and pass the reffs up */
2032 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
2033 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
2034 so for now, just count internally */
2035 if (pStreamData != NULL) {
2036 IWineD3DVertexBuffer_AddRef(pStreamData);
2038 if (oldSrc != NULL) {
2039 IWineD3DVertexBuffer_Release(oldSrc);
2045 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
2046 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2049 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
2050 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
2053 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2055 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2056 FIXME("stream index data not supported\n");
2058 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2059 FIXME("stream instance data not supported\n");
2063 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2065 if (StreamNumber >= MAX_STREAMS) {
2066 WARN("Stream out of range %d\n", StreamNumber);
2067 return WINED3DERR_INVALIDCALL;
2069 *pStream = This->stateBlock->streamSource[StreamNumber];
2070 *pStride = This->stateBlock->streamStride[StreamNumber];
2071 *pOffset = This->stateBlock->streamOffset[StreamNumber];
2073 if (*pStream == NULL) {
2074 FIXME("Attempting to get an empty stream %d, returning WINED3DERR_INVALIDCALL\n", StreamNumber);
2075 return WINED3DERR_INVALIDCALL;
2078 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
2082 /*Should be quite easy, just an extension of vertexdata
2084 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2086 The divider is a bit odd though
2088 VertexOffset = StartVertex / Divider * StreamStride +
2089 VertexIndex / Divider * StreamStride + StreamOffset
2092 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
2093 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2095 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
2096 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (D3DSTREAMSOURCE_INSTANCEDATA | D3DSTREAMSOURCE_INDEXEDDATA );
2098 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
2099 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
2100 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
2102 if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
2103 FIXME("Stream indexing not fully supported\n");
2109 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
2110 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2112 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
2113 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
2115 TRACE("(%p) : returning %d\n", This, *Divider);
2121 * Get / Set & Multiply Transform
2123 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
2124 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2126 /* Most of this routine, comments included copied from ddraw tree initially: */
2127 TRACE("(%p) : Transform State=%d\n", This, d3dts);
2129 /* Handle recording of state blocks */
2130 if (This->isRecordingState) {
2131 TRACE("Recording... not performing anything\n");
2132 This->updateStateBlock->changed.transform[d3dts] = TRUE;
2133 This->updateStateBlock->set.transform[d3dts] = TRUE;
2134 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
2139 * If the new matrix is the same as the current one,
2140 * we cut off any further processing. this seems to be a reasonable
2141 * optimization because as was noticed, some apps (warcraft3 for example)
2142 * tend towards setting the same matrix repeatedly for some reason.
2144 * From here on we assume that the new matrix is different, wherever it matters.
2146 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
2147 TRACE("The app is setting the same matrix over again\n");
2150 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
2154 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2155 where ViewMat = Camera space, WorldMat = world space.
2157 In OpenGL, camera and world space is combined into GL_MODELVIEW
2158 matrix. The Projection matrix stay projection matrix.
2161 /* Capture the times we can just ignore the change for now */
2162 if (d3dts == D3DTS_WORLDMATRIX(0)) {
2163 This->modelview_valid = FALSE;
2166 } else if (d3dts == D3DTS_PROJECTION) {
2167 This->proj_valid = FALSE;
2170 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
2171 /* Indexed Vertex Blending Matrices 256 -> 511 */
2172 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
2173 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
2177 /* Now we really are going to have to change a matrix */
2180 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
2181 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
2182 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
2185 /* If we are changing the View matrix, reset the light and clipping planes to the new view
2186 * NOTE: We have to reset the positions even if the light/plane is not currently
2187 * enabled, since the call to enable it will not reset the position.
2188 * NOTE2: Apparently texture transforms do NOT need reapplying
2191 PLIGHTINFOEL *lightChain = NULL;
2192 This->modelview_valid = FALSE;
2193 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
2195 glMatrixMode(GL_MODELVIEW);
2196 checkGLcall("glMatrixMode(GL_MODELVIEW)");
2198 glLoadMatrixf((float *)lpmatrix);
2199 checkGLcall("glLoadMatrixf(...)");
2202 lightChain = This->stateBlock->lights;
2203 while (lightChain && lightChain->glIndex != -1) {
2204 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
2205 checkGLcall("glLightfv posn");
2206 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
2207 checkGLcall("glLightfv dirn");
2208 lightChain = lightChain->next;
2211 /* Reset Clipping Planes if clipping is enabled */
2212 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2213 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
2214 checkGLcall("glClipPlane");
2218 } else { /* What was requested!?? */
2219 WARN("invalid matrix specified: %i\n", d3dts);
2222 /* Release lock, all done */
2227 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
2228 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2229 TRACE("(%p) : for Transform State %d\n", This, State);
2230 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
2234 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
2235 D3DMATRIX *mat = NULL;
2238 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2239 * below means it will be recorded in a state block change, but it
2240 * works regardless where it is recorded.
2241 * If this is found to be wrong, change to StateBlock.
2243 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2244 TRACE("(%p) : For state %u\n", This, State);
2246 if (State < HIGHEST_TRANSFORMSTATE)
2248 mat = &This->updateStateBlock->transforms[State];
2250 FIXME("Unhandled transform state!!\n");
2253 /* Copied from ddraw code: */
2254 temp.u.s._11 = (mat->u.s._11 * pMatrix->u.s._11) + (mat->u.s._21 * pMatrix->u.s._12) +
2255 (mat->u.s._31 * pMatrix->u.s._13) + (mat->u.s._41 * pMatrix->u.s._14);
2256 temp.u.s._21 = (mat->u.s._11 * pMatrix->u.s._21) + (mat->u.s._21 * pMatrix->u.s._22) +
2257 (mat->u.s._31 * pMatrix->u.s._23) + (mat->u.s._41 * pMatrix->u.s._24);
2258 temp.u.s._31 = (mat->u.s._11 * pMatrix->u.s._31) + (mat->u.s._21 * pMatrix->u.s._32) +
2259 (mat->u.s._31 * pMatrix->u.s._33) + (mat->u.s._41 * pMatrix->u.s._34);
2260 temp.u.s._41 = (mat->u.s._11 * pMatrix->u.s._41) + (mat->u.s._21 * pMatrix->u.s._42) +
2261 (mat->u.s._31 * pMatrix->u.s._43) + (mat->u.s._41 * pMatrix->u.s._44);
2263 temp.u.s._12 = (mat->u.s._12 * pMatrix->u.s._11) + (mat->u.s._22 * pMatrix->u.s._12) +
2264 (mat->u.s._32 * pMatrix->u.s._13) + (mat->u.s._42 * pMatrix->u.s._14);
2265 temp.u.s._22 = (mat->u.s._12 * pMatrix->u.s._21) + (mat->u.s._22 * pMatrix->u.s._22) +
2266 (mat->u.s._32 * pMatrix->u.s._23) + (mat->u.s._42 * pMatrix->u.s._24);
2267 temp.u.s._32 = (mat->u.s._12 * pMatrix->u.s._31) + (mat->u.s._22 * pMatrix->u.s._32) +
2268 (mat->u.s._32 * pMatrix->u.s._33) + (mat->u.s._42 * pMatrix->u.s._34);
2269 temp.u.s._42 = (mat->u.s._12 * pMatrix->u.s._41) + (mat->u.s._22 * pMatrix->u.s._42) +
2270 (mat->u.s._32 * pMatrix->u.s._43) + (mat->u.s._42 * pMatrix->u.s._44);
2272 temp.u.s._13 = (mat->u.s._13 * pMatrix->u.s._11) + (mat->u.s._23 * pMatrix->u.s._12) +
2273 (mat->u.s._33 * pMatrix->u.s._13) + (mat->u.s._43 * pMatrix->u.s._14);
2274 temp.u.s._23 = (mat->u.s._13 * pMatrix->u.s._21) + (mat->u.s._23 * pMatrix->u.s._22) +
2275 (mat->u.s._33 * pMatrix->u.s._23) + (mat->u.s._43 * pMatrix->u.s._24);
2276 temp.u.s._33 = (mat->u.s._13 * pMatrix->u.s._31) + (mat->u.s._23 * pMatrix->u.s._32) +
2277 (mat->u.s._33 * pMatrix->u.s._33) + (mat->u.s._43 * pMatrix->u.s._34);
2278 temp.u.s._43 = (mat->u.s._13 * pMatrix->u.s._41) + (mat->u.s._23 * pMatrix->u.s._42) +
2279 (mat->u.s._33 * pMatrix->u.s._43) + (mat->u.s._43 * pMatrix->u.s._44);
2281 temp.u.s._14 = (mat->u.s._14 * pMatrix->u.s._11) + (mat->u.s._24 * pMatrix->u.s._12) +
2282 (mat->u.s._34 * pMatrix->u.s._13) + (mat->u.s._44 * pMatrix->u.s._14);
2283 temp.u.s._24 = (mat->u.s._14 * pMatrix->u.s._21) + (mat->u.s._24 * pMatrix->u.s._22) +
2284 (mat->u.s._34 * pMatrix->u.s._23) + (mat->u.s._44 * pMatrix->u.s._24);
2285 temp.u.s._34 = (mat->u.s._14 * pMatrix->u.s._31) + (mat->u.s._24 * pMatrix->u.s._32) +
2286 (mat->u.s._34 * pMatrix->u.s._33) + (mat->u.s._44 * pMatrix->u.s._34);
2287 temp.u.s._44 = (mat->u.s._14 * pMatrix->u.s._41) + (mat->u.s._24 * pMatrix->u.s._42) +
2288 (mat->u.s._34 * pMatrix->u.s._43) + (mat->u.s._44 * pMatrix->u.s._44);
2290 /* Apply change via set transform - will reapply to eg. lights this way */
2291 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2296 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
2298 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2299 you can reference any indexes you want as long as that number max are enabled at any
2300 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2301 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2302 but when recording, just build a chain pretty much of commands to be replayed. */
2304 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2306 PLIGHTINFOEL *object, *temp;
2308 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2309 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2311 /* If recording state block, just add to end of lights chain */
2312 if (This->isRecordingState) {
2313 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2314 if (NULL == object) {
2315 return WINED3DERR_OUTOFVIDEOMEMORY;
2317 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2318 object->OriginalIndex = Index;
2319 object->glIndex = -1;
2320 object->changed = TRUE;
2322 /* Add to the END of the chain of lights changes to be replayed */
2323 if (This->updateStateBlock->lights == NULL) {
2324 This->updateStateBlock->lights = object;
2326 temp = This->updateStateBlock->lights;
2327 while (temp->next != NULL) temp=temp->next;
2328 temp->next = object;
2330 TRACE("Recording... not performing anything more\n");
2334 /* Ok, not recording any longer so do real work */
2335 object = This->stateBlock->lights;
2336 while (object != NULL && object->OriginalIndex != Index) object = object->next;
2338 /* If we didn't find it in the list of lights, time to add it */
2339 if (object == NULL) {
2340 PLIGHTINFOEL *insertAt,*prevPos;
2342 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2343 if (NULL == object) {
2344 return WINED3DERR_OUTOFVIDEOMEMORY;
2346 object->OriginalIndex = Index;
2347 object->glIndex = -1;
2349 /* Add it to the front of list with the idea that lights will be changed as needed
2350 BUT after any lights currently assigned GL indexes */
2351 insertAt = This->stateBlock->lights;
2353 while (insertAt != NULL && insertAt->glIndex != -1) {
2355 insertAt = insertAt->next;
2358 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2359 This->stateBlock->lights = object;
2360 } else if (insertAt == NULL) { /* End of list */
2361 prevPos->next = object;
2362 object->prev = prevPos;
2363 } else { /* Middle of chain */
2364 if (prevPos == NULL) {
2365 This->stateBlock->lights = object;
2367 prevPos->next = object;
2369 object->prev = prevPos;
2370 object->next = insertAt;
2371 insertAt->prev = object;
2375 /* Initialize the object */
2376 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,
2377 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2378 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2379 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2380 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2381 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2382 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2384 /* Save away the information */
2385 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2387 switch (pLight->Type) {
2388 case D3DLIGHT_POINT:
2390 object->lightPosn[0] = pLight->Position.x;
2391 object->lightPosn[1] = pLight->Position.y;
2392 object->lightPosn[2] = pLight->Position.z;
2393 object->lightPosn[3] = 1.0f;
2394 object->cutoff = 180.0f;
2398 case D3DLIGHT_DIRECTIONAL:
2400 object->lightPosn[0] = -pLight->Direction.x;
2401 object->lightPosn[1] = -pLight->Direction.y;
2402 object->lightPosn[2] = -pLight->Direction.z;
2403 object->lightPosn[3] = 0.0;
2404 object->exponent = 0.0f;
2405 object->cutoff = 180.0f;
2410 object->lightPosn[0] = pLight->Position.x;
2411 object->lightPosn[1] = pLight->Position.y;
2412 object->lightPosn[2] = pLight->Position.z;
2413 object->lightPosn[3] = 1.0;
2416 object->lightDirn[0] = pLight->Direction.x;
2417 object->lightDirn[1] = pLight->Direction.y;
2418 object->lightDirn[2] = pLight->Direction.z;
2419 object->lightDirn[3] = 1.0;
2422 * opengl-ish and d3d-ish spot lights use too different models for the
2423 * light "intensity" as a function of the angle towards the main light direction,
2424 * so we only can approximate very roughly.
2425 * however spot lights are rather rarely used in games (if ever used at all).
2426 * furthermore if still used, probably nobody pays attention to such details.
2428 if (pLight->Falloff == 0) {
2431 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2433 if (rho < 0.0001) rho = 0.0001f;
2434 object->exponent = -0.3/log(cos(rho/2));
2435 object->cutoff = pLight->Phi*90/M_PI;
2441 FIXME("Unrecognized light type %d\n", pLight->Type);
2444 /* Update the live definitions if the light is currently assigned a glIndex */
2445 if (object->glIndex != -1) {
2446 setup_light(iface, object->glIndex, object);
2451 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2452 PLIGHTINFOEL *lightInfo = NULL;
2453 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2454 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2456 /* Locate the light in the live lights */
2457 lightInfo = This->stateBlock->lights;
2458 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2460 if (lightInfo == NULL) {
2461 TRACE("Light information requested but light not defined\n");
2462 return WINED3DERR_INVALIDCALL;
2465 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
2470 * Get / Set Light Enable
2471 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2473 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2474 PLIGHTINFOEL *lightInfo = NULL;
2475 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2476 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2478 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2479 if (This->isRecordingState) {
2480 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2481 if (NULL == lightInfo) {
2482 return WINED3DERR_OUTOFVIDEOMEMORY;
2484 lightInfo->OriginalIndex = Index;
2485 lightInfo->glIndex = -1;
2486 lightInfo->enabledChanged = TRUE;
2488 /* Add to the END of the chain of lights changes to be replayed */
2489 if (This->updateStateBlock->lights == NULL) {
2490 This->updateStateBlock->lights = lightInfo;
2492 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2493 while (temp->next != NULL) temp=temp->next;
2494 temp->next = lightInfo;
2496 TRACE("Recording... not performing anything more\n");
2500 /* Not recording... So, locate the light in the live lights */
2501 lightInfo = This->stateBlock->lights;
2502 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2504 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2505 if (lightInfo == NULL) {
2506 D3DLIGHT9 lightParms;
2507 /* Warning - untested code :-) Prob safe to change fixme to a trace but
2508 wait until someone confirms it seems to work! */
2509 TRACE("Light enabled requested but light not defined, so defining one!\n");
2510 lightParms.Type = D3DLIGHT_DIRECTIONAL;
2511 lightParms.Diffuse.r = 1.0;
2512 lightParms.Diffuse.g = 1.0;
2513 lightParms.Diffuse.b = 1.0;
2514 lightParms.Diffuse.a = 0.0;
2515 lightParms.Specular.r = 0.0;
2516 lightParms.Specular.g = 0.0;
2517 lightParms.Specular.b = 0.0;
2518 lightParms.Specular.a = 0.0;
2519 lightParms.Ambient.r = 0.0;
2520 lightParms.Ambient.g = 0.0;
2521 lightParms.Ambient.b = 0.0;
2522 lightParms.Ambient.a = 0.0;
2523 lightParms.Position.x = 0.0;
2524 lightParms.Position.y = 0.0;
2525 lightParms.Position.z = 0.0;
2526 lightParms.Direction.x = 0.0;
2527 lightParms.Direction.y = 0.0;
2528 lightParms.Direction.z = 1.0;
2529 lightParms.Range = 0.0;
2530 lightParms.Falloff = 0.0;
2531 lightParms.Attenuation0 = 0.0;
2532 lightParms.Attenuation1 = 0.0;
2533 lightParms.Attenuation2 = 0.0;
2534 lightParms.Theta = 0.0;
2535 lightParms.Phi = 0.0;
2536 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
2538 /* Search for it again! Should be fairly quick as near head of list */
2539 lightInfo = This->stateBlock->lights;
2540 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2541 if (lightInfo == NULL) {
2542 FIXME("Adding default lights has failed dismally\n");
2543 return WINED3DERR_INVALIDCALL;
2547 /* OK, we now have a light... */
2548 if (Enable == FALSE) {
2550 /* If we are disabling it, check it was enabled, and
2551 still only do something if it has assigned a glIndex (which it should have!) */
2552 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2553 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2555 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2556 checkGLcall("glDisable GL_LIGHT0+Index");
2559 TRACE("Nothing to do as light was not enabled\n");
2561 lightInfo->lightEnabled = FALSE;
2564 /* We are enabling it. If it is enabled, it's really simple */
2565 if (lightInfo->lightEnabled) {
2567 TRACE("Nothing to do as light was enabled\n");
2569 /* If it already has a glIndex, it's still simple */
2570 } else if (lightInfo->glIndex != -1) {
2571 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2572 lightInfo->lightEnabled = TRUE;
2574 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2575 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2578 /* Otherwise got to find space - lights are ordered gl indexes first */
2580 PLIGHTINFOEL *bsf = NULL;
2581 PLIGHTINFOEL *pos = This->stateBlock->lights;
2582 PLIGHTINFOEL *prev = NULL;
2586 /* Try to minimize changes as much as possible */
2587 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2589 /* Try to remember which index can be replaced if necessary */
2590 if (bsf==NULL && pos->lightEnabled == FALSE) {
2591 /* Found a light we can replace, save as best replacement */
2595 /* Step to next space */
2601 /* If we have too many active lights, fail the call */
2602 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2603 FIXME("Program requests too many concurrent lights\n");
2604 return WINED3DERR_INVALIDCALL;
2606 /* If we have allocated all lights, but not all are enabled,
2607 reuse one which is not enabled */
2608 } else if (Index == This->maxConcurrentLights) {
2609 /* use bsf - Simply swap the new light and the BSF one */
2610 PLIGHTINFOEL *bsfNext = bsf->next;
2611 PLIGHTINFOEL *bsfPrev = bsf->prev;
2614 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2615 if (bsf->prev != NULL) {
2616 bsf->prev->next = lightInfo;
2618 This->stateBlock->lights = lightInfo;
2621 /* If not side by side, lots of chains to update */
2622 if (bsf->next != lightInfo) {
2623 lightInfo->prev->next = bsf;
2624 bsf->next->prev = lightInfo;
2625 bsf->next = lightInfo->next;
2626 bsf->prev = lightInfo->prev;
2627 lightInfo->next = bsfNext;
2628 lightInfo->prev = bsfPrev;
2632 bsf->prev = lightInfo;
2633 bsf->next = lightInfo->next;
2634 lightInfo->next = bsf;
2635 lightInfo->prev = bsfPrev;
2640 glIndex = bsf->glIndex;
2642 lightInfo->glIndex = glIndex;
2643 lightInfo->lightEnabled = TRUE;
2645 /* Finally set up the light in gl itself */
2646 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2648 setup_light(iface, glIndex, lightInfo);
2649 glEnable(GL_LIGHT0 + glIndex);
2650 checkGLcall("glEnable GL_LIGHT0 new setup");
2653 /* If we reached the end of the allocated lights, with space in the
2654 gl lights, setup a new light */
2655 } else if (pos->glIndex == -1) {
2657 /* We reached the end of the allocated gl lights, so already
2658 know the index of the next one! */
2660 lightInfo->glIndex = glIndex;
2661 lightInfo->lightEnabled = TRUE;
2663 /* In an ideal world, it's already in the right place */
2664 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2665 /* No need to move it */
2667 /* Remove this light from the list */
2668 lightInfo->prev->next = lightInfo->next;
2669 if (lightInfo->next != NULL) {
2670 lightInfo->next->prev = lightInfo->prev;
2673 /* Add in at appropriate place (inbetween prev and pos) */
2674 lightInfo->prev = prev;
2675 lightInfo->next = pos;
2677 This->stateBlock->lights = lightInfo;
2679 prev->next = lightInfo;
2682 pos->prev = lightInfo;
2686 /* Finally set up the light in gl itself */
2687 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2689 setup_light(iface, glIndex, lightInfo);
2690 glEnable(GL_LIGHT0 + glIndex);
2691 checkGLcall("glEnable GL_LIGHT0 new setup");
2700 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2702 PLIGHTINFOEL *lightInfo = NULL;
2703 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2704 TRACE("(%p) : for idx(%ld)\n", This, Index);
2706 /* Locate the light in the live lights */
2707 lightInfo = This->stateBlock->lights;
2708 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2710 if (lightInfo == NULL) {
2711 TRACE("Light enabled state requested but light not defined\n");
2712 return WINED3DERR_INVALIDCALL;
2714 *pEnable = lightInfo->lightEnabled;
2719 * Get / Set Clip Planes
2721 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2722 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2723 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2725 /* Validate Index */
2726 if (Index >= GL_LIMITS(clipplanes)) {
2727 TRACE("Application has requested clipplane this device doesn't support\n");
2728 return WINED3DERR_INVALIDCALL;
2731 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2732 This->updateStateBlock->set.clipplane[Index] = TRUE;
2733 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2734 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2735 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2736 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2738 /* Handle recording of state blocks */
2739 if (This->isRecordingState) {
2740 TRACE("Recording... not performing anything\n");
2748 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2749 glMatrixMode(GL_MODELVIEW);
2751 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2753 TRACE("Clipplane [%f,%f,%f,%f]\n",
2754 This->updateStateBlock->clipplane[Index][0],
2755 This->updateStateBlock->clipplane[Index][1],
2756 This->updateStateBlock->clipplane[Index][2],
2757 This->updateStateBlock->clipplane[Index][3]);
2758 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2759 checkGLcall("glClipPlane");
2767 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2768 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2769 TRACE("(%p) : for idx %ld\n", This, Index);
2771 /* Validate Index */
2772 if (Index >= GL_LIMITS(clipplanes)) {
2773 TRACE("Application has requested clipplane this device doesn't support\n");
2774 return WINED3DERR_INVALIDCALL;
2777 pPlane[0] = This->stateBlock->clipplane[Index][0];
2778 pPlane[1] = This->stateBlock->clipplane[Index][1];
2779 pPlane[2] = This->stateBlock->clipplane[Index][2];
2780 pPlane[3] = This->stateBlock->clipplane[Index][3];
2785 * Get / Set Clip Plane Status
2786 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2788 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2789 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2790 FIXME("(%p) : stub\n", This);
2791 if (NULL == pClipStatus) {
2792 return WINED3DERR_INVALIDCALL;
2794 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2795 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2799 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2800 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2801 FIXME("(%p) : stub\n", This);
2802 if (NULL == pClipStatus) {
2803 return WINED3DERR_INVALIDCALL;
2805 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2806 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2811 * Get / Set Material
2812 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2814 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2815 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2817 This->updateStateBlock->changed.material = TRUE;
2818 This->updateStateBlock->set.material = TRUE;
2819 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2821 /* Handle recording of state blocks */
2822 if (This->isRecordingState) {
2823 TRACE("Recording... not performing anything\n");
2828 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2829 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2830 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2831 pMaterial->Ambient.b, pMaterial->Ambient.a);
2832 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2833 pMaterial->Specular.b, pMaterial->Specular.a);
2834 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2835 pMaterial->Emissive.b, pMaterial->Emissive.a);
2836 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2838 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2839 checkGLcall("glMaterialfv(GL_AMBIENT)");
2840 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2841 checkGLcall("glMaterialfv(GL_DIFFUSE)");
2843 /* Only change material color if specular is enabled, otherwise it is set to black */
2844 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2845 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2846 checkGLcall("glMaterialfv(GL_SPECULAR");
2848 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2849 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2850 checkGLcall("glMaterialfv(GL_SPECULAR");
2852 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2853 checkGLcall("glMaterialfv(GL_EMISSION)");
2854 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2855 checkGLcall("glMaterialf(GL_SHININESS");
2861 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2862 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2863 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2864 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2865 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2866 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2867 pMaterial->Ambient.b, pMaterial->Ambient.a);
2868 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2869 pMaterial->Specular.b, pMaterial->Specular.a);
2870 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2871 pMaterial->Emissive.b, pMaterial->Emissive.a);
2872 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2880 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2881 UINT BaseVertexIndex) {
2882 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2883 IWineD3DIndexBuffer *oldIdxs;
2885 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2886 oldIdxs = This->updateStateBlock->pIndexData;
2888 This->updateStateBlock->changed.indices = TRUE;
2889 This->updateStateBlock->set.indices = TRUE;
2890 This->updateStateBlock->pIndexData = pIndexData;
2891 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2893 /* Handle recording of state blocks */
2894 if (This->isRecordingState) {
2895 TRACE("Recording... not performing anything\n");
2899 if (NULL != pIndexData) {
2900 IWineD3DIndexBuffer_AddRef(pIndexData);
2902 if (NULL != oldIdxs) {
2903 IWineD3DIndexBuffer_Release(oldIdxs);
2908 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2909 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2911 *ppIndexData = This->stateBlock->pIndexData;
2913 /* up ref count on ppindexdata */
2915 IWineD3DIndexBuffer_AddRef(*ppIndexData);
2916 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2917 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
2919 TRACE("(%p) No index data set\n", This);
2921 TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
2927 * Get / Set Viewports
2929 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2930 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2932 TRACE("(%p)\n", This);
2933 This->updateStateBlock->changed.viewport = TRUE;
2934 This->updateStateBlock->set.viewport = TRUE;
2935 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2937 /* Handle recording of state blocks */
2938 if (This->isRecordingState) {
2939 TRACE("Recording... not performing anything\n");
2942 This->viewport_changed = TRUE;
2946 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2947 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2949 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2950 checkGLcall("glDepthRange");
2951 /* Note: GL requires lower left, DirectX supplies upper left */
2952 /* TODO: replace usage of renderTarget with context management */
2953 glViewport(pViewport->X,
2954 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2955 pViewport->Width, pViewport->Height);
2957 checkGLcall("glViewport");
2965 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2966 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2967 TRACE("(%p)\n", This);
2968 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2973 * Get / Set Render States
2974 * TODO: Verify against dx9 definitions
2976 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2978 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2979 DWORD OldValue = This->stateBlock->renderState[State];
2981 /* Simple way of referring to either a DWORD or a 4 byte float */
2987 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2988 This->updateStateBlock->changed.renderState[State] = TRUE;
2989 This->updateStateBlock->set.renderState[State] = TRUE;
2990 This->updateStateBlock->renderState[State] = Value;
2992 /* Handle recording of state blocks */
2993 if (This->isRecordingState) {
2994 TRACE("Recording... not performing anything\n");
3001 case WINED3DRS_FILLMODE :
3002 switch ((D3DFILLMODE) Value) {
3003 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
3004 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
3005 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
3007 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
3009 checkGLcall("glPolygonMode (fillmode)");
3012 case WINED3DRS_LIGHTING :
3014 glEnable(GL_LIGHTING);
3015 checkGLcall("glEnable GL_LIGHTING");
3017 glDisable(GL_LIGHTING);
3018 checkGLcall("glDisable GL_LIGHTING");
3022 case WINED3DRS_ZENABLE :
3023 switch ((D3DZBUFFERTYPE) Value) {
3025 glDisable(GL_DEPTH_TEST);
3026 checkGLcall("glDisable GL_DEPTH_TEST");
3029 glEnable(GL_DEPTH_TEST);
3030 checkGLcall("glEnable GL_DEPTH_TEST");
3033 glEnable(GL_DEPTH_TEST);
3034 checkGLcall("glEnable GL_DEPTH_TEST");
3035 FIXME("W buffer is not well handled\n");
3038 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
3042 case WINED3DRS_CULLMODE :
3044 /* If we are culling "back faces with clockwise vertices" then
3045 set front faces to be counter clockwise and enable culling
3047 switch ((D3DCULL) Value) {
3049 glDisable(GL_CULL_FACE);
3050 checkGLcall("glDisable GL_CULL_FACE");
3053 glEnable(GL_CULL_FACE);
3054 checkGLcall("glEnable GL_CULL_FACE");
3055 if (This->renderUpsideDown) {
3057 checkGLcall("glFrontFace GL_CW");
3059 glFrontFace(GL_CCW);
3060 checkGLcall("glFrontFace GL_CCW");
3062 glCullFace(GL_BACK);
3065 glEnable(GL_CULL_FACE);
3066 checkGLcall("glEnable GL_CULL_FACE");
3067 if (This->renderUpsideDown) {
3068 glFrontFace(GL_CCW);
3069 checkGLcall("glFrontFace GL_CCW");
3072 checkGLcall("glFrontFace GL_CW");
3074 glCullFace(GL_BACK);
3077 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
3081 case WINED3DRS_SHADEMODE :
3082 switch ((D3DSHADEMODE) Value) {
3084 glShadeModel(GL_FLAT);
3085 checkGLcall("glShadeModel");
3087 case D3DSHADE_GOURAUD:
3088 glShadeModel(GL_SMOOTH);
3089 checkGLcall("glShadeModel");
3091 case D3DSHADE_PHONG:
3092 FIXME("D3DSHADE_PHONG isn't supported?\n");
3095 return WINED3DERR_INVALIDCALL;
3097 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
3101 case WINED3DRS_DITHERENABLE :
3103 glEnable(GL_DITHER);
3104 checkGLcall("glEnable GL_DITHER");
3106 glDisable(GL_DITHER);
3107 checkGLcall("glDisable GL_DITHER");
3111 case WINED3DRS_ZWRITEENABLE :
3114 checkGLcall("glDepthMask");
3117 checkGLcall("glDepthMask");
3121 case WINED3DRS_ZFUNC :
3123 int glParm = GL_LESS;
3125 switch ((D3DCMPFUNC) Value) {
3126 case D3DCMP_NEVER: glParm=GL_NEVER; break;
3127 case D3DCMP_LESS: glParm=GL_LESS; break;
3128 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
3129 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
3130 case D3DCMP_GREATER: glParm=GL_GREATER; break;
3131 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
3132 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
3133 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
3135 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3137 glDepthFunc(glParm);
3138 checkGLcall("glDepthFunc");
3142 case WINED3DRS_AMBIENT :
3145 D3DCOLORTOGLFLOAT4(Value, col);
3146 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
3147 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
3148 checkGLcall("glLightModel for MODEL_AMBIENT");
3153 case WINED3DRS_ALPHABLENDENABLE :
3156 checkGLcall("glEnable GL_BLEND");
3158 glDisable(GL_BLEND);
3159 checkGLcall("glDisable GL_BLEND");
3163 case WINED3DRS_SRCBLEND :
3164 case WINED3DRS_DESTBLEND :
3166 int newVal = GL_ZERO;
3168 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
3169 case D3DBLEND_ONE : newVal = GL_ONE; break;
3170 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
3171 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
3172 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
3173 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
3174 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
3175 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
3176 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
3177 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
3178 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
3180 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
3181 This->srcBlend = newVal;
3182 This->dstBlend = newVal;
3185 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
3186 This->srcBlend = newVal;
3187 This->dstBlend = newVal;
3190 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
3193 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
3194 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
3195 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
3196 glBlendFunc(This->srcBlend, This->dstBlend);
3198 checkGLcall("glBlendFunc");
3202 case WINED3DRS_ALPHATESTENABLE :
3204 glEnable(GL_ALPHA_TEST);
3205 checkGLcall("glEnable GL_ALPHA_TEST");
3207 glDisable(GL_ALPHA_TEST);
3208 checkGLcall("glDisable GL_ALPHA_TEST");
3212 case WINED3DRS_ALPHAFUNC :
3214 int glParm = GL_LESS;
3215 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
3217 switch ((D3DCMPFUNC) Value) {
3218 case D3DCMP_NEVER: glParm = GL_NEVER; break;
3219 case D3DCMP_LESS: glParm = GL_LESS; break;
3220 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
3221 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
3222 case D3DCMP_GREATER: glParm = GL_GREATER; break;
3223 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
3224 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
3225 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
3227 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3229 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
3230 glAlphaFunc(glParm, ref);
3231 This->alphafunc = glParm;
3232 checkGLcall("glAlphaFunc");
3236 case WINED3DRS_ALPHAREF :
3238 int glParm = This->alphafunc;
3241 ref = ((float) Value) / 255.0f;
3242 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
3243 glAlphaFunc(glParm, ref);
3244 checkGLcall("glAlphaFunc");
3248 case WINED3DRS_CLIPPLANEENABLE :
3249 case WINED3DRS_CLIPPING :
3251 /* Ensure we only do the changed clip planes */
3252 DWORD enable = 0xFFFFFFFF;
3253 DWORD disable = 0x00000000;
3255 /* If enabling / disabling all */
3256 if (State == WINED3DRS_CLIPPING) {
3258 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3261 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3265 enable = Value & ~OldValue;
3266 disable = ~Value & OldValue;
3269 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
3270 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
3271 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
3272 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
3273 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
3274 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
3276 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
3277 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
3278 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
3279 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
3280 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
3281 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
3283 /** update clipping status */
3285 This->stateBlock->clip_status.ClipUnion = 0;
3286 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
3288 This->stateBlock->clip_status.ClipUnion = 0;
3289 This->stateBlock->clip_status.ClipIntersection = 0;
3294 case WINED3DRS_BLENDOP :
3296 int glParm = GL_FUNC_ADD;
3298 switch ((D3DBLENDOP) Value) {
3299 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
3300 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
3301 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3302 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
3303 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
3305 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
3307 TRACE("glBlendEquation(%x)\n", glParm);
3308 glBlendEquation(glParm);
3309 checkGLcall("glBlendEquation");
3313 case WINED3DRS_TEXTUREFACTOR :
3317 /* Note the texture color applies to all textures whereas
3318 GL_TEXTURE_ENV_COLOR applies to active only */
3320 D3DCOLORTOGLFLOAT4(Value, col);
3321 /* Set the default alpha blend color */
3322 glBlendColor(col[0], col[1], col[2], col[3]);
3323 checkGLcall("glBlendColor");
3325 /* And now the default texture color as well */
3326 for (i = 0; i < GL_LIMITS(textures); i++) {
3328 /* Note the D3DRS value applies to all textures, but GL has one
3329 per texture, so apply it now ready to be used! */
3330 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3333 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3336 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3337 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3342 case WINED3DRS_SPECULARENABLE :
3344 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3345 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3346 specular color. This is wrong:
3347 Separate specular color means the specular colour is maintained separately, whereas
3348 single color means it is merged in. However in both cases they are being used to
3350 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3351 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3355 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3356 checkGLcall("glMaterialfv");
3357 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3358 glEnable(GL_COLOR_SUM_EXT);
3360 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3362 checkGLcall("glEnable(GL_COLOR_SUM)");
3364 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3366 /* for the case of enabled lighting: */
3367 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3368 checkGLcall("glMaterialfv");
3370 /* for the case of disabled lighting: */
3371 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3372 glDisable(GL_COLOR_SUM_EXT);
3374 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3376 checkGLcall("glDisable(GL_COLOR_SUM)");
3381 case WINED3DRS_STENCILENABLE :
3383 glEnable(GL_STENCIL_TEST);
3384 checkGLcall("glEnable GL_STENCIL_TEST");
3386 glDisable(GL_STENCIL_TEST);
3387 checkGLcall("glDisable GL_STENCIL_TEST");
3391 case WINED3DRS_STENCILFUNC :
3394 GLint ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3395 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3398 switch ((D3DCMPFUNC)Value) {
3399 case D3DCMP_NEVER: func = GL_NEVER; break;
3400 case D3DCMP_LESS: func = GL_LESS; break;
3401 case D3DCMP_EQUAL: func = GL_EQUAL; break;
3402 case D3DCMP_LESSEQUAL: func = GL_LEQUAL; break;
3403 case D3DCMP_GREATER: func = GL_GREATER; break;
3404 case D3DCMP_NOTEQUAL: func = GL_NOTEQUAL; break;
3405 case D3DCMP_GREATEREQUAL: func = GL_GEQUAL; break;
3406 case D3DCMP_ALWAYS: func = GL_ALWAYS; break;
3408 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3410 This->stencilfunc = func;
3411 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3412 #if 0 /* Don't use OpenGL 2.0 calls for now */
3413 if(GL_EXTCALL(glStencilFuncSeparate)) {
3414 GL_EXTCALL(glStencilFuncSeparate(GL_FRONT, func, ref, mask));
3415 checkGLcall("glStencilFuncSeparate(GL_FRONT,...)");
3419 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3420 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3421 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3422 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
3423 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
3424 glStencilFunc(func, ref, mask);
3425 checkGLcall("glStencilFunc(...)");
3427 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3428 GL_EXTCALL(glStencilFuncSeparateATI(GL_FRONT, func, ref, mask));
3429 checkGLcall("glStencilFuncSeparateATI(GL_FRONT,...)");
3431 TRACE("Separate stencil function not supported on this version of opengl");
3432 glStencilFunc(func, ref, mask);
3433 checkGLcall("glStencilFunc(...)");
3436 glStencilFunc(func, ref, mask);
3437 checkGLcall("glStencilFunc(...)");
3441 case WINED3DRS_STENCILREF :
3443 int glParm = This->stencilfunc;
3445 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3448 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3449 glStencilFunc(glParm, ref, mask);
3450 checkGLcall("glStencilFunc");
3454 case WINED3DRS_STENCILMASK :
3456 int glParm = This->stencilfunc;
3457 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3458 GLuint mask = Value;
3460 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3461 glStencilFunc(glParm, ref, mask);
3462 checkGLcall("glStencilFunc");
3466 case WINED3DRS_STENCILFAIL :
3467 case WINED3DRS_STENCILZFAIL :
3468 case WINED3DRS_STENCILPASS :
3474 GLint action = StencilOp(Value);
3476 glGetIntegerv(GL_STENCIL_FAIL, &stencilFail);
3477 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &depthFail);
3478 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &stencilPass);
3480 if(WINED3DRS_STENCILFAIL == State) {
3481 stencilFail = action;
3483 else if(WINED3DRS_STENCILZFAIL == State) {
3486 else if(WINED3DRS_STENCILPASS == State) {
3487 stencilPass = action;
3490 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3491 #if 0 /* Don't use OpenGL 2.0 calls for now */
3492 if(GL_EXTCALL(glStencilOpSeparate)) {
3493 GL_EXTCALL(glStencilOpSeparate(GL_FRONT, stencilFail, depthFail, stencilPass));
3494 checkGLcall("glStencilOpSeparate(GL_FRONT,...)");
3498 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3499 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3500 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3501 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
3502 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
3503 glStencilOp(stencilFail, depthFail, stencilPass);
3504 checkGLcall("glStencilOp(...)");
3506 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3507 GL_EXTCALL(glStencilOpSeparateATI(GL_FRONT, stencilFail, depthFail, stencilPass));
3508 checkGLcall("glStencilOpSeparateATI(GL_FRONT,...)");
3510 TRACE("Separate stencil operation not supported on this version of opengl");
3511 glStencilOp(stencilFail, depthFail, stencilPass);
3512 checkGLcall("glStencilOp(...)");
3515 glStencilOp(stencilFail, depthFail, stencilPass);
3516 checkGLcall("glStencilOp(...)");
3520 case WINED3DRS_STENCILWRITEMASK :
3522 glStencilMask(Value);
3523 TRACE("glStencilMask(%lu)\n", Value);
3524 checkGLcall("glStencilMask");
3528 case WINED3DRS_FOGENABLE :
3530 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
3532 checkGLcall("glEnable GL_FOG");
3535 checkGLcall("glDisable GL_FOG");
3540 case WINED3DRS_RANGEFOGENABLE :
3543 TRACE("Enabled RANGEFOG");
3545 TRACE("Disabled RANGEFOG");
3550 case WINED3DRS_FOGCOLOR :
3553 D3DCOLORTOGLFLOAT4(Value, col);
3554 /* Set the default alpha blend color */
3555 glFogfv(GL_FOG_COLOR, &col[0]);
3556 checkGLcall("glFog GL_FOG_COLOR");
3560 case WINED3DRS_FOGTABLEMODE :
3562 glHint(GL_FOG_HINT, GL_NICEST);
3564 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3565 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3566 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3567 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3569 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3571 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3572 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3577 case WINED3DRS_FOGVERTEXMODE :
3579 glHint(GL_FOG_HINT, GL_FASTEST);
3581 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3582 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3583 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3584 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3586 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3588 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3589 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
3594 case WINED3DRS_FOGSTART :
3597 glFogfv(GL_FOG_START, &tmpvalue.f);
3598 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3599 TRACE("Fog Start == %f\n", tmpvalue.f);
3603 case WINED3DRS_FOGEND :
3606 glFogfv(GL_FOG_END, &tmpvalue.f);
3607 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3608 TRACE("Fog End == %f\n", tmpvalue.f);
3612 case WINED3DRS_FOGDENSITY :
3615 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3616 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3620 case WINED3DRS_VERTEXBLEND :
3622 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3623 TRACE("Vertex Blending state to %ld\n", Value);
3627 case WINED3DRS_TWEENFACTOR :
3630 This->updateStateBlock->tween_factor = tmpvalue.f;
3631 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3635 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
3637 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3641 case WINED3DRS_COLORVERTEX :
3642 case WINED3DRS_DIFFUSEMATERIALSOURCE :
3643 case WINED3DRS_SPECULARMATERIALSOURCE :
3644 case WINED3DRS_AMBIENTMATERIALSOURCE :
3645 case WINED3DRS_EMISSIVEMATERIALSOURCE :
3647 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3649 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3650 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3651 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3652 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3653 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3654 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3656 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3657 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3658 Parm = GL_AMBIENT_AND_DIFFUSE;
3662 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3664 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3666 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3673 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3675 This->tracking_color = NEEDS_TRACKING;
3676 This->tracking_parm = Parm;
3680 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3685 case WINED3DRS_LINEPATTERN :
3691 tmppattern.d = Value;
3693 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3695 if (tmppattern.lp.wRepeatFactor) {
3696 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3697 checkGLcall("glLineStipple(repeat, linepattern)");
3698 glEnable(GL_LINE_STIPPLE);
3699 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3701 glDisable(GL_LINE_STIPPLE);
3702 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3707 case WINED3DRS_ZBIAS : /* D3D8 only */
3711 TRACE("ZBias value %f\n", tmpvalue.f);
3712 glPolygonOffset(0, -tmpvalue.f);
3713 checkGLcall("glPolygonOffset(0, -Value)");
3714 glEnable(GL_POLYGON_OFFSET_FILL);
3715 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3716 glEnable(GL_POLYGON_OFFSET_LINE);
3717 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3718 glEnable(GL_POLYGON_OFFSET_POINT);
3719 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3721 glDisable(GL_POLYGON_OFFSET_FILL);
3722 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3723 glDisable(GL_POLYGON_OFFSET_LINE);
3724 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3725 glDisable(GL_POLYGON_OFFSET_POINT);
3726 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3731 case WINED3DRS_NORMALIZENORMALS :
3733 glEnable(GL_NORMALIZE);
3734 checkGLcall("glEnable(GL_NORMALIZE);");
3736 glDisable(GL_NORMALIZE);
3737 checkGLcall("glDisable(GL_NORMALIZE);");
3741 case WINED3DRS_POINTSIZE :
3742 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
3744 TRACE("Set point size to %f\n", tmpvalue.f);
3745 glPointSize(tmpvalue.f);
3746 checkGLcall("glPointSize(...);");
3749 case WINED3DRS_POINTSIZE_MIN :
3750 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3752 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3753 checkGLcall("glPointParameterfEXT(...);");
3755 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3759 case WINED3DRS_POINTSIZE_MAX :
3760 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3762 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3763 checkGLcall("glPointParameterfEXT(...);");
3765 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3769 case WINED3DRS_POINTSCALE_A :
3770 case WINED3DRS_POINTSCALE_B :
3771 case WINED3DRS_POINTSCALE_C :
3772 case WINED3DRS_POINTSCALEENABLE :
3775 * POINTSCALEENABLE controls how point size value is treated. If set to
3776 * true, the point size is scaled with respect to height of viewport.
3777 * When set to false point size is in pixels.
3779 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
3782 /* Default values */
3783 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3786 * Minimum valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
3787 * This means that OpenGL will clamp really small point sizes to 1.0f.
3788 * To correct for this we need to multiply by the scale factor when sizes
3789 * are less than 1.0f. scale_factor = 1.0f / point_size.
3791 GLfloat pointSize = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSIZE]);
3792 if(pointSize > 0.0f) {
3793 GLfloat scaleFactor;
3795 if(pointSize < 1.0f) {
3796 scaleFactor = pointSize * pointSize;
3801 if(This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3802 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]) /
3803 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3804 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]) /
3805 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3806 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) /
3807 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3811 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
3812 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
3813 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
3815 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3816 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3817 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
3819 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
3823 case WINED3DRS_COLORWRITEENABLE :
3825 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3826 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3827 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3828 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3829 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3830 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3831 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3832 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3833 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3834 checkGLcall("glColorMask(...)");
3838 case WINED3DRS_LOCALVIEWER :
3840 GLint state = (Value) ? 1 : 0;
3841 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3842 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3846 case WINED3DRS_LASTPIXEL :
3849 TRACE("Last Pixel Drawing Enabled\n");
3851 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3856 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3859 TRACE("Software Processing Enabled\n");
3861 TRACE("Software Processing Disabled\n");
3866 /** not supported */
3867 case WINED3DRS_ZVISIBLE :
3870 return WINED3DERR_INVALIDCALL;
3872 case WINED3DRS_POINTSPRITEENABLE :
3874 /* TODO: NV_POINT_SPRITE */
3875 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
3876 TRACE("Point sprites not supported\n");
3881 * Point sprites are always enabled. Value controls texture coordinate
3882 * replacement mode. Must be set true for point sprites to use
3885 glEnable(GL_POINT_SPRITE_ARB);
3886 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
3889 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
3890 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, TRUE)");
3892 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, FALSE);
3893 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, FALSE)");
3897 case WINED3DRS_EDGEANTIALIAS :
3900 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3902 checkGLcall("glEnable(GL_BLEND)");
3903 glEnable(GL_LINE_SMOOTH);
3904 checkGLcall("glEnable(GL_LINE_SMOOTH)");
3906 glDisable(GL_BLEND);
3907 checkGLcall("glDisable(GL_BLEND)");
3908 glDisable(GL_LINE_SMOOTH);
3909 checkGLcall("glDisable(GL_LINE_SMOOTH)");
3913 case WINED3DRS_WRAP0 :
3914 case WINED3DRS_WRAP1 :
3915 case WINED3DRS_WRAP2 :
3916 case WINED3DRS_WRAP3 :
3917 case WINED3DRS_WRAP4 :
3918 case WINED3DRS_WRAP5 :
3919 case WINED3DRS_WRAP6 :
3920 case WINED3DRS_WRAP7 :
3921 case WINED3DRS_WRAP8 :
3922 case WINED3DRS_WRAP9 :
3923 case WINED3DRS_WRAP10 :
3924 case WINED3DRS_WRAP11 :
3925 case WINED3DRS_WRAP12 :
3926 case WINED3DRS_WRAP13 :
3927 case WINED3DRS_WRAP14 :
3928 case WINED3DRS_WRAP15 :
3930 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
3931 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
3932 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
3933 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
3934 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
3936 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
3938 TRACE("(%p)->(%s,%ld) Texture wraping not yet supported\n",This, debug_d3drenderstate(State), Value);
3940 case WINED3DRS_MULTISAMPLEANTIALIAS :
3942 if (!GL_SUPPORT(ARB_MULTISAMPLE)) {
3943 TRACE("Multisample antialiasing not supported\n");
3948 glEnable(GL_MULTISAMPLE_ARB);
3949 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
3951 glDisable(GL_MULTISAMPLE_ARB);
3952 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
3956 case WINED3DRS_SCISSORTESTENABLE :
3959 glEnable(GL_SCISSOR_TEST);
3960 checkGLcall("glEnable(GL_SCISSOR_TEST)");
3962 glDisable(GL_SCISSOR_TEST);
3963 checkGLcall("glDisable(GL_SCISSOR_TEST)");
3967 case WINED3DRS_SLOPESCALEDEPTHBIAS :
3971 glEnable(GL_POLYGON_OFFSET_FILL);
3972 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
3973 glPolygonOffset(tmpvalue.f, *((float*)&This->stateBlock->renderState[WINED3DRS_DEPTHBIAS]));
3974 checkGLcall("glPolygonOffset(...)");
3976 glDisable(GL_POLYGON_OFFSET_FILL);
3977 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
3981 case WINED3DRS_ANTIALIASEDLINEENABLE :
3984 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3986 checkGLcall("glEnable(GL_BLEND)");
3987 glEnable(GL_LINE_SMOOTH);
3988 checkGLcall("glEnable(GL_LINE_SMOOTH)");
3990 glDisable(GL_BLEND);
3991 checkGLcall("glDisable(GL_BLEND)");
3992 glDisable(GL_LINE_SMOOTH);
3993 checkGLcall("glDisable(GL_LINE_SMOOTH)");
3997 case WINED3DRS_TWOSIDEDSTENCILMODE :
4000 TRACE("Two-sided stencil mode enabled\n");
4002 TRACE("Two-sided stencil mode disabled\n");
4006 case WINED3DRS_CCW_STENCILFAIL :
4007 case WINED3DRS_CCW_STENCILZFAIL :
4008 case WINED3DRS_CCW_STENCILPASS :
4014 GLint action = StencilOp(Value);
4016 glGetIntegerv(GL_STENCIL_BACK_FAIL, &stencilFail);
4017 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &depthFail);
4018 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS, &stencilPass);
4020 if(WINED3DRS_CCW_STENCILFAIL == State) {
4021 stencilFail = action;
4023 else if(WINED3DRS_CCW_STENCILZFAIL == State) {
4026 else if(WINED3DRS_CCW_STENCILPASS == State) {
4027 stencilPass = action;
4030 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
4031 #if 0 /* Don't use OpenGL 2.0 calls for now */
4032 if(GL_EXTCALL(glStencilOpSeparate)) {
4033 GL_EXTCALL(glStencilOpSeparate(GL_BACK, stencilFail, depthFail, stencilPass));
4034 checkGLcall("glStencilOpSeparate(GL_BACK,...)");
4038 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
4039 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
4040 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
4041 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
4042 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
4043 glStencilOp(stencilFail, depthFail, stencilPass);
4044 checkGLcall("glStencilOp(...)");
4046 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
4047 GL_EXTCALL(glStencilOpSeparateATI(GL_BACK, stencilFail, depthFail, stencilPass));
4048 checkGLcall("glStencilOpSeparateATI(GL_BACK,...)");
4050 TRACE("Separate stencil operation not supported on this version of opengl");
4051 glStencilOp(stencilFail, depthFail, stencilPass);
4052 checkGLcall("glStencilOp(...)");
4055 glStencilOp(stencilFail, depthFail, stencilPass);
4056 checkGLcall("glStencilOp(...)");
4060 case WINED3DRS_CCW_STENCILFUNC :
4063 GLint ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
4064 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
4067 switch ((D3DCMPFUNC)Value) {
4068 case D3DCMP_NEVER: func = GL_NEVER; break;
4069 case D3DCMP_LESS: func = GL_LESS; break;
4070 case D3DCMP_EQUAL: func = GL_EQUAL; break;
4071 case D3DCMP_LESSEQUAL: func = GL_LEQUAL; break;
4072 case D3DCMP_GREATER: func = GL_GREATER; break;
4073 case D3DCMP_NOTEQUAL: func = GL_NOTEQUAL; break;
4074 case D3DCMP_GREATEREQUAL: func = GL_GEQUAL; break;
4075 case D3DCMP_ALWAYS: func = GL_ALWAYS; break;
4077 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
4079 This->stencilfunc = func;
4080 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
4081 #if 0 /* Don't use OpenGL 2.0 calls for now */
4082 if(GL_EXTCALL(glStencilFuncSeparate)) {
4083 GL_EXTCALL(glStencilFuncSeparate(GL_BACK, func, ref, mask));
4084 checkGLcall("glStencilFuncSeparate(GL_BACK,...)");
4088 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
4089 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
4090 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
4091 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
4092 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
4093 glStencilFunc(func, ref, mask);
4094 checkGLcall("glStencilFunc(...)");
4096 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
4097 GL_EXTCALL(glStencilFuncSeparateATI(GL_BACK, func, ref, mask));
4098 checkGLcall("glStencilFuncSeparateATI(GL_BACK,...)");
4100 TRACE("Separate stencil function not supported on this version of opengl");
4101 glStencilFunc(func, ref, mask);
4102 checkGLcall("glStencilFunc(...)");
4105 glStencilFunc(func, ref, mask);
4106 checkGLcall("glStencilFunc(...)");
4110 case WINED3DRS_DEPTHBIAS :
4114 glEnable(GL_POLYGON_OFFSET_FILL);
4115 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4116 glPolygonOffset(*((float*)&This->stateBlock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS]), tmpvalue.f);
4117 checkGLcall("glPolygonOffset(...)");
4119 glDisable(GL_POLYGON_OFFSET_FILL);
4120 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4124 case WINED3DRS_SEPARATEALPHABLENDENABLE :
4125 case WINED3DRS_SRCBLENDALPHA :
4126 case WINED3DRS_DESTBLENDALPHA :
4127 case WINED3DRS_BLENDOPALPHA :
4128 case WINED3DRS_MULTISAMPLEMASK :
4129 case WINED3DRS_PATCHEDGESTYLE :
4130 case WINED3DRS_PATCHSEGMENTS :
4131 case WINED3DRS_DEBUGMONITORTOKEN :
4132 case WINED3DRS_POSITIONORDER :
4133 case WINED3DRS_NORMALORDER :
4134 case WINED3DRS_MINTESSELLATIONLEVEL :
4135 case WINED3DRS_MAXTESSELLATIONLEVEL :
4136 case WINED3DRS_ADAPTIVETESS_X :
4137 case WINED3DRS_ADAPTIVETESS_Y :
4138 case WINED3DRS_ADAPTIVETESS_Z :
4139 case WINED3DRS_ADAPTIVETESS_W :
4140 case WINED3DRS_ENABLEADAPTIVETESSELLATION :
4141 case WINED3DRS_COLORWRITEENABLE1 :
4142 case WINED3DRS_COLORWRITEENABLE2 :
4143 case WINED3DRS_COLORWRITEENABLE3 :
4144 case WINED3DRS_BLENDFACTOR :
4145 case WINED3DRS_SRGBWRITEENABLE :
4146 FIXME("(%p)->(%s,%ld) not handled yet\n", This, debug_d3drenderstate(State), Value);
4149 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
4157 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
4158 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4159 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
4160 *pValue = This->stateBlock->renderState[State];
4165 * Get / Set Sampler States
4166 * TODO: Verify against dx9 definitions
4169 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
4170 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4172 * SetSampler is designed to allow for more than the standard up to 8 textures
4173 * and Geforce has stopped supporting more than 6 standard textures in openGL.
4174 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
4176 * http://developer.nvidia.com/object/General_FAQ.html#t6
4178 * There are two new settings for GForce
4180 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
4181 * and the texture one:
4182 * GL_MAX_TEXTURE_COORDS_ARB.
4183 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
4185 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
4186 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
4188 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
4189 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE, Sampler, Type);
4190 return WINED3DERR_INVALIDCALL;
4192 TRACE("Setting sampler %ld %d to %ld\n", Sampler, Type, Value);
4193 This->updateStateBlock->samplerState[Sampler][Type] = Value;
4194 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
4195 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
4197 /* Handle recording of state blocks */
4198 if (This->isRecordingState) {
4199 TRACE("Recording... not performing anything\n");
4206 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
4207 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4208 /** TODO: check that sampler is in range **/
4209 *Value = This->updateStateBlock->samplerState[Sampler][Type];
4210 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
4215 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
4216 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4219 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4220 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4221 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
4227 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
4228 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4229 GLint scissorBox[4];
4232 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4233 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
4234 pRect->left = scissorBox[1];
4235 pRect->top = scissorBox[2];
4236 pRect->right = scissorBox[1] + scissorBox[3];
4237 pRect->bottom = scissorBox[2] + scissorBox[4];
4238 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4243 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
4244 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4245 IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
4247 TRACE("(%p) : pDecl=%p\n", This, pDecl);
4249 This->updateStateBlock->vertexDecl = pDecl;
4250 This->updateStateBlock->changed.vertexDecl = TRUE;
4251 This->updateStateBlock->set.vertexDecl = TRUE;
4253 if (This->isRecordingState) {
4254 TRACE("Recording... not performing anything\n");
4257 if (NULL != pDecl) {
4258 IWineD3DVertexDeclaration_AddRef(pDecl);
4260 if (NULL != oldDecl) {
4261 IWineD3DVertexDeclaration_Release(oldDecl);
4266 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
4267 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4269 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
4271 *ppDecl = This->stateBlock->vertexDecl;
4272 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
4276 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
4277 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4278 IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
4280 This->updateStateBlock->vertexShader = pShader;
4281 This->updateStateBlock->changed.vertexShader = TRUE;
4282 This->updateStateBlock->set.vertexShader = TRUE;
4284 if (This->isRecordingState) {
4285 TRACE("Recording... not performing anything\n");
4288 if (NULL != pShader) {
4289 IWineD3DVertexShader_AddRef(pShader);
4291 if (NULL != oldShader) {
4292 IWineD3DVertexShader_Release(oldShader);
4295 if (pShader != NULL && ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration != NULL) {
4296 TRACE("(%p) : setting vertexDeclaration(%p)\n", This, ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration);
4297 IWineD3DDevice_SetVertexDeclaration(iface, ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration);
4300 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4302 * TODO: merge HAL shaders context switching from prototype
4307 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
4308 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4310 if (NULL == ppShader) {
4311 return WINED3DERR_INVALIDCALL;
4313 *ppShader = This->stateBlock->vertexShader;
4314 if( NULL != *ppShader)
4315 IWineD3DVertexShader_AddRef(*ppShader);
4317 TRACE("(%p) : returning %p\n", This, *ppShader);
4321 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4322 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4325 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4327 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4328 iface, dstData, srcData, type, start, count, registersize);
4330 if (type != WINESHADERCNST_NONE) {
4331 if (srcData == NULL || cnt < 0) {
4332 return WINED3DERR_INVALIDCALL;
4335 CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
4338 for (i = start; i < cnt + start; ++i) {
4339 This->updateStateBlock->changed.vertexShaderConstants[i] = TRUE;
4340 This->updateStateBlock->set.vertexShaderConstants[i] = TRUE;
4341 This->updateStateBlock->vertexShaderConstantT[i] = type;
4347 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4348 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4351 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4353 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4354 iface, dstData, srcData, type, start, count, registersize);
4356 /* Verify that the requested shader constant was populated with the correct type */
4357 for (i = start; i < cnt + start; ++i) {
4358 if (This->updateStateBlock->vertexShaderConstantT[i] != type) {
4359 TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning WINED3DERR_INVALIDCALL\n",
4360 This, type, This->updateStateBlock->vertexShaderConstantT[i]);
4361 return WINED3DERR_INVALIDCALL;
4365 if (dstData == NULL || cnt < 0) {
4366 return WINED3DERR_INVALIDCALL;
4369 CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
4374 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
4375 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4377 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4378 This->updateStateBlock->vertexShaderConstantB,
4380 WINESHADERCNST_BOOL,
4383 sizeof(*pConstantData));
4386 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
4387 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4389 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4391 This->updateStateBlock->vertexShaderConstantB,
4392 WINESHADERCNST_BOOL,
4395 sizeof(*pConstantData));
4398 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
4399 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4401 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4402 This->updateStateBlock->vertexShaderConstantI,
4404 WINESHADERCNST_INTEGER,
4407 4 * sizeof(*pConstantData));
4410 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
4411 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4413 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4415 This->updateStateBlock->vertexShaderConstantI,
4416 WINESHADERCNST_INTEGER,
4419 4 * sizeof(*pConstantData));
4423 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
4424 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4426 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4427 This->updateStateBlock->vertexShaderConstantF,
4429 WINESHADERCNST_FLOAT,
4432 4 * sizeof(*pConstantData));
4435 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
4436 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4438 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4440 This->updateStateBlock->vertexShaderConstantF,
4441 WINESHADERCNST_FLOAT,
4444 4 * sizeof(*pConstantData));
4447 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
4448 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4451 WINESHADERCNST_NONE,
4457 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
4458 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4459 IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader;
4460 This->updateStateBlock->pixelShader = pShader;
4461 This->updateStateBlock->changed.pixelShader = TRUE;
4462 This->updateStateBlock->set.pixelShader = TRUE;
4464 /* Handle recording of state blocks */
4465 if (This->isRecordingState) {
4466 TRACE("Recording... not performing anything\n");
4469 if (NULL != pShader) {
4470 IWineD3DPixelShader_AddRef(pShader);
4472 if (NULL != oldShader) {
4473 IWineD3DPixelShader_Release(oldShader);
4476 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4478 * TODO: merge HAL shaders context switching from prototype
4483 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
4484 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4486 if (NULL == ppShader) {
4487 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
4488 return WINED3DERR_INVALIDCALL;
4491 *ppShader = This->stateBlock->pixelShader;
4492 if (NULL != *ppShader) {
4493 IWineD3DPixelShader_AddRef(*ppShader);
4495 TRACE("(%p) : returning %p\n", This, *ppShader);
4499 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4500 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4503 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4505 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4506 iface, dstData, srcData, type, start, count, registersize);
4508 if (type != WINESHADERCNST_NONE) {
4509 if (srcData == NULL || cnt < 0) {
4510 return WINED3DERR_INVALIDCALL;
4513 CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
4516 for (i = start; i < cnt + start; ++i) {
4517 This->updateStateBlock->changed.pixelShaderConstants[i] = TRUE;
4518 This->updateStateBlock->set.pixelShaderConstants[i] = TRUE;
4519 This->updateStateBlock->pixelShaderConstantT[i] = type;
4525 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4526 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4529 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4531 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4532 iface, dstData, srcData, type, start, count, registersize);
4534 /* Verify that the requested shader constant was populated with the correct type */
4535 for (i = start; i < cnt + start; ++i) {
4536 if (This->updateStateBlock->pixelShaderConstantT[i] != type) {
4537 TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning WINED3DERR_INVALIDCALL\n",
4538 This, type, This->updateStateBlock->pixelShaderConstantT[i]);
4539 return WINED3DERR_INVALIDCALL;
4543 if (dstData == NULL || cnt < 0) {
4544 return WINED3DERR_INVALIDCALL;
4547 CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
4552 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
4553 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4555 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4556 This->updateStateBlock->pixelShaderConstantB,
4558 WINESHADERCNST_BOOL,
4561 sizeof(*pConstantData));
4564 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
4565 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4567 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4569 This->updateStateBlock->pixelShaderConstantB,
4570 WINESHADERCNST_BOOL,
4573 sizeof(*pConstantData));
4576 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
4577 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4579 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4580 This->updateStateBlock->pixelShaderConstantI,
4582 WINESHADERCNST_INTEGER,
4585 4 * sizeof(*pConstantData));
4588 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
4589 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4591 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4593 This->updateStateBlock->pixelShaderConstantI,
4594 WINESHADERCNST_INTEGER,
4597 4 * sizeof(*pConstantData));
4600 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
4601 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4603 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4604 This->updateStateBlock->pixelShaderConstantF,
4606 WINESHADERCNST_FLOAT,
4609 4 * sizeof(*pConstantData));
4612 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
4613 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4615 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4617 This->updateStateBlock->pixelShaderConstantF,
4618 WINESHADERCNST_FLOAT,
4621 4 * sizeof(*pConstantData));
4624 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
4625 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4628 WINESHADERCNST_NONE,
4634 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
4635 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4636 FIXME("(%p) : stub\n", This);
4641 * Apply / Get / Set Texture Stage States
4642 * TODO: Verify against dx9 definitions
4645 /* 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 calling ApplyTextureStageState */
4646 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
4647 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4648 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
4649 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4651 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4653 /* Check that the stage is within limits */
4654 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4655 TRACE("Attempt to access invalid texture rejected\n");
4662 case WINED3DTSS_ALPHAOP :
4663 case WINED3DTSS_COLOROP :
4664 /* nothing to do as moved to drawprim for now */
4666 case WINED3DTSS_ADDRESSW :
4667 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
4668 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
4669 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
4672 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
4673 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
4674 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
4675 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
4678 case WINED3DTSS_TEXCOORDINDEX :
4680 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
4682 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
4683 one flag, you can still specify an index value, which the system uses to
4684 determine the texture wrapping mode.
4685 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
4686 means use the vertex position (camera-space) as the input texture coordinates
4687 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
4688 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
4689 to the TEXCOORDINDEX value */
4692 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
4694 switch (Value & 0xFFFF0000) {
4695 case D3DTSS_TCI_PASSTHRU:
4696 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
4697 glDisable(GL_TEXTURE_GEN_S);
4698 glDisable(GL_TEXTURE_GEN_T);
4699 glDisable(GL_TEXTURE_GEN_R);
4700 glDisable(GL_TEXTURE_GEN_Q);
4701 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
4704 case D3DTSS_TCI_CAMERASPACEPOSITION:
4705 /* CameraSpacePosition means use the vertex position, transformed to camera space,
4706 as the input texture coordinates for this stage's texture transformation. This
4707 equates roughly to EYE_LINEAR */
4709 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4710 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4711 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4712 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4713 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4715 glMatrixMode(GL_MODELVIEW);
4718 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4719 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4720 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4721 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4724 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
4725 glEnable(GL_TEXTURE_GEN_S);
4726 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4727 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4728 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4729 glEnable(GL_TEXTURE_GEN_T);
4730 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4731 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4732 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4733 glEnable(GL_TEXTURE_GEN_R);
4734 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4735 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4736 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4740 case D3DTSS_TCI_CAMERASPACENORMAL:
4742 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4743 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4744 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4745 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4746 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4747 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
4749 glMatrixMode(GL_MODELVIEW);
4752 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4753 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4754 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4755 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4758 glEnable(GL_TEXTURE_GEN_S);
4759 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4760 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4761 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4762 glEnable(GL_TEXTURE_GEN_T);
4763 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4764 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4765 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4766 glEnable(GL_TEXTURE_GEN_R);
4767 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4768 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4769 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4774 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
4776 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4777 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4778 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4779 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4780 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4781 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
4783 glMatrixMode(GL_MODELVIEW);
4786 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4787 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4788 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4789 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4792 glEnable(GL_TEXTURE_GEN_S);
4793 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4794 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4795 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4796 glEnable(GL_TEXTURE_GEN_T);
4797 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4798 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4799 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4800 glEnable(GL_TEXTURE_GEN_R);
4801 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4802 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4803 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4808 /* Unhandled types: */
4811 /* ? disable GL_TEXTURE_GEN_n ? */
4812 glDisable(GL_TEXTURE_GEN_S);
4813 glDisable(GL_TEXTURE_GEN_T);
4814 glDisable(GL_TEXTURE_GEN_R);
4815 glDisable(GL_TEXTURE_GEN_Q);
4816 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
4823 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
4824 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);
4827 case WINED3DTSS_BUMPENVMAT00 :
4828 case WINED3DTSS_BUMPENVMAT01 :
4829 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
4831 case WINED3DTSS_BUMPENVMAT10 :
4832 case WINED3DTSS_BUMPENVMAT11 :
4833 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
4836 case WINED3DTSS_BUMPENVLSCALE :
4837 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4840 case WINED3DTSS_BUMPENVLOFFSET :
4841 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4844 case WINED3DTSS_RESULTARG :
4845 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4849 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
4850 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4859 * Get / Set Texture Stage States
4860 * TODO: Verify against dx9 definitions
4862 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
4863 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4865 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4867 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4869 /* Reject invalid texture units */
4870 if (Stage >= GL_LIMITS(textures)) {
4871 TRACE("Attempt to access invalid texture rejected\n");
4872 return WINED3DERR_INVALIDCALL;
4875 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
4876 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
4877 This->updateStateBlock->textureState[Stage][Type] = Value;
4882 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4883 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4884 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4885 *pValue = This->updateStateBlock->textureState[Stage][Type];
4892 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4894 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4895 IWineD3DBaseTexture *oldTexture;
4897 oldTexture = This->updateStateBlock->textures[Stage];
4898 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
4900 #if 0 /* TODO: check so vertex textures */
4901 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
4902 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
4907 /* Reject invalid texture units */
4908 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4909 WARN("Attempt to access invalid texture rejected\n");
4910 return WINED3DERR_INVALIDCALL;
4913 if(pTexture != NULL) {
4914 /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH; The same is
4915 * the case for WINED3DPOOL_SYSTEMMEM textures unless WINED3DDEVCAPS_TEXTURESYSTEMMORY is set.
4916 * We don't check the caps as GetDeviceCaps is inefficient and we don't set the cap anyway.
4918 if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH || ((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SYSTEMMEM) {
4919 WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
4920 return WINED3DERR_INVALIDCALL;
4924 oldTexture = This->updateStateBlock->textures[Stage];
4925 TRACE("GL_LIMITS %d\n",GL_LIMITS(textures));
4926 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
4928 This->updateStateBlock->set.textures[Stage] = TRUE;
4929 This->updateStateBlock->changed.textures[Stage] = TRUE;
4930 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
4931 This->updateStateBlock->textures[Stage] = pTexture;
4933 /* Handle recording of state blocks */
4934 if (This->isRecordingState) {
4935 TRACE("Recording... not performing anything\n");
4939 /** NOTE: MSDN says that setTexture increases the reference count,
4940 * and the the application nust set the texture back to null (or have a leaky application),
4941 * This means we should pass the refcount up to the parent
4942 *******************************/
4943 if (NULL != This->updateStateBlock->textures[Stage]) {
4944 IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
4947 if (NULL != oldTexture) {
4948 IWineD3DBaseTexture_Release(oldTexture);
4954 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4955 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4956 TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
4958 /* Reject invalid texture units */
4959 if (Stage >= GL_LIMITS(textures)) {
4960 TRACE("Attempt to access invalid texture rejected\n");
4961 return WINED3DERR_INVALIDCALL;
4963 *ppTexture=This->updateStateBlock->textures[Stage];
4965 IWineD3DBaseTexture_AddRef(*ppTexture);
4967 return WINED3DERR_INVALIDCALL;
4974 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
4975 IWineD3DSurface **ppBackBuffer) {
4976 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4977 IWineD3DSwapChain *swapChain;
4980 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4982 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4983 if (hr == WINED3D_OK) {
4984 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4985 IWineD3DSwapChain_Release(swapChain);
4987 *ppBackBuffer = NULL;
4992 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4993 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4994 WARN("(%p) : stub, calling idirect3d for now\n", This);
4995 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4998 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
4999 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5000 IWineD3DSwapChain *swapChain;
5003 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5004 if (hr == WINED3D_OK) {
5005 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
5006 IWineD3DSwapChain_Release(swapChain);
5008 FIXME("(%p) Error getting display mode\n", This);
5013 HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
5014 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5015 TRACE("(%p)->(%p)\n", This, hWnd);
5017 This->ddraw_window = hWnd;
5021 HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
5022 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5023 TRACE("(%p)->(%p)\n", This, hWnd);
5025 *hWnd = This->ddraw_window;
5030 * Stateblock related functions
5033 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
5034 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5035 IWineD3DStateBlockImpl *object;
5036 TRACE("(%p)", This);
5038 if (This->isRecordingState) {
5039 return WINED3DERR_INVALIDCALL;
5042 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
5043 if (NULL == object ) {
5044 FIXME("(%p)Error allocating memory for stateblock\n", This);
5045 return E_OUTOFMEMORY;
5047 TRACE("(%p) creted object %p\n", This, object);
5048 object->wineD3DDevice= This;
5049 /** FIXME: object->parent = parent; **/
5050 object->parent = NULL;
5051 object->blockType = WINED3DSBT_ALL;
5053 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
5055 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
5056 This->updateStateBlock = object;
5057 This->isRecordingState = TRUE;
5059 TRACE("(%p) recording stateblock %p\n",This , object);
5063 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
5064 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5066 if (!This->isRecordingState) {
5067 FIXME("(%p) not recording! returning error\n", This);
5068 *ppStateBlock = NULL;
5069 return WINED3DERR_INVALIDCALL;
5072 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
5073 This->isRecordingState = FALSE;
5074 This->updateStateBlock = This->stateBlock;
5075 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
5076 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
5077 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
5082 * Scene related functions
5084 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
5085 /* At the moment we have no need for any functionality at the beginning
5087 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5088 TRACE("(%p) : stub\n", This);
5092 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
5093 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5094 TRACE("(%p)\n", This);
5096 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
5098 checkGLcall("glFlush");
5100 TRACE("End Scene\n");
5101 if(This->renderTarget != NULL) {
5103 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
5104 IUnknown *targetContainer = NULL;
5105 if (WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
5106 || WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
5107 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
5108 /** always dirtify for now. we must find a better way to see that surface have been modified
5109 (Modifications should will only occur via draw-primitive, but we do need better locking
5110 switching to render-to-texture should remove the overhead though.
5112 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
5113 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
5114 IWineD3DSurface_PreLoad(This->renderTarget);
5115 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
5116 IUnknown_Release(targetContainer);
5119 This->sceneEnded = TRUE;
5124 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
5125 CONST RECT* pSourceRect, CONST RECT* pDestRect,
5126 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
5127 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5128 IWineD3DSwapChain *swapChain = NULL;
5130 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
5132 TRACE("(%p) Presenting the frame\n", This);
5134 for(i = 0 ; i < swapchains ; i ++) {
5136 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
5137 TRACE("presentinng chain %d, %p\n", i, swapChain);
5138 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
5139 IWineD3DSwapChain_Release(swapChain);
5145 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
5146 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
5147 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5149 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
5150 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
5151 when the depth-buffer format does not contain stencil buffer information, this method fails. */
5152 GLbitfield glMask = 0;
5153 GLboolean old_ztest;
5154 GLfloat old_z_clear_value;
5155 GLint old_stencil_clear_value;
5156 GLfloat old_color_clear_value[4];
5158 CONST D3DRECT* curRect;
5160 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
5161 Count, pRects, Flags, Z, Stencil);
5165 glEnable(GL_SCISSOR_TEST);
5166 checkGLcall("glEnable GL_SCISSOR_TEST");
5168 if (Count > 0 && pRects) {
5174 /* Only set the values up once, as they are not changing */
5175 if (Flags & D3DCLEAR_STENCIL) {
5176 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
5177 glClearStencil(Stencil);
5178 checkGLcall("glClearStencil");
5179 glMask = glMask | GL_STENCIL_BUFFER_BIT;
5180 glStencilMask(0xFFFFFFFF);
5183 if (Flags & D3DCLEAR_ZBUFFER) {
5184 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
5185 glDepthMask(GL_TRUE);
5186 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
5188 checkGLcall("glClearDepth");
5189 glMask = glMask | GL_DEPTH_BUFFER_BIT;
5192 if (Flags & D3DCLEAR_TARGET) {
5193 TRACE("Clearing screen with glClear to color %lx\n", Color);
5194 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
5195 glClearColor(D3DCOLOR_R(Color),
5199 checkGLcall("glClearColor");
5201 /* Clear ALL colors! */
5202 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5203 glMask = glMask | GL_COLOR_BUFFER_BIT;
5206 /* Now process each rect in turn */
5207 for (i = 0; i < Count || i == 0; i++) {
5210 /* Note gl uses lower left, width/height */
5211 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
5212 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
5213 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
5214 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
5215 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
5216 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
5217 checkGLcall("glScissor");
5219 glScissor(This->stateBlock->viewport.X,
5220 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
5221 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
5222 This->stateBlock->viewport.Width,
5223 This->stateBlock->viewport.Height);
5224 checkGLcall("glScissor");
5227 /* Clear the selected rectangle (or full screen) */
5229 checkGLcall("glClear");
5231 /* Step to the next rectangle */
5232 if (curRect) curRect = curRect + sizeof(D3DRECT);
5235 /* Restore the old values (why..?) */
5236 if (Flags & D3DCLEAR_STENCIL) {
5237 glClearStencil(old_stencil_clear_value);
5238 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
5240 if (Flags & D3DCLEAR_ZBUFFER) {
5241 glDepthMask(old_ztest);
5242 glClearDepth(old_z_clear_value);
5244 if (Flags & D3DCLEAR_TARGET) {
5245 glClearColor(old_color_clear_value[0],
5246 old_color_clear_value[1],
5247 old_color_clear_value[2],
5248 old_color_clear_value[3]);
5249 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
5250 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
5251 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
5252 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
5255 glDisable(GL_SCISSOR_TEST);
5256 checkGLcall("glDisable");
5265 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
5266 UINT PrimitiveCount) {
5268 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5269 This->stateBlock->streamIsUP = FALSE;
5271 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
5272 debug_d3dprimitivetype(PrimitiveType),
5273 StartVertex, PrimitiveCount);
5274 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
5275 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */, NULL);
5281 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
5282 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
5283 D3DPRIMITIVETYPE PrimitiveType,
5284 INT baseVIndex, UINT minIndex,
5285 UINT NumVertices, UINT startIndex, UINT primCount) {
5287 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5289 IWineD3DIndexBuffer *pIB;
5290 WINED3DINDEXBUFFER_DESC IdxBufDsc;
5292 pIB = This->stateBlock->pIndexData;
5293 This->stateBlock->streamIsUP = FALSE;
5295 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
5296 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5297 minIndex, NumVertices, startIndex, baseVIndex, primCount);
5299 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
5300 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
5306 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
5307 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex, NULL);
5312 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
5313 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
5314 UINT VertexStreamZeroStride) {
5315 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5317 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
5318 debug_d3dprimitivetype(PrimitiveType),
5319 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
5321 /* release the stream source */
5322 if (This->stateBlock->streamSource[0] != NULL) {
5323 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5326 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5327 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5328 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5329 This->stateBlock->streamIsUP = TRUE;
5331 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
5332 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */, NULL);
5333 /* stream zero settings set to null at end, as per the msdn
5334 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
5336 This->stateBlock->streamStride[0] = 0;
5337 This->stateBlock->streamSource[0] = NULL;
5339 /*stream zero settings set to null at end, as per the msdn */
5343 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
5344 UINT MinVertexIndex, UINT NumVertices,
5345 UINT PrimitiveCount, CONST void* pIndexData,
5346 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
5347 UINT VertexStreamZeroStride) {
5349 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5351 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
5352 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5353 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
5354 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
5356 if (IndexDataFormat == WINED3DFMT_INDEX16) {
5362 /* release the stream and index data */
5363 if (This->stateBlock->streamSource[0] != NULL) {
5364 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5366 if (This->stateBlock->pIndexData) {
5367 IWineD3DIndexBuffer_Release(This->stateBlock->pIndexData);
5370 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5371 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5372 This->stateBlock->streamIsUP = TRUE;
5373 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5375 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex, NULL);
5376 /* stream zero settings set to null at end as per the msdn
5377 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
5380 /* stream zero settings set to null at end as per the msdn */
5381 This->stateBlock->streamSource[0] = NULL;
5382 This->stateBlock->streamStride[0] = 0;
5387 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
5389 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0, DrawPrimStrideData);
5392 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
5393 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
5394 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5395 HRESULT hr = WINED3D_OK;
5396 WINED3DRESOURCETYPE sourceType;
5397 WINED3DRESOURCETYPE destinationType;
5400 /* TODO: think about moving the code into IWineD3DBaseTexture */
5402 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
5404 /* verify that the source and destination textures aren't NULL */
5405 if (NULL == pSourceTexture || NULL == pDestinationTexture) {
5406 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
5407 This, pSourceTexture, pDestinationTexture);
5408 hr = WINED3DERR_INVALIDCALL;
5411 if (pSourceTexture == pDestinationTexture) {
5412 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
5413 This, pSourceTexture, pDestinationTexture);
5414 hr = WINED3DERR_INVALIDCALL;
5416 /* Verify that the source and destination textures are the same type */
5417 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
5418 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
5420 if (sourceType != destinationType) {
5421 WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
5423 hr = WINED3DERR_INVALIDCALL;
5426 /* check that both textures have the identical numbers of levels */
5427 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
5428 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
5429 hr = WINED3DERR_INVALIDCALL;
5432 if (WINED3D_OK == hr) {
5434 /* Make sure that the destination texture is loaded */
5435 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
5437 /* Update every surface level of the texture */
5438 levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
5440 switch (sourceType) {
5441 case WINED3DRTYPE_TEXTURE:
5443 IWineD3DSurface *srcSurface;
5444 IWineD3DSurface *destSurface;
5446 for (i = 0 ; i < levels ; ++i) {
5447 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture, i, &srcSurface);
5448 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
5449 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5450 IWineD3DSurface_Release(srcSurface);
5451 IWineD3DSurface_Release(destSurface);
5452 if (WINED3D_OK != hr) {
5453 WARN("(%p) : Call to update surface failed\n", This);
5459 case WINED3DRTYPE_CUBETEXTURE:
5461 IWineD3DSurface *srcSurface;
5462 IWineD3DSurface *destSurface;
5463 WINED3DCUBEMAP_FACES faceType;
5465 for (i = 0 ; i < levels ; ++i) {
5466 /* Update each cube face */
5467 for (faceType = D3DCUBEMAP_FACE_POSITIVE_X; faceType <= D3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
5468 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture, faceType, i, &srcSurface);
5469 if (WINED3D_OK != hr) {
5470 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5472 TRACE("Got srcSurface %p\n", srcSurface);
5474 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
5475 if (WINED3D_OK != hr) {
5476 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5478 TRACE("Got desrSurface %p\n", destSurface);
5480 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5481 IWineD3DSurface_Release(srcSurface);
5482 IWineD3DSurface_Release(destSurface);
5483 if (WINED3D_OK != hr) {
5484 WARN("(%p) : Call to update surface failed\n", This);
5491 #if 0 /* TODO: Add support for volume textures */
5492 case WINED3DRTYPE_VOLUMETEXTURE:
5494 IWineD3DVolume srcVolume = NULL;
5495 IWineD3DSurface destVolume = NULL;
5497 for (i = 0 ; i < levels ; ++i) {
5498 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture, i, &srcVolume);
5499 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
5500 hr = IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
5501 IWineD3DVolume_Release(srcSurface);
5502 IWineD3DVolume_Release(destSurface);
5503 if (WINED3D_OK != hr) {
5504 WARN("(%p) : Call to update volume failed\n", This);
5512 FIXME("(%p) : Unsupported source and destination type\n", This);
5513 hr = WINED3DERR_INVALIDCALL;
5520 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
5521 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
5522 CONST RECT* pDestRect, WINED3DTEXTUREFILTERTYPE Filter) {
5523 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5525 TRACE("(%p) : stub\n", This);
5528 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
5529 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5530 /** TODO: remove remove casts to IWineD3DSurfaceImpl *
5531 * NOTE It may be best to move the code into surface to occomplish this
5532 ****************************************/
5534 WINED3DSURFACE_DESC surfaceDesc;
5535 unsigned int surfaceWidth, surfaceHeight;
5536 glDescriptor *targetGlDescription = NULL;
5537 glDescriptor *surfaceGlDescription = NULL;
5538 IWineD3DSwapChainImpl *container = NULL;
5540 IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
5541 IWineD3DSurface_GetGlDesc(pSurface, &surfaceGlDescription);
5542 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5544 surfaceDesc.Width = &surfaceWidth;
5545 surfaceDesc.Height = &surfaceHeight;
5546 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5547 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
5549 /* Ok, I may need to setup some kind of active swapchain reference on the device */
5550 IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
5552 /* TODO: opengl Context switching for swapchains etc... */
5553 if (NULL != container || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
5554 if (NULL != container && (pRenderTarget == container->backBuffer)) {
5555 glReadBuffer(GL_BACK);
5556 vcheckGLcall("glReadBuffer(GL_BACK)");
5557 } else if ((NULL != container && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
5558 glReadBuffer(GL_FRONT);
5559 vcheckGLcall("glReadBuffer(GL_FRONT)");
5560 } else if (pRenderTarget == This->depthStencilBuffer) {
5561 FIXME("Reading of depthstencil not yet supported\n");
5564 glReadPixels(surfaceGlDescription->target,
5565 surfaceGlDescription->level,
5568 surfaceGlDescription->glFormat,
5569 surfaceGlDescription->glType,
5570 (void *)IWineD3DSurface_GetData(pSurface));
5571 vcheckGLcall("glReadPixels(...)");
5572 if(NULL != container ){
5573 IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
5576 IWineD3DBaseTexture *container;
5577 GLenum textureDimensions = GL_TEXTURE_2D;
5579 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
5580 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
5581 IWineD3DBaseTexture_Release(container);
5583 /* TODO: 2D -> Cube surface coppies etc.. */
5584 if (surfaceGlDescription->target != textureDimensions) {
5585 FIXME("(%p) : Texture dimension mismatch\n", This);
5587 glEnable(textureDimensions);
5588 vcheckGLcall("glEnable(GL_TEXTURE_...)");
5589 /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
5590 glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
5591 vcheckGLcall("glBindTexture");
5592 glGetTexImage(surfaceGlDescription->target,
5593 surfaceGlDescription->level,
5594 surfaceGlDescription->glFormat,
5595 surfaceGlDescription->glType,
5596 (void *)IWineD3DSurface_GetData(pSurface));
5597 glDisable(textureDimensions);
5598 vcheckGLcall("glDisable(GL_TEXTURE_...)");
5605 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
5606 IWineD3DSwapChain *swapChain;
5608 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5609 if(hr == WINED3D_OK) {
5610 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
5611 IWineD3DSwapChain_Release(swapChain);
5616 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5617 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5618 /* return a sensible default */
5620 /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
5621 FIXME("(%p) : stub\n", This);
5625 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5626 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5628 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5629 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5630 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5631 return WINED3DERR_INVALIDCALL;
5633 for (j = 0; j < 256; ++j) {
5634 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
5635 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5636 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
5637 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5639 TRACE("(%p) : returning\n", This);
5643 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5644 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5646 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5647 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5648 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5649 return WINED3DERR_INVALIDCALL;
5651 for (j = 0; j < 256; ++j) {
5652 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
5653 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5654 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
5655 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5657 TRACE("(%p) : returning\n", This);
5661 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5662 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5663 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5664 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5665 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5666 return WINED3DERR_INVALIDCALL;
5668 /*TODO: stateblocks */
5669 This->currentPalette = PaletteNumber;
5670 TRACE("(%p) : returning\n", This);
5674 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
5675 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5676 if (PaletteNumber == NULL) {
5677 WARN("(%p) : returning Invalid Call\n", This);
5678 return WINED3DERR_INVALIDCALL;
5680 /*TODO: stateblocks */
5681 *PaletteNumber = This->currentPalette;
5682 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
5686 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
5687 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5688 static BOOL showFixmes = TRUE;
5690 FIXME("(%p) : stub\n", This);
5694 This->softwareVertexProcessing = bSoftware;
5699 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
5700 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5701 static BOOL showFixmes = TRUE;
5703 FIXME("(%p) : stub\n", This);
5706 return This->softwareVertexProcessing;
5710 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
5711 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5712 IWineD3DSwapChain *swapChain;
5715 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
5717 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5718 if(hr == WINED3D_OK){
5719 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
5720 IWineD3DSwapChain_Release(swapChain);
5722 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
5728 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
5729 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5730 static BOOL showfixmes = TRUE;
5731 if(nSegments != 0.0f) {
5733 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
5740 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
5741 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5742 static BOOL showfixmes = TRUE;
5744 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
5750 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
5751 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5752 /** TODO: remove casts to IWineD3DSurfaceImpl
5753 * NOTE: move code to surface to accomplish this
5754 ****************************************/
5755 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
5756 int srcWidth, srcHeight;
5757 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
5758 WINED3DFORMAT destFormat, srcFormat;
5760 int destLeft, destTop;
5761 WINED3DPOOL srcPool, destPool;
5763 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
5764 glDescriptor *glDescription = NULL;
5765 GLenum textureDimensions = GL_TEXTURE_2D;
5766 IWineD3DBaseTexture *baseTexture;
5768 WINED3DSURFACE_DESC winedesc;
5770 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
5771 memset(&winedesc, 0, sizeof(winedesc));
5772 winedesc.Width = &srcSurfaceWidth;
5773 winedesc.Height = &srcSurfaceHeight;
5774 winedesc.Pool = &srcPool;
5775 winedesc.Format = &srcFormat;
5777 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5779 winedesc.Width = &destSurfaceWidth;
5780 winedesc.Height = &destSurfaceHeight;
5781 winedesc.Pool = &destPool;
5782 winedesc.Format = &destFormat;
5783 winedesc.Size = &destSize;
5785 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5787 if(srcPool != WINED3DPOOL_SYSTEMMEM || destPool != WINED3DPOOL_DEFAULT){
5788 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
5789 return WINED3DERR_INVALIDCALL;
5792 if (destFormat == WINED3DFMT_UNKNOWN) {
5793 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5794 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5796 /* Get the update surface description */
5797 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5800 /* Make sure the surface is loaded and up to date */
5801 IWineD3DSurface_PreLoad(pDestinationSurface);
5803 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
5807 /* this needs to be done in lines if the sourceRect != the sourceWidth */
5808 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
5809 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
5810 destLeft = pDestPoint ? pDestPoint->x : 0;
5811 destTop = pDestPoint ? pDestPoint->y : 0;
5814 /* This function doesn't support compressed textures
5815 the pitch is just bytesPerPixel * width */
5816 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
5817 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
5818 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
5819 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
5821 /* TODO DXT formats */
5823 if(pSourceRect != NULL && pSourceRect->top != 0){
5824 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
5826 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
5828 ,glDescription->level
5833 ,glDescription->glFormat
5834 ,glDescription->glType
5835 ,IWineD3DSurface_GetData(pSourceSurface)
5839 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
5841 /* need to lock the surface to get the data */
5842 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5845 /* TODO: Cube and volume support */
5847 /* not a whole row so we have to do it a line at a time */
5850 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
5851 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5853 for(j = destTop ; j < (srcHeight + destTop) ; j++){
5855 glTexSubImage2D(glDescription->target
5856 ,glDescription->level
5861 ,glDescription->glFormat
5862 ,glDescription->glType
5863 ,data /* could be quicker using */
5868 } else { /* Full width, so just write out the whole texture */
5870 if (WINED3DFMT_DXT1 == destFormat ||
5871 WINED3DFMT_DXT2 == destFormat ||
5872 WINED3DFMT_DXT3 == destFormat ||
5873 WINED3DFMT_DXT4 == destFormat ||
5874 WINED3DFMT_DXT5 == destFormat) {
5875 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
5876 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
5877 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
5878 FIXME("Updating part of a compressed texture is not supported at the moment\n");
5879 } if (destFormat != srcFormat) {
5880 FIXME("Updating mixed format compressed texture is not curretly support\n");
5882 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
5883 glDescription->level,
5884 glDescription->glFormatInternal,
5889 IWineD3DSurface_GetData(pSourceSurface));
5892 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
5897 if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
5899 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
5900 to repack the data from pow2Width/Height to expected Width,Height, this makes the
5901 data returned by GetData non-power2 width/height with hardware non-power2
5902 pow2Width/height are set to surface width height, repacking isn't needed so it
5903 doesn't matter which function gets called. */
5904 glTexSubImage2D(glDescription->target
5905 ,glDescription->level
5910 ,glDescription->glFormat
5911 ,glDescription->glType
5912 ,IWineD3DSurface_GetData(pSourceSurface)
5916 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
5917 glTexSubImage2D(glDescription->target
5918 ,glDescription->level
5921 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
5922 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
5923 ,glDescription->glFormat
5924 ,glDescription->glType
5925 ,IWineD3DSurface_GetData(pSourceSurface)
5931 checkGLcall("glTexSubImage2D");
5933 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
5934 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
5935 * surface bigger than it needs to be hmm.. */
5936 if (WINED3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
5937 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
5938 IWineD3DBaseTexture_Release(baseTexture);
5941 glDisable(textureDimensions); /* This needs to be managed better.... */
5947 /* Used by DirectX 8 */
5948 HRESULT WINAPI IWineD3DDeviceImpl_CopyRects(IWineD3DDevice *iface,
5949 IWineD3DSurface* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
5950 IWineD3DSurface* pDestinationSurface, CONST POINT* pDestPointsArray) {
5952 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5953 HRESULT hr = WINED3D_OK;
5954 WINED3DFORMAT srcFormat, destFormat;
5955 UINT srcWidth, destWidth;
5956 UINT srcHeight, destHeight;
5958 WINED3DSURFACE_DESC winedesc;
5960 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
5961 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
5964 /* Check that the source texture is in WINED3DPOOL_SYSTEMMEM and the destination texture is in WINED3DPOOL_DEFAULT */
5965 memset(&winedesc, 0, sizeof(winedesc));
5967 winedesc.Format = &srcFormat;
5968 winedesc.Width = &srcWidth;
5969 winedesc.Height = &srcHeight;
5970 winedesc.Size = &srcSize;
5971 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5973 winedesc.Format = &destFormat;
5974 winedesc.Width = &destWidth;
5975 winedesc.Height = &destHeight;
5976 winedesc.Size = NULL;
5977 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5979 /* Check that the source and destination formats match */
5980 if (srcFormat != destFormat && WINED3DFMT_UNKNOWN != destFormat) {
5981 WARN("(%p) source %p format must match the dest %p format, returning WINED3DERR_INVALIDCALL\n", This, pSourceSurface, pDestinationSurface);
5982 return WINED3DERR_INVALIDCALL;
5983 } else if (WINED3DFMT_UNKNOWN == destFormat) {
5984 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5985 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5986 destFormat = srcFormat;
5989 /* Quick if complete copy ... */
5990 if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
5992 if (srcWidth == destWidth && srcHeight == destHeight) {
5993 WINED3DLOCKED_RECT lrSrc;
5994 WINED3DLOCKED_RECT lrDst;
5995 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, NULL, WINED3DLOCK_READONLY);
5996 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, NULL, 0L);
5997 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", srcWidth, srcHeight);
5999 memcpy(lrDst.pBits, lrSrc.pBits, srcSize);
6001 IWineD3DSurface_UnlockRect(pSourceSurface);
6002 IWineD3DSurface_UnlockRect(pDestinationSurface);
6003 TRACE("Unlocked src and dst\n");
6007 FIXME("Wanted to copy all surfaces but size not compatible, returning WINED3DERR_INVALIDCALL\n");
6008 hr = WINED3DERR_INVALIDCALL;
6013 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
6015 int bytesPerPixel = ((IWineD3DSurfaceImpl *) pSourceSurface)->bytesPerPixel;
6018 /* Copy rect by rect */
6019 for (i = 0; i < cRects; ++i) {
6020 CONST RECT* r = &pSourceRectsArray[i];
6021 CONST POINT* p = &pDestPointsArray[i];
6024 WINED3DLOCKED_RECT lrSrc;
6025 WINED3DLOCKED_RECT lrDst;
6028 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
6029 if (srcFormat == WINED3DFMT_DXT1) {
6030 copyperline = ((r->right - r->left) * bytesPerPixel) / 2; /* DXT1 is half byte per pixel */
6032 copyperline = ((r->right - r->left) * bytesPerPixel);
6035 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, r, WINED3DLOCK_READONLY);
6036 dest_rect.left = p->x;
6037 dest_rect.top = p->y;
6038 dest_rect.right = p->x + (r->right - r->left);
6039 dest_rect.bottom= p->y + (r->bottom - r->top);
6040 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, &dest_rect, 0L);
6041 TRACE("Locked src and dst\n");
6043 /* Find where to start */
6044 for (j = 0; j < (r->bottom - r->top - 1); ++j) {
6045 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
6047 IWineD3DSurface_UnlockRect(pSourceSurface);
6048 IWineD3DSurface_UnlockRect(pDestinationSurface);
6049 TRACE("Unlocked src and dst\n");
6052 FIXME("Wanted to copy partial surfaces not implemented, returning WINED3DERR_INVALIDCALL\n");
6053 hr = WINED3DERR_INVALIDCALL;
6060 /* Implementation details at http://developer.nvidia.com/attach/6494
6062 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
6063 hmm.. no longer supported use
6064 OpenGL evaluators or tessellate surfaces within your application.
6067 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
6068 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
6069 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6070 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
6071 FIXME("(%p) : Stub\n", This);
6076 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
6077 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
6078 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6079 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
6080 FIXME("(%p) : Stub\n", This);
6084 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
6085 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6086 TRACE("(%p) Handle(%d)\n", This, Handle);
6087 FIXME("(%p) : Stub\n", This);
6091 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
6092 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
6093 fill a surface with a block of color! */
6094 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6095 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
6096 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
6097 IWineD3DSwapChainImpl *container = NULL;
6098 BOOL isRenderTarget = FALSE;
6099 unsigned int width, height;
6100 unsigned int top, left;
6103 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
6105 if (surface->resource.pool != WINED3DPOOL_DEFAULT) {
6106 FIXME("call to colorfill with non WINED3DPOOL_DEFAULT surface\n");
6107 return WINED3DERR_INVALIDCALL;
6110 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
6111 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
6112 if (WINED3DUSAGE_RENDERTARGET & surface->resource.usage) {
6113 /* TODO: make sure we set everything back to the way it was, and context management!
6114 glGetIntegerv(GL_READ_BUFFER, &prev_read);
6115 vcheckGLcall("glIntegerv");
6116 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
6117 vcheckGLcall("glIntegerv");
6119 TRACE("Color fill to render targets may cause some graphics issues\n");
6120 if (pSurface == container->frontBuffer) {
6121 glDrawBuffer(GL_FRONT);
6123 glDrawBuffer(GL_BACK);
6126 if (WINED3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
6127 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld\n", surface, surface->resource.usage);
6129 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
6131 if (container != NULL) {
6132 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
6134 /* we can use GL_STENCIL_INDEX etc...*/
6137 if (container != NULL) {
6138 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
6140 isRenderTarget = TRUE;
6142 /* TODO: drawing to GL_FRONT and GL_BACK */
6143 /* TODO: see if things can be speeded up by using the correct
6144 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
6145 if (pRect == NULL) {
6148 width = surface->currentDesc.Width;
6149 height = surface->currentDesc.Height;
6153 width = pRect->x2 - left;
6154 height = pRect->y2 - top;
6157 data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
6158 /* Create a 'line' of color color, in the correct format for the surface */
6159 for (u = 0 ; u < width ; u ++) {
6164 if (isRenderTarget == FALSE) {
6165 glDescriptor *glDesc;
6166 IWineD3DSurface_PreLoad(pSurface);
6168 /* draw a block of the coloured line on the sufrace */
6169 IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
6170 for (v = 0 ; v< height;v++) {
6171 glTexSubImage2D(glDesc->target
6172 ,glDesc->level /* level */
6182 checkGLcall("glTexSubImage2D");
6184 glDisable(glDesc->target);
6186 /** FIXME: Using GLClear may be faster **/
6187 glRasterPos2i(left, top);
6188 glPixelZoom((float)width ,(float)height);
6189 glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
6190 checkGLcall("glDrawPixels");
6192 HeapFree(GetProcessHeap(), 0, data);
6198 /* rendertarget and deptth stencil functions */
6199 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
6200 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6202 /* FIXME: Implelent RenderTargetIndex >0 */
6203 if(RenderTargetIndex > 0)
6204 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
6206 *ppRenderTarget = This->renderTarget;
6207 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
6208 /* Note inc ref on returned surface */
6209 if(*ppRenderTarget != NULL)
6210 IWineD3DSurface_AddRef(*ppRenderTarget);
6214 HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
6215 FIXME("This call is a d3d7 merge stub. It will be implemented later\n");
6216 return WINED3DERR_INVALIDCALL;
6219 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
6220 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6221 *ppZStencilSurface = This->depthStencilBuffer;
6222 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
6224 if(*ppZStencilSurface != NULL) {
6225 /* Note inc ref on returned surface */
6226 IWineD3DSurface_AddRef(*ppZStencilSurface);
6231 /* internal static helper functions */
6232 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
6233 IWineD3DSurface *RenderSurface);
6235 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
6236 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6237 HRESULT hr = WINED3D_OK;
6238 WINED3DVIEWPORT viewport;
6240 TRACE("(%p) Swapping rendertarget\n",This);
6241 if (RenderTargetIndex > 0) {
6242 FIXME("(%p) Render targets other than the first are not supported\n",This);
6243 RenderTargetIndex = 0;
6246 /* MSDN says that null disables the render target
6247 but a device must always be associated with a render target
6248 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
6250 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
6253 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
6254 FIXME("Trying to set render target 0 to NULL\n");
6255 return WINED3DERR_INVALIDCALL;
6257 /* TODO: replace Impl* usage with interface usage */
6258 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
6259 FIXME("(%p)Trying to set the render target to a surface(%p) that wasn't created with a usage of WINED3DUSAGE_RENDERTARGET\n",This ,pRenderTarget);
6260 return WINED3DERR_INVALIDCALL;
6262 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
6263 * builds, but I think wine counts as a 'debug' build for now.
6264 ******************************/
6265 /* If we are trying to set what we already have, don't bother */
6266 if (pRenderTarget == This->renderTarget) {
6267 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6269 /* Otherwise, set the render target up */
6271 if (FALSE == This->sceneEnded) {
6272 IWineD3DDevice_EndScene(iface);
6274 TRACE("clearing renderer\n");
6275 /* IWineD3DDeviceImpl_CleanRender(iface); */
6276 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6277 depending on the renter target implementation being used.
6278 A shared context implementation will share all buffers between all rendertargets (including swapchains),
6279 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6280 stencil buffer and incure an extra memory overhead */
6281 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
6284 if (SUCCEEDED(hr)) {
6285 /* Finally, reset the viewport as the MSDN states. */
6286 /* TODO: Replace impl usage */
6287 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
6288 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
6291 viewport.MaxZ = 1.0f;
6292 viewport.MinZ = 0.0f;
6293 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
6295 FIXME("Unknown error setting the render target\n");
6297 This->sceneEnded = FALSE;
6301 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
6302 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6303 HRESULT hr = WINED3D_OK;
6304 IWineD3DSurface *tmp;
6306 TRACE("(%p) Swapping z-buffer\n",This);
6308 if (pNewZStencil == This->stencilBufferTarget) {
6309 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6311 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6312 * depending on the renter target implementation being used.
6313 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
6314 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6315 * stencil buffer and incure an extra memory overhead
6316 ******************************************************/
6319 tmp = This->stencilBufferTarget;
6320 This->stencilBufferTarget = pNewZStencil;
6321 /* should we be calling the parent or the wined3d surface? */
6322 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
6323 if (NULL != tmp) IWineD3DSurface_Release(tmp);
6325 /** TODO: glEnable/glDisable on depth/stencil depending on
6326 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
6327 **********************************************************/
6334 #ifdef GL_VERSION_1_3
6335 /* Internal functions not in DirectX */
6336 /** TODO: move this off to the opengl context manager
6337 *(the swapchain doesn't need to know anything about offscreen rendering!)
6338 ****************************************************/
6340 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
6342 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6344 TRACE("(%p), %p\n", This, swapchain);
6346 if (swapchain->win != swapchain->drawable) {
6347 /* Set everything back the way it ws */
6348 swapchain->render_ctx = swapchain->glCtx;
6349 swapchain->drawable = swapchain->win;
6354 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
6355 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
6356 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6359 unsigned int height;
6360 WINED3DFORMAT format;
6361 WINED3DSURFACE_DESC surfaceDesc;
6362 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
6363 surfaceDesc.Width = &width;
6364 surfaceDesc.Height = &height;
6365 surfaceDesc.Format = &format;
6366 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
6368 /* I need a get width/height function (and should do something with the format) */
6369 for (i = 0; i < CONTEXT_CACHE; ++i) {
6370 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
6371 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
6372 the pSurface can be set to 0 allowing it to be reused from cache **/
6373 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
6374 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
6375 *context = &This->contextCache[i];
6378 if (This->contextCache[i].Width == 0) {
6379 This->contextCache[i].pSurface = pSurface;
6380 This->contextCache[i].Width = width;
6381 This->contextCache[i].Height = height;
6382 *context = &This->contextCache[i];
6386 if (i == CONTEXT_CACHE) {
6387 int minUsage = 0x7FFFFFFF; /* MAX_INT */
6388 glContext *dropContext = 0;
6389 for (i = 0; i < CONTEXT_CACHE; i++) {
6390 if (This->contextCache[i].usedcount < minUsage) {
6391 dropContext = &This->contextCache[i];
6392 minUsage = This->contextCache[i].usedcount;
6395 /* clean up the context (this doesn't work for ATI at the moment */
6397 glXDestroyContext(swapchain->display, dropContext->context);
6398 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
6401 dropContext->Width = 0;
6402 dropContext->pSurface = pSurface;
6403 *context = dropContext;
6405 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
6406 for (i = 0; i < CONTEXT_CACHE; i++) {
6407 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
6411 if (*context != NULL)
6414 return E_OUTOFMEMORY;
6418 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
6419 * the functionality needs splitting up so that we don't do more than we should do.
6420 * this only seems to impact performance a little.
6421 ******************************/
6422 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
6423 IWineD3DSurface *RenderSurface) {
6424 HRESULT ret = WINED3DERR_INVALIDCALL;
6427 * Currently only active for GLX >= 1.3
6428 * for others versions we'll have to use GLXPixmaps
6430 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
6431 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
6432 * so only check OpenGL version
6433 * ..........................
6434 * I don't believe that it is a problem with NVidia headers,
6435 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
6436 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
6438 * Your application will report GLX version 1.2 on glXQueryVersion.
6439 * However, it is safe to call the GLX 1.3 functions as described below.
6441 #if defined(GL_VERSION_1_3)
6443 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6444 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
6445 IWineD3DSurface *tmp;
6446 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
6447 GLXFBConfig* cfgs = NULL;
6451 IWineD3DSwapChain *currentSwapchain;
6452 IWineD3DSwapChainImpl *swapchain;
6453 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
6454 * but switch them off if the StencilSurface is set to NULL
6455 ** *********************************************************/
6456 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
6457 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
6460 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
6461 it StencilSurface != NULL && zBufferTarget == NULL switch it on
6464 #define PUSH1(att) attribs[nAttribs++] = (att);
6465 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
6467 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
6469 /** TODO: remove the reff to Impl (context manager should fix this!) **/
6470 IWineD3DSwapChainImpl *impSwapChain;
6471 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
6472 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
6473 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
6478 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
6479 PUSH2(GLX_X_RENDERABLE, TRUE);
6480 PUSH2(GLX_DOUBLEBUFFER, TRUE);
6481 TRACE("calling makeglcfg\n");
6482 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
6485 TRACE("calling chooseFGConfig\n");
6486 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
6489 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
6490 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
6491 why we failed and only show this message once! */
6492 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"); /**/
6494 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
6495 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
6496 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
6497 PUSH2(GLX_DOUBLEBUFFER, FALSE);
6498 TRACE("calling makeglcfg\n");
6499 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
6501 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
6508 for (i = 0; i < nCfgs; ++i) {
6509 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
6510 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
6511 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
6514 if (NULL != This->renderTarget) {
6516 vcheckGLcall("glFlush");
6517 /** This is only useful if the old render target was a swapchain,
6518 * we need to supercede this with a function that displays
6519 * the current buffer on the screen. This is easy to do in glx1.3 but
6520 * we need to do copy-write pixels in glx 1.2.
6521 ************************************************/
6522 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
6524 printf("Hit Enter to get next frame ...\n");
6530 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain) != WINED3D_OK) {
6531 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
6532 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
6536 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
6537 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
6538 **********************************************************************/
6539 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == WINED3D_OK) {
6540 /* We also need to make sure that the lights &co are also in the context of the swapchains */
6541 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
6542 TRACE("making swapchain active\n");
6543 if (RenderSurface != This->renderTarget) {
6544 if (RenderSurface == swapchain->backBuffer) {
6546 /* This could be flagged so that some operations work directly with the front buffer */
6547 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
6549 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
6551 TRACE("Error in setting current context: context %p drawable %ld !\n",
6552 impSwapChain->glCtx, impSwapChain->win);
6555 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
6557 checkGLcall("glXMakeContextCurrent");
6559 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
6561 else if (pbuffer_support == TRUE && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
6563 /** ********************************************************************
6564 * This is a quickly hacked out implementation of offscreen textures.
6565 * It will work in most cases but there may be problems if the client
6566 * modifies the texture directly, or expects the contents of the rendertarget
6569 * There are some real speed vs compatibility issues here:
6570 * we should really use a new context for every texture, but that eats ram.
6571 * we should also be restoring the texture to the pbuffer but that eats CPU
6572 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
6573 * but if this means reusing the display backbuffer then we need to make sure that
6574 * states are correctly preserved.
6575 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
6576 * and gain a good performance increase at the cost of compatibility.
6577 * I would suggest that, when this is the case, a user configurable flag be made
6578 * available, allowing the user to choose the best emulated experience for them.
6579 *********************************************************************/
6581 XVisualInfo *visinfo;
6582 glContext *newContext;
6584 /* Here were using a shared context model */
6585 if (WINED3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
6586 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6589 /* If the context doesn't exist then create a new one */
6590 /* TODO: This should really be part of findGlContext */
6591 if (NULL == newContext->context) {
6593 TRACE("making new buffer\n");
6595 PUSH2(GLX_PBUFFER_WIDTH, newContext->Width);
6596 PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
6599 newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
6601 /** ****************************************
6602 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
6604 * In future releases, we may provide the calls glXCreateNewContext,
6605 * glXQueryDrawable and glXMakeContextCurrent.
6606 * so until then we have to use glXGetVisualFromFBConfig &co..
6607 ********************************************/
6610 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
6612 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
6614 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
6618 if (NULL == newContext || NULL == newContext->context) {
6619 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6621 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
6622 if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
6623 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
6626 /* Clean up the old context */
6627 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
6628 /* Set the current context of the swapchain to the new context */
6629 impSwapChain->drawable = newContext->drawable;
6630 impSwapChain->render_ctx = newContext->context;
6634 #if 1 /* Apply the stateblock to the new context
6635 FIXME: This is a bit of a hack, each context should know it's own state,
6636 the directX current directX state should then be applied to the context */
6639 IWineD3DStateBlockImpl *oldUpdateStateBlock;
6640 oldUpdateStateBlock = This->updateStateBlock;
6641 oldRecording= This->isRecordingState;
6642 This->isRecordingState = FALSE;
6643 This->updateStateBlock = This->stateBlock;
6644 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
6646 This->isRecordingState = oldRecording;
6647 This->updateStateBlock = oldUpdateStateBlock;
6652 /* clean up the current rendertargets swapchain (if it belonged to one) */
6653 if (currentSwapchain != NULL) {
6654 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
6657 /* Were done with the opengl context management, setup the rendertargets */
6659 tmp = This->renderTarget;
6660 This->renderTarget = RenderSurface;
6661 IWineD3DSurface_AddRef(This->renderTarget);
6662 IWineD3DSurface_Release(tmp);
6668 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
6669 /* Check that the container is not a swapchain member */
6671 IWineD3DSwapChain *tmpSwapChain;
6672 if (WINED3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
6673 This->renderUpsideDown = TRUE;
6675 This->renderUpsideDown = FALSE;
6676 IWineD3DSwapChain_Release(tmpSwapChain);
6678 /* Force updating the cull mode */
6679 TRACE("setting render state\n");
6680 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
6681 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
6683 /* Force updating projection matrix */
6684 This->last_was_rhw = FALSE;
6685 This->proj_valid = FALSE;
6693 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
6694 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
6699 if ( NULL != impSwapChain) {
6700 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
6708 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
6709 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
6710 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6711 /* TODO: the use of Impl is deprecated. */
6712 /* some basic validation checks */
6713 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
6715 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
6717 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
6718 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
6719 return WINED3DERR_INVALIDCALL;
6721 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
6722 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
6723 return WINED3DERR_INVALIDCALL;
6725 /* TODO: make the cursor 'real' */
6727 This->xHotSpot = XHotSpot;
6728 This->yHotSpot = YHotSpot;
6733 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
6734 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6735 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
6737 This->xScreenSpace = XScreenSpace;
6738 This->yScreenSpace = YScreenSpace;
6744 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
6745 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6746 TRACE("(%p) : visible(%d)\n", This, bShow);
6748 This->bCursorVisible = bShow;
6753 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
6754 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6755 TRACE("(%p) : state (%lu)\n", This, This->state);
6756 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
6757 switch (This->state) {
6760 case WINED3DERR_DEVICELOST:
6762 ResourceList *resourceList = This->resources;
6763 while (NULL != resourceList) {
6764 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
6765 return WINED3DERR_DEVICENOTRESET;
6766 resourceList = resourceList->next;
6768 return WINED3DERR_DEVICELOST;
6770 case WINED3DERR_DRIVERINTERNALERROR:
6771 return WINED3DERR_DRIVERINTERNALERROR;
6775 return WINED3DERR_DRIVERINTERNALERROR;
6779 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
6780 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6781 /** FIXME: Resource tracking needs to be done,
6782 * The closes we can do to this is set the priorities of all managed textures low
6783 * and then reset them.
6784 ***********************************************************/
6785 FIXME("(%p) : stub\n", This);
6789 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
6790 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6791 /** FIXME: Resource trascking needs to be done.
6792 * in effect this pulls all non only default
6793 * textures out of video memory and deletes all glTextures (glDeleteTextures)
6794 * and should clear down the context and set it up according to pPresentationParameters
6795 ***********************************************************/
6796 FIXME("(%p) : stub\n", This);
6800 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
6801 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6802 /** FIXME: always true at the moment **/
6803 if(bEnableDialogs == FALSE) {
6804 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
6810 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
6811 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6812 TRACE("(%p) : pParameters %p\n", This, pParameters);
6814 *pParameters = This->createParms;
6818 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
6819 IWineD3DSwapChain *swapchain;
6820 HRESULT hrc = WINED3D_OK;
6822 TRACE("Relaying to swapchain\n");
6824 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
6825 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
6826 IWineD3DSwapChain_Release(swapchain);
6831 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
6832 IWineD3DSwapChain *swapchain;
6833 HRESULT hrc = WINED3D_OK;
6835 TRACE("Relaying to swapchain\n");
6837 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
6838 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
6839 IWineD3DSwapChain_Release(swapchain);
6845 /** ********************************************************
6846 * Notification functions
6847 ** ********************************************************/
6848 /** This function must be called in the release of a resource when ref == 0,
6849 * the contents of resource must still be correct,
6850 * any handels to other resource held by the caller must be closed
6851 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
6852 *****************************************************/
6853 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6854 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6855 ResourceList* resourceList;
6857 TRACE("(%p) : resource %p\n", This, resource);
6859 EnterCriticalSection(&resourceStoreCriticalSection);
6861 /* add a new texture to the frot of the linked list */
6862 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
6863 resourceList->resource = resource;
6865 /* Get the old head */
6866 resourceList->next = This->resources;
6868 This->resources = resourceList;
6869 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
6872 LeaveCriticalSection(&resourceStoreCriticalSection);
6877 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6878 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6879 ResourceList* resourceList = NULL;
6880 ResourceList* previousResourceList = NULL;
6882 TRACE("(%p) : resource %p\n", This, resource);
6885 EnterCriticalSection(&resourceStoreCriticalSection);
6887 resourceList = This->resources;
6889 while (resourceList != NULL) {
6890 if(resourceList->resource == resource) break;
6891 previousResourceList = resourceList;
6892 resourceList = resourceList->next;
6895 if (resourceList == NULL) {
6896 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
6898 LeaveCriticalSection(&resourceStoreCriticalSection);
6902 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
6904 /* make sure we don't leave a hole in the list */
6905 if (previousResourceList != NULL) {
6906 previousResourceList->next = resourceList->next;
6908 This->resources = resourceList->next;
6912 LeaveCriticalSection(&resourceStoreCriticalSection);
6918 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
6919 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6922 TRACE("(%p) : resource %p\n", This, resource);
6923 switch(IWineD3DResource_GetType(resource)){
6924 case WINED3DRTYPE_SURFACE:
6925 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
6927 case WINED3DRTYPE_TEXTURE:
6928 case WINED3DRTYPE_CUBETEXTURE:
6929 case WINED3DRTYPE_VOLUMETEXTURE:
6930 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
6931 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6932 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6933 This->stateBlock->textures[counter] = NULL;
6935 if (This->updateStateBlock != This->stateBlock ){
6936 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6937 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6938 This->updateStateBlock->textures[counter] = NULL;
6943 case WINED3DRTYPE_VOLUME:
6944 /* TODO: nothing really? */
6946 case WINED3DRTYPE_VERTEXBUFFER:
6947 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
6950 TRACE("Cleaning up stream pointers\n");
6952 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
6953 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
6954 FINDOUT: should changes.streamSource[StreamNumber] be set ?
6956 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6957 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
6958 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
6959 This->updateStateBlock->streamSource[streamNumber] = 0;
6960 /* Set changed flag? */
6963 if (This->stateBlock != NULL ) { /* only happens if there is an error in the application, or on reset/release (because we don't manage internal tracking properly) */
6964 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
6965 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
6966 This->stateBlock->streamSource[streamNumber] = 0;
6969 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
6970 else { /* This shouldn't happen */
6971 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
6978 case WINED3DRTYPE_INDEXBUFFER:
6979 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
6980 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6981 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6982 This->updateStateBlock->pIndexData = NULL;
6985 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
6986 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6987 This->stateBlock->pIndexData = NULL;
6993 FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
6998 /* Remove the resoruce from the resourceStore */
6999 IWineD3DDeviceImpl_RemoveResource(iface, resource);
7001 TRACE("Resource released\n");
7006 /** This function is to be called by the swapchain when it is released and it's ref = 0
7007 *****************************************************/
7008 void WINAPI IWineD3DDeviceImpl_SwapChainReleased(IWineD3DDevice *iface, IWineD3DSwapChain *swapChain){
7009 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7010 SwapChainList **nextSwapchain;
7011 nextSwapchain = &This->swapchains;
7013 /* Check to see if the swapchian is being used as the render target */
7014 if (This->renderTarget != NULL) {
7015 IWineD3DSurface *swapchainBackBuffer;
7017 IWineD3DSwapChain_GetBackBuffer(swapChain, 0 ,( D3DBACKBUFFER_TYPE) 0, &swapchainBackBuffer);
7018 if (This->renderTarget == swapchainBackBuffer) {
7019 /* Don't know what to do, so warn and carry on as usual (which in this case leaves the renderterget in limbo) */
7020 FIXME("Atempting to release a swapchain that is currently beuing used as a render target, behaviour is undefined\n");
7024 /* Go through the swapchain list and try to find the swapchain being released */
7025 while(*nextSwapchain != NULL && (*nextSwapchain)->swapchain != swapChain) {
7026 nextSwapchain = &(*nextSwapchain)->next;
7029 /* Check to see if we found the swapchain */
7030 if (NULL != *nextSwapchain) {
7031 /* We found the swapchain so remove it from the list */
7032 TRACE("(%p) releasing swapchain(%p)\n", iface, swapChain);
7033 HeapFree(GetProcessHeap(), 0 , *nextSwapchain);
7034 *nextSwapchain = (*nextSwapchain)->next;
7036 /* We didn't find the swapchain on the list, this can only heppen because of a programming error in wined3d */
7037 FIXME("(%p) Attempting to release a swapchain (%p) that hasn't been stored\n", iface, swapChain);
7040 TRACE("swapchain (%p) released\n", swapChain);
7044 /**********************************************************
7045 * IWineD3DDevice VTbl follows
7046 **********************************************************/
7048 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
7050 /*** IUnknown methods ***/
7051 IWineD3DDeviceImpl_QueryInterface,
7052 IWineD3DDeviceImpl_AddRef,
7053 IWineD3DDeviceImpl_Release,
7054 /*** IWineD3DDevice methods ***/
7055 IWineD3DDeviceImpl_GetParent,
7056 /*** Creation methods**/
7057 IWineD3DDeviceImpl_CreateVertexBuffer,
7058 IWineD3DDeviceImpl_CreateIndexBuffer,
7059 IWineD3DDeviceImpl_CreateStateBlock,
7060 IWineD3DDeviceImpl_CreateSurface,
7061 IWineD3DDeviceImpl_CreateTexture,
7062 IWineD3DDeviceImpl_CreateVolumeTexture,
7063 IWineD3DDeviceImpl_CreateVolume,
7064 IWineD3DDeviceImpl_CreateCubeTexture,
7065 IWineD3DDeviceImpl_CreateQuery,
7066 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
7067 IWineD3DDeviceImpl_CreateVertexDeclaration,
7068 IWineD3DDeviceImpl_CreateVertexShader,
7069 IWineD3DDeviceImpl_CreatePixelShader,
7070 IWineD3DDeviceImpl_CreatePalette,
7071 /*** Odd functions **/
7072 IWineD3DDeviceImpl_Init3D,
7073 IWineD3DDeviceImpl_Uninit3D,
7074 IWineD3DDeviceImpl_EnumDisplayModes,
7075 IWineD3DDeviceImpl_EvictManagedResources,
7076 IWineD3DDeviceImpl_GetAvailableTextureMem,
7077 IWineD3DDeviceImpl_GetBackBuffer,
7078 IWineD3DDeviceImpl_GetCreationParameters,
7079 IWineD3DDeviceImpl_GetDeviceCaps,
7080 IWineD3DDeviceImpl_GetDirect3D,
7081 IWineD3DDeviceImpl_GetDisplayMode,
7082 IWineD3DDeviceImpl_SetDisplayMode,
7083 IWineD3DDeviceImpl_GetHWND,
7084 IWineD3DDeviceImpl_SetHWND,
7085 IWineD3DDeviceImpl_GetNumberOfSwapChains,
7086 IWineD3DDeviceImpl_GetRasterStatus,
7087 IWineD3DDeviceImpl_GetSwapChain,
7088 IWineD3DDeviceImpl_Reset,
7089 IWineD3DDeviceImpl_SetDialogBoxMode,
7090 IWineD3DDeviceImpl_SetCursorProperties,
7091 IWineD3DDeviceImpl_SetCursorPosition,
7092 IWineD3DDeviceImpl_ShowCursor,
7093 IWineD3DDeviceImpl_TestCooperativeLevel,
7094 IWineD3DDeviceImpl_EnumZBufferFormats,
7095 IWineD3DDeviceImpl_EnumTextureFormats,
7096 /*** Getters and setters **/
7097 IWineD3DDeviceImpl_SetClipPlane,
7098 IWineD3DDeviceImpl_GetClipPlane,
7099 IWineD3DDeviceImpl_SetClipStatus,
7100 IWineD3DDeviceImpl_GetClipStatus,
7101 IWineD3DDeviceImpl_SetCurrentTexturePalette,
7102 IWineD3DDeviceImpl_GetCurrentTexturePalette,
7103 IWineD3DDeviceImpl_SetDepthStencilSurface,
7104 IWineD3DDeviceImpl_GetDepthStencilSurface,
7105 IWineD3DDeviceImpl_SetFVF,
7106 IWineD3DDeviceImpl_GetFVF,
7107 IWineD3DDeviceImpl_SetGammaRamp,
7108 IWineD3DDeviceImpl_GetGammaRamp,
7109 IWineD3DDeviceImpl_SetIndices,
7110 IWineD3DDeviceImpl_GetIndices,
7111 IWineD3DDeviceImpl_SetLight,
7112 IWineD3DDeviceImpl_GetLight,
7113 IWineD3DDeviceImpl_SetLightEnable,
7114 IWineD3DDeviceImpl_GetLightEnable,
7115 IWineD3DDeviceImpl_SetMaterial,
7116 IWineD3DDeviceImpl_GetMaterial,
7117 IWineD3DDeviceImpl_SetNPatchMode,
7118 IWineD3DDeviceImpl_GetNPatchMode,
7119 IWineD3DDeviceImpl_SetPaletteEntries,
7120 IWineD3DDeviceImpl_GetPaletteEntries,
7121 IWineD3DDeviceImpl_SetPixelShader,
7122 IWineD3DDeviceImpl_GetPixelShader,
7123 IWineD3DDeviceImpl_SetPixelShaderConstant,
7124 IWineD3DDeviceImpl_GetPixelShaderConstant,
7125 IWineD3DDeviceImpl_SetPixelShaderConstantB,
7126 IWineD3DDeviceImpl_GetPixelShaderConstantB,
7127 IWineD3DDeviceImpl_SetPixelShaderConstantI,
7128 IWineD3DDeviceImpl_GetPixelShaderConstantI,
7129 IWineD3DDeviceImpl_SetPixelShaderConstantF,
7130 IWineD3DDeviceImpl_GetPixelShaderConstantF,
7131 IWineD3DDeviceImpl_SetPixelShaderConstantN,
7132 IWineD3DDeviceImpl_SetRenderState,
7133 IWineD3DDeviceImpl_GetRenderState,
7134 IWineD3DDeviceImpl_SetRenderTarget,
7135 IWineD3DDeviceImpl_GetRenderTarget,
7136 IWineD3DDeviceImpl_SetFrontBackBuffers,
7137 IWineD3DDeviceImpl_SetSamplerState,
7138 IWineD3DDeviceImpl_GetSamplerState,
7139 IWineD3DDeviceImpl_SetScissorRect,
7140 IWineD3DDeviceImpl_GetScissorRect,
7141 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
7142 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
7143 IWineD3DDeviceImpl_SetStreamSource,
7144 IWineD3DDeviceImpl_GetStreamSource,
7145 IWineD3DDeviceImpl_SetStreamSourceFreq,
7146 IWineD3DDeviceImpl_GetStreamSourceFreq,
7147 IWineD3DDeviceImpl_SetTexture,
7148 IWineD3DDeviceImpl_GetTexture,
7149 IWineD3DDeviceImpl_SetTextureStageState,
7150 IWineD3DDeviceImpl_GetTextureStageState,
7151 IWineD3DDeviceImpl_SetTransform,
7152 IWineD3DDeviceImpl_GetTransform,
7153 IWineD3DDeviceImpl_SetVertexDeclaration,
7154 IWineD3DDeviceImpl_GetVertexDeclaration,
7155 IWineD3DDeviceImpl_SetVertexShader,
7156 IWineD3DDeviceImpl_GetVertexShader,
7157 IWineD3DDeviceImpl_SetVertexShaderConstant,
7158 IWineD3DDeviceImpl_GetVertexShaderConstant,
7159 IWineD3DDeviceImpl_SetVertexShaderConstantB,
7160 IWineD3DDeviceImpl_GetVertexShaderConstantB,
7161 IWineD3DDeviceImpl_SetVertexShaderConstantI,
7162 IWineD3DDeviceImpl_GetVertexShaderConstantI,
7163 IWineD3DDeviceImpl_SetVertexShaderConstantF,
7164 IWineD3DDeviceImpl_GetVertexShaderConstantF,
7165 IWineD3DDeviceImpl_SetVertexShaderConstantN,
7166 IWineD3DDeviceImpl_SetViewport,
7167 IWineD3DDeviceImpl_GetViewport,
7168 IWineD3DDeviceImpl_MultiplyTransform,
7169 IWineD3DDeviceImpl_ValidateDevice,
7170 IWineD3DDeviceImpl_ProcessVertices,
7171 /*** State block ***/
7172 IWineD3DDeviceImpl_BeginStateBlock,
7173 IWineD3DDeviceImpl_EndStateBlock,
7174 /*** Scene management ***/
7175 IWineD3DDeviceImpl_BeginScene,
7176 IWineD3DDeviceImpl_EndScene,
7177 IWineD3DDeviceImpl_Present,
7178 IWineD3DDeviceImpl_Clear,
7180 IWineD3DDeviceImpl_DrawPrimitive,
7181 IWineD3DDeviceImpl_DrawIndexedPrimitive,
7182 IWineD3DDeviceImpl_DrawPrimitiveUP,
7183 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
7184 IWineD3DDeviceImpl_DrawPrimitiveStrided,
7185 IWineD3DDeviceImpl_DrawRectPatch,
7186 IWineD3DDeviceImpl_DrawTriPatch,
7187 IWineD3DDeviceImpl_DeletePatch,
7188 IWineD3DDeviceImpl_ColorFill,
7189 IWineD3DDeviceImpl_UpdateTexture,
7190 IWineD3DDeviceImpl_UpdateSurface,
7191 IWineD3DDeviceImpl_CopyRects,
7192 IWineD3DDeviceImpl_StretchRect,
7193 IWineD3DDeviceImpl_GetRenderTargetData,
7194 IWineD3DDeviceImpl_GetFrontBufferData,
7195 /*** Internal use IWineD3DDevice methods ***/
7196 IWineD3DDeviceImpl_SetupTextureStates,
7197 /*** object tracking ***/
7198 IWineD3DDeviceImpl_SwapChainReleased,
7199 IWineD3DDeviceImpl_ResourceReleased
7203 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
7204 WINED3DRS_ALPHABLENDENABLE ,
7205 WINED3DRS_ALPHAFUNC ,
7206 WINED3DRS_ALPHAREF ,
7207 WINED3DRS_ALPHATESTENABLE ,
7209 WINED3DRS_COLORWRITEENABLE ,
7210 WINED3DRS_DESTBLEND ,
7211 WINED3DRS_DITHERENABLE ,
7212 WINED3DRS_FILLMODE ,
7213 WINED3DRS_FOGDENSITY ,
7215 WINED3DRS_FOGSTART ,
7216 WINED3DRS_LASTPIXEL ,
7217 WINED3DRS_SHADEMODE ,
7218 WINED3DRS_SRCBLEND ,
7219 WINED3DRS_STENCILENABLE ,
7220 WINED3DRS_STENCILFAIL ,
7221 WINED3DRS_STENCILFUNC ,
7222 WINED3DRS_STENCILMASK ,
7223 WINED3DRS_STENCILPASS ,
7224 WINED3DRS_STENCILREF ,
7225 WINED3DRS_STENCILWRITEMASK ,
7226 WINED3DRS_STENCILZFAIL ,
7227 WINED3DRS_TEXTUREFACTOR ,
7238 WINED3DRS_ZWRITEENABLE
7241 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
7242 WINED3DTSS_ADDRESSW ,
7243 WINED3DTSS_ALPHAARG0 ,
7244 WINED3DTSS_ALPHAARG1 ,
7245 WINED3DTSS_ALPHAARG2 ,
7246 WINED3DTSS_ALPHAOP ,
7247 WINED3DTSS_BUMPENVLOFFSET ,
7248 WINED3DTSS_BUMPENVLSCALE ,
7249 WINED3DTSS_BUMPENVMAT00 ,
7250 WINED3DTSS_BUMPENVMAT01 ,
7251 WINED3DTSS_BUMPENVMAT10 ,
7252 WINED3DTSS_BUMPENVMAT11 ,
7253 WINED3DTSS_COLORARG0 ,
7254 WINED3DTSS_COLORARG1 ,
7255 WINED3DTSS_COLORARG2 ,
7256 WINED3DTSS_COLOROP ,
7257 WINED3DTSS_RESULTARG ,
7258 WINED3DTSS_TEXCOORDINDEX ,
7259 WINED3DTSS_TEXTURETRANSFORMFLAGS
7262 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
7263 WINED3DSAMP_ADDRESSU ,
7264 WINED3DSAMP_ADDRESSV ,
7265 WINED3DSAMP_ADDRESSW ,
7266 WINED3DSAMP_BORDERCOLOR ,
7267 WINED3DSAMP_MAGFILTER ,
7268 WINED3DSAMP_MINFILTER ,
7269 WINED3DSAMP_MIPFILTER ,
7270 WINED3DSAMP_MIPMAPLODBIAS ,
7271 WINED3DSAMP_MAXMIPLEVEL ,
7272 WINED3DSAMP_MAXANISOTROPY ,
7273 WINED3DSAMP_SRGBTEXTURE ,
7274 WINED3DSAMP_ELEMENTINDEX
7277 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
7279 WINED3DRS_AMBIENTMATERIALSOURCE ,
7280 WINED3DRS_CLIPPING ,
7281 WINED3DRS_CLIPPLANEENABLE ,
7282 WINED3DRS_COLORVERTEX ,
7283 WINED3DRS_DIFFUSEMATERIALSOURCE ,
7284 WINED3DRS_EMISSIVEMATERIALSOURCE ,
7285 WINED3DRS_FOGDENSITY ,
7287 WINED3DRS_FOGSTART ,
7288 WINED3DRS_FOGTABLEMODE ,
7289 WINED3DRS_FOGVERTEXMODE ,
7290 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
7291 WINED3DRS_LIGHTING ,
7292 WINED3DRS_LOCALVIEWER ,
7293 WINED3DRS_MULTISAMPLEANTIALIAS ,
7294 WINED3DRS_MULTISAMPLEMASK ,
7295 WINED3DRS_NORMALIZENORMALS ,
7296 WINED3DRS_PATCHEDGESTYLE ,
7297 WINED3DRS_POINTSCALE_A ,
7298 WINED3DRS_POINTSCALE_B ,
7299 WINED3DRS_POINTSCALE_C ,
7300 WINED3DRS_POINTSCALEENABLE ,
7301 WINED3DRS_POINTSIZE ,
7302 WINED3DRS_POINTSIZE_MAX ,
7303 WINED3DRS_POINTSIZE_MIN ,
7304 WINED3DRS_POINTSPRITEENABLE ,
7305 WINED3DRS_RANGEFOGENABLE ,
7306 WINED3DRS_SPECULARMATERIALSOURCE ,
7307 WINED3DRS_TWEENFACTOR ,
7308 WINED3DRS_VERTEXBLEND
7311 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
7312 WINED3DTSS_TEXCOORDINDEX ,
7313 WINED3DTSS_TEXTURETRANSFORMFLAGS
7316 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
7317 WINED3DSAMP_DMAPOFFSET