2 * IWineD3DDevice implementation
4 * Copyright 2002-2005 Jason Edmeades
5 * Copyright 2003-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include "wined3d_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
31 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
33 /* x11drv GDI escapes */
34 #define X11DRV_ESCAPE 6789
35 enum x11drv_escape_codes
37 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
38 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
39 X11DRV_GET_FONT, /* get current X font for a DC */
42 /* retrieve the X display to use on a given DC */
43 inline static Display *get_display( HDC hdc )
46 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
48 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
49 sizeof(display), (LPSTR)&display )) display = NULL;
53 /* Memory tracking and object counting */
54 static unsigned int emulated_textureram = 64*1024*1024;
56 /* TODO: setup some flags in the regestry to enable, disable pbuffer support */
57 /* enable pbuffer support for offscreen textures */
58 BOOL pbuffer_support = FALSE;
59 /* allocate one pbuffer per surface */
60 BOOL pbuffer_per_surface = FALSE;
62 /* static function declarations */
63 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
65 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type);
68 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return WINED3DERR_OUTOFVIDEOMEMORY;}
70 #define D3DCREATEOBJECTINSTANCE(object, type) { \
71 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
72 D3DMEMCHECK(object, pp##type); \
73 object->lpVtbl = &IWineD3D##type##_Vtbl; \
74 object->wineD3DDevice = This; \
75 object->parent = parent; \
77 *pp##type = (IWineD3D##type *) object; \
80 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
81 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
82 D3DMEMCHECK(object, pp##type); \
83 object->lpVtbl = &IWineD3D##type##_Vtbl; \
84 object->resource.wineD3DDevice = This; \
85 object->resource.parent = parent; \
86 object->resource.resourceType = d3dtype; \
87 object->resource.ref = 1; \
88 object->resource.pool = Pool; \
89 object->resource.format = Format; \
90 object->resource.usage = Usage; \
91 object->resource.size = _size; \
92 /* Check that we have enough video ram left */ \
93 if (Pool == WINED3DPOOL_DEFAULT) { \
94 if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
95 WARN("Out of 'bogus' video memory\n"); \
96 HeapFree(GetProcessHeap(), 0, object); \
98 return WINED3DERR_OUTOFVIDEOMEMORY; \
100 globalChangeGlRam(_size); \
102 object->resource.allocatedMemory = (0 == _size ? NULL : Pool == WINED3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
103 if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != WINED3DPOOL_DEFAULT) { \
104 FIXME("Out of memory!\n"); \
105 HeapFree(GetProcessHeap(), 0, object); \
107 return WINED3DERR_OUTOFVIDEOMEMORY; \
109 *pp##type = (IWineD3D##type *) object; \
110 IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
111 TRACE("(%p) : Created resource %p\n", This, object); \
114 #define D3DINITIALIZEBASETEXTURE(_basetexture) { \
115 _basetexture.levels = Levels; \
116 _basetexture.filterType = (Usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE; \
117 _basetexture.LOD = 0; \
118 _basetexture.dirty = TRUE; \
121 /**********************************************************
122 * Global variable / Constants follow
123 **********************************************************/
124 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
126 /**********************************************************
127 * Utility functions follow
128 **********************************************************/
129 /* Convert the D3DLIGHT properties into equivalent gl lights */
130 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
133 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
134 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
136 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
137 glMatrixMode(GL_MODELVIEW);
139 glLoadMatrixf((float *)&This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
142 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
143 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
144 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
145 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
146 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
147 checkGLcall("glLightfv");
150 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
151 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
152 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
153 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
154 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
155 checkGLcall("glLightfv");
158 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
159 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
160 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
161 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
162 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
163 checkGLcall("glLightfv");
165 /* Attenuation - Are these right? guessing... */
166 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
167 checkGLcall("glLightf");
168 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
169 checkGLcall("glLightf");
171 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
172 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
174 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
177 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
178 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
179 checkGLcall("glLightf");
181 switch (lightInfo->OriginalParms.Type) {
184 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
185 checkGLcall("glLightfv");
186 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
187 checkGLcall("glLightf");
193 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
194 checkGLcall("glLightfv");
196 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
197 checkGLcall("glLightfv");
198 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
199 checkGLcall("glLightf");
200 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
201 checkGLcall("glLightf");
205 case D3DLIGHT_DIRECTIONAL:
207 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
208 checkGLcall("glLightfv");
209 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
210 checkGLcall("glLightf");
211 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
212 checkGLcall("glLightf");
216 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
219 /* Restore the modelview matrix */
223 /* Apply the current values to the specified texture stage */
224 void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Sampler, DWORD Flags) {
225 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
233 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
234 clamping, MIPLOD, etc. This will work for up to 16 samplers.
237 if (Sampler >= GL_LIMITS(samplers)) {
238 FIXME("Trying to set the state of more samplers %ld than are supported %d by this openGL implementation\n", Sampler, GL_LIMITS(samplers));
241 VTRACE(("Activating appropriate texture state %ld\n", Sampler));
242 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
244 GLACTIVETEXTURE(Sampler);
246 /* Could we use bindTexture and then apply the states instead of GLACTIVETEXTURE */
247 } else if (Sampler > 0) {
248 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
252 /* TODO: change this to a lookup table
253 LOOKUP_TEXTURE_STATES lists all texture states that should be applied.
254 LOOKUP_CONTEXT_SATES list all context applicable states that can be applied
255 etc.... it's a lot cleaner, quicker and possibly easier to maintain than running a switch and setting a skip flag...
256 especially when there are a number of groups of states. */
258 TRACE("-----------------------> Updating the texture at Sampler %ld to have new texture state information\n", Sampler);
260 /* The list of states not to apply is a big as the list of states to apply, so it makes sense to produce an inclusive list */
261 #define APPLY_STATE(_state) IWineD3DDeviceImpl_ApplyTextureUnitState(iface, Sampler, _state)
262 /* these are the only two supported states that need to be applied */
263 APPLY_STATE(WINED3DTSS_TEXCOORDINDEX);
264 APPLY_STATE(WINED3DTSS_TEXTURETRANSFORMFLAGS);
265 #if 0 /* not supported at the moment */
266 APPLY_STATE(WINED3DTSS_BUMPENVMAT00);
267 APPLY_STATE(WINED3DTSS_BUMPENVMAT01);
268 APPLY_STATE(WINED3DTSS_BUMPENVMAT10);
269 APPLY_STATE(WINED3DTSS_BUMPENVMAT11);
270 APPLY_STATE(WINED3DTSS_BUMPENVLSCALE);
271 APPLY_STATE(WINED3DTSS_BUMPENVLOFFSET);
272 APPLY_STATE(WINED3DTSS_RESULTARG);
273 APPLY_STATE(WINED3DTSS_CONSTANT);
275 /* a quick sanity check in case someone forgot to update this function */
276 if (WINED3D_HIGHEST_TEXTURE_STATE > WINED3DTSS_CONSTANT) {
277 FIXME("(%p) : There are more texture states than expected, update device.c to match\n", This);
281 /* apply any sampler states that always need applying */
282 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
283 tmpvalue.d = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPMAPLODBIAS];
284 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
285 GL_TEXTURE_LOD_BIAS_EXT,
287 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
290 /* Note the D3DRS value applies to all textures, but GL has one
291 * per texture, so apply it now ready to be used!
293 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
294 /* Set the default alpha blend color */
295 glBlendColor(col[0], col[1], col[2], col[3]);
296 checkGLcall("glBlendColor");
298 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
299 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
300 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
302 /* TODO: NV_POINT_SPRITE */
303 if (GL_SUPPORT(ARB_POINT_SPRITE)) {
304 if (This->stateBlock->renderState[WINED3DRS_POINTSPRITEENABLE] != FALSE) {
305 /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
306 glDisable(GL_POINT_SMOOTH);
308 /* Centre the texture on the vertex */
309 VTRACE("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
310 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
312 VTRACE("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
313 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
314 checkGLcall("glTexEnvf(...)");
315 VTRACE("glEnable( GL_POINT_SPRITE_ARB )\n");
316 glEnable( GL_POINT_SPRITE_ARB );
317 checkGLcall("glEnable(...)");
319 VTRACE("glDisable( GL_POINT_SPRITE_ARB )\n");
320 glDisable( GL_POINT_SPRITE_ARB );
321 checkGLcall("glEnable(...)");
325 TRACE("-----------------------> Updated the texture at Sampler %ld to have new texture state information\n", Sampler);
328 /**********************************************************
329 * IUnknown parts follows
330 **********************************************************/
332 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
334 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
336 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
337 if (IsEqualGUID(riid, &IID_IUnknown)
338 || IsEqualGUID(riid, &IID_IWineD3DBase)
339 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
340 IUnknown_AddRef(iface);
345 return E_NOINTERFACE;
348 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
349 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
350 ULONG refCount = InterlockedIncrement(&This->ref);
352 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
356 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
357 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
358 ULONG refCount = InterlockedDecrement(&This->ref);
360 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
363 /* TODO: Clean up all the surfaces and textures! */
364 /* FIXME: Create targets and state blocks in d3d8 */
365 if (((IWineD3DImpl *)This->wineD3D)->dxVersion >= 8) { /*We don't create state blocks for d3d7 yet*/
366 /* NOTE: You must release the parent if the object was created via a callback
367 ** ***************************/
368 /* TODO: this is exactly the same as required by _Reset.., so at some point we need to move the code so that is can be called by reset add release... */
369 /* Release all of the swapchains, except the implicit swapchain */
370 IUnknown* stencilBufferParent;
371 IUnknown* swapChainParent;
373 /* NOTE: Don't release swapchain 0 here, it's 'special' */
374 SwapChainList *nextSwapchain = This->swapchains;
375 if (nextSwapchain != NULL) {
376 nextSwapchain = nextSwapchain->next;
378 WARN("Expected to find the implicit swapchain\n");
381 /* release all the other swapchains */
382 while (nextSwapchain != NULL) {
383 SwapChainList *prevSwapchain = nextSwapchain;
384 nextSwapchain = nextSwapchain->next;
385 IWineD3DSwapChain_Release(prevSwapchain->swapchain);
386 /* NOTE: no need to free the list element, it will be done by the release callback
387 HeapFree(GetProcessHeap(), 0, prevSwapchain); */
389 /* Release the buffers (with sanity checks)*/
390 if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
391 if(This->depthStencilBuffer != This->stencilBufferTarget)
392 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
394 This->stencilBufferTarget = NULL;
396 if(IWineD3DSurface_Release(This->renderTarget) >0){
397 /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
399 This->renderTarget = NULL;
401 IWineD3DSurface_GetParent(This->depthStencilBuffer, &stencilBufferParent);
402 IUnknown_Release(stencilBufferParent); /* once for the get parent */
403 if(IUnknown_Release(stencilBufferParent) >0){ /* the second time for when it was created */
404 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
406 This->depthStencilBuffer = NULL;
408 /* Release the update stateblock */
409 if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){
410 if(This->updateStateBlock != This->stateBlock)
411 FIXME("(%p) Something's still holding the Update stateblock\n",This);
413 This->updateStateBlock = NULL;
414 { /* because were not doing proper internal refcounts releasing the primary state block
415 causes recursion with the extra checks in ResourceReleased, to avoid this we have
416 to set this->stateBlock = NULL; first */
417 IWineD3DStateBlock *stateBlock = (IWineD3DStateBlock *)This->stateBlock;
418 This->stateBlock = NULL;
420 /* Release the stateblock */
421 if(IWineD3DStateBlock_Release(stateBlock) > 0){
422 FIXME("(%p) Something's still holding the Update stateblock\n",This);
426 if (This->swapchains != NULL) {
427 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
428 IWineD3DSwapChain_GetParent(This->swapchains->swapchain, &swapChainParent);
429 IUnknown_Release(swapChainParent); /* once for the get parent */
430 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
431 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
435 if (This->resources != NULL ) {
436 FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This);
438 #if 0 /* TODO: Dump a list of all the resources still bound */
439 dumpResources(This->resources);
441 /* TODO: set the resources to a lost state */
445 IWineD3D_Release(This->wineD3D);
446 This->wineD3D = NULL;
447 HeapFree(GetProcessHeap(), 0, This);
448 TRACE("Freed device %p\n", This);
454 /**********************************************************
455 * IWineD3DDevice implementation follows
456 **********************************************************/
457 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
458 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
459 *pParent = This->parent;
460 IUnknown_AddRef(This->parent);
464 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
465 DWORD FVF, WINED3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
467 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
468 IWineD3DVertexBufferImpl *object;
469 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
470 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, WINED3DRTYPE_VERTEXBUFFER, Size)
473 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
474 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
478 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
479 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
484 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
485 WINED3DFORMAT Format, WINED3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
486 HANDLE *sharedHandle, IUnknown *parent) {
487 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
488 IWineD3DIndexBufferImpl *object;
489 TRACE("(%p) Creating index buffer\n", This);
491 /* Allocate the storage for the device */
492 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,WINED3DRTYPE_INDEXBUFFER, Length)
495 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
496 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
499 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
500 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
501 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
506 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
508 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
509 IWineD3DStateBlockImpl *object;
512 D3DCREATEOBJECTINSTANCE(object, StateBlock)
513 object->blockType = Type;
515 /* Special case - Used during initialization to produce a placeholder stateblock
516 so other functions called can update a state block */
517 if (Type == WINED3DSBT_INIT) {
518 /* Don't bother increasing the reference count otherwise a device will never
519 be freed due to circular dependencies */
523 /* Otherwise, might as well set the whole state block to the appropriate values */
524 if ( This->stateBlock != NULL) {
525 memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
527 memset(object->streamFreq, 1, sizeof(object->streamFreq));
530 /* Reset the ref and type after kludging it */
531 object->wineD3DDevice = This;
533 object->blockType = Type;
535 TRACE("Updating changed flags appropriate for type %d\n", Type);
537 if (Type == WINED3DSBT_ALL) {
539 TRACE("ALL => Pretend everything has changed\n");
540 memset(&object->changed, TRUE, sizeof(This->stateBlock->changed));
541 } else if (Type == WINED3DSBT_PIXELSTATE) {
543 TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
544 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
546 object->changed.pixelShader = TRUE;
548 /* Pixel Shader Constants */
549 for (i = 0; i < MAX_PSHADER_CONSTANTS; ++i) {
550 object->changed.pixelShaderConstants[i] = TRUE;
552 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
553 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
555 for (j = 0; j < GL_LIMITS(textures); j++) {
556 for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
557 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
560 for (j = 0 ; j < 16; j++) {
561 for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
563 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
567 } else if (Type == WINED3DSBT_VERTEXSTATE) {
569 TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
570 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
572 object->changed.vertexShader = TRUE;
574 /* Vertex Shader Constants */
575 for (i = 0; i < MAX_VSHADER_CONSTANTS; ++i) {
576 object->changed.vertexShaderConstants[i] = TRUE;
578 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
579 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
581 for (j = 0; j < GL_LIMITS(textures); j++) {
582 for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
583 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
586 for (j = 0 ; j < 16; j++){
587 for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
588 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
592 /* Duplicate light chain */
594 PLIGHTINFOEL *src = NULL;
595 PLIGHTINFOEL *dst = NULL;
596 PLIGHTINFOEL *newEl = NULL;
597 src = This->stateBlock->lights;
598 object->lights = NULL;
602 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
603 if (newEl == NULL) return WINED3DERR_OUTOFVIDEOMEMORY;
604 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
606 newEl->changed = TRUE;
607 newEl->enabledChanged = TRUE;
609 object->lights = newEl;
620 FIXME("Unrecognized state block type %d\n", Type);
623 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
628 /* ************************************
630 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
633 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
635 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.
637 ******************************** */
639 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, IUnknown *parent) {
640 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
641 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
642 unsigned int pow2Width, pow2Height;
643 unsigned int Size = 1;
644 TRACE("(%p) Create surface\n",This);
646 /** FIXME: Check ranges on the inputs are valid
649 * [in] Quality level. The valid range is between zero and one less than the level
650 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
651 * Passing a larger value returns the error WINED3DERR_INVALIDCALL. The MultisampleQuality
652 * values of paired render targets, depth stencil surfaces, and the MultiSample type
654 *******************************/
659 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
661 * If this flag is set, the contents of the depth stencil buffer will be
662 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
663 * with a different depth surface.
665 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
666 ***************************/
668 if(MultisampleQuality < 0) {
669 FIXME("Invalid multisample level %ld\n", MultisampleQuality);
670 return WINED3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
673 if(MultisampleQuality > 0) {
674 FIXME("MultisampleQuality set to %ld, substituting 0\n", MultisampleQuality);
675 MultisampleQuality=0;
678 /** FIXME: Check that the format is supported
680 *******************************/
682 /* Non-power2 support */
684 /* Find the nearest pow2 match */
685 pow2Width = pow2Height = 1;
686 while (pow2Width < Width) pow2Width <<= 1;
687 while (pow2Height < Height) pow2Height <<= 1;
689 if (pow2Width > Width || pow2Height > Height) {
690 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
691 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
692 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
693 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
694 This, Width, Height);
695 return WINED3DERR_NOTAVAILABLE;
699 /** Check against the maximum texture sizes supported by the video card **/
700 if (pow2Width > GL_LIMITS(texture_size) || pow2Height > GL_LIMITS(texture_size)) {
701 /* one of three options
702 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)
703 2: Set the texture to the maxium size (bad idea)
704 3: WARN and return WINED3DERR_NOTAVAILABLE;
706 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));
707 return WINED3DERR_NOTAVAILABLE;
712 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
713 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
715 *********************************/
716 if (WINED3DFMT_UNKNOWN == Format) {
718 } else if (Format == WINED3DFMT_DXT1) {
719 /* DXT1 is half byte per pixel */
720 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4)) >> 1;
722 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
723 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
724 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4));
726 Size = (pow2Width * D3DFmtGetBpp(This, Format)) * pow2Height;
729 /** Create and initialise the surface resource **/
730 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,WINED3DRTYPE_SURFACE, Size)
731 /* "Standalone" surface */
732 IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL);
734 object->currentDesc.Width = Width;
735 object->currentDesc.Height = Height;
736 object->currentDesc.MultiSampleType = MultiSample;
737 object->currentDesc.MultiSampleQuality = MultisampleQuality;
739 /* Setup some glformat defaults */
740 if (WINED3DFMT_UNKNOWN != Format) {
741 object->glDescription.glFormat = D3DFmt2GLFmt(This, object->resource.format);
742 object->glDescription.glFormatInternal = D3DFmt2GLIntFmt(This, object->resource.format);
743 object->glDescription.glType = D3DFmt2GLType(This, object->resource.format);
745 object->glDescription.glFormat = 0;
746 object->glDescription.glFormatInternal = 0;
747 object->glDescription.glType = 0;
750 object->glDescription.textureName = 0;
751 object->glDescription.level = Level;
752 object->glDescription.target = GL_TEXTURE_2D;
755 object->pow2Width = pow2Width;
756 object->pow2Height = pow2Height;
757 object->nonpow2 = (pow2Width != Width || pow2Height != Height) ? TRUE : FALSE;
758 object->discard = Discard;
759 object->activeLock = FALSE;
761 if (WINED3DFMT_UNKNOWN != Format) {
762 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
763 object->pow2Size = (pow2Width * object->bytesPerPixel) * pow2Height;
765 object->bytesPerPixel = 0;
766 object->pow2Size = 0;
769 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
771 TRACE("Pool %d %d %d %d",Pool, WINED3DPOOL_DEFAULT, WINED3DPOOL_MANAGED, WINED3DPOOL_SYSTEMMEM);
773 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
774 * this function is too deap to need to care about things like this.
775 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
776 * ****************************************/
778 case WINED3DPOOL_SCRATCH:
779 if(Lockable == FALSE)
780 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
781 which are mutually exclusive, setting lockable to true\n");
784 case WINED3DPOOL_SYSTEMMEM:
785 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
786 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
787 case WINED3DPOOL_MANAGED:
788 if(Usage == WINED3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
789 Usage of DYNAMIC which are mutually exclusive, not doing \
790 anything just telling you.\n");
792 case WINED3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
793 if(!(Usage & WINED3DUSAGE_DYNAMIC) && !(Usage & WINED3DUSAGE_RENDERTARGET)
794 && !(Usage && WINED3DUSAGE_DEPTHSTENCIL ) && Lockable == TRUE)
795 FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
798 FIXME("(%p) Unknown pool %d\n", This, Pool);
802 if (Usage & WINED3DUSAGE_RENDERTARGET && Pool != WINED3DPOOL_DEFAULT) {
803 FIXME("Trying to create a render target that isn't in the default pool\n");
807 object->locked = FALSE;
808 object->lockable = (WINED3DFMT_D16_LOCKABLE == Format) ? TRUE : Lockable;
810 /* mark the texture as dirty so that it get's loaded first time around*/
811 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
812 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
813 This, Width, Height, Format, debug_d3dformat(Format),
814 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
819 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
820 DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
821 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
822 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
824 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
825 IWineD3DTextureImpl *object;
830 unsigned int pow2Width = Width;
831 unsigned int pow2Height = Height;
834 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) ....\n", This, Width, Height, Levels, Usage);
836 /* TODO: It should only be possible to create textures for formats
837 that are reported as supported */
838 if (WINED3DFMT_UNKNOWN >= Format) {
839 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
840 return WINED3DERR_INVALIDCALL;
843 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, WINED3DRTYPE_TEXTURE, 0);
844 D3DINITIALIZEBASETEXTURE(object->baseTexture);
845 object->width = Width;
846 object->height = Height;
848 /** Non-power2 support **/
849 /* Find the nearest pow2 match */
850 pow2Width = pow2Height = 1;
851 while (pow2Width < Width) pow2Width <<= 1;
852 while (pow2Height < Height) pow2Height <<= 1;
854 /** FIXME: add support for real non-power-two if it's provided by the video card **/
855 /* Precalculated scaling for 'faked' non power of two texture coords */
856 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
857 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
858 TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
860 /* Calculate levels for mip mapping */
862 TRACE("calculating levels %d\n", object->baseTexture.levels);
863 object->baseTexture.levels++;
866 while (tmpW > 1 && tmpH > 1) {
867 tmpW = max(1, tmpW >> 1);
868 tmpH = max(1, tmpH >> 1);
869 object->baseTexture.levels++;
871 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
874 /* Generate all the surfaces */
877 for (i = 0; i < object->baseTexture.levels; i++)
879 /* use the callback to create the texture surface */
880 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
881 if (hr!= WINED3D_OK) {
883 FIXME("Failed to create surface %p\n", object);
885 for (j = 0 ; j < i ; j++) {
886 IWineD3DSurface_Release(object->surfaces[j]);
888 /* heap free object */
889 HeapFree(GetProcessHeap(), 0, object);
895 IWineD3DSurface_SetContainer(object->surfaces[i], (IWineD3DBase *)object);
896 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
897 /* calculate the next mipmap level */
898 tmpW = max(1, tmpW >> 1);
899 tmpH = max(1, tmpH >> 1);
902 TRACE("(%p) : Created texture %p\n", This, object);
906 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
907 UINT Width, UINT Height, UINT Depth,
908 UINT Levels, DWORD Usage,
909 WINED3DFORMAT Format, WINED3DPOOL Pool,
910 IWineD3DVolumeTexture **ppVolumeTexture,
911 HANDLE *pSharedHandle, IUnknown *parent,
912 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
914 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
915 IWineD3DVolumeTextureImpl *object;
921 /* TODO: It should only be possible to create textures for formats
922 that are reported as supported */
923 if (WINED3DFMT_UNKNOWN >= Format) {
924 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
925 return WINED3DERR_INVALIDCALL;
928 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, WINED3DRTYPE_VOLUMETEXTURE, 0);
929 D3DINITIALIZEBASETEXTURE(object->baseTexture);
931 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
932 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
934 object->width = Width;
935 object->height = Height;
936 object->depth = Depth;
938 /* Calculate levels for mip mapping */
940 object->baseTexture.levels++;
944 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
945 tmpW = max(1, tmpW >> 1);
946 tmpH = max(1, tmpH >> 1);
947 tmpD = max(1, tmpD >> 1);
948 object->baseTexture.levels++;
950 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
953 /* Generate all the surfaces */
958 for (i = 0; i < object->baseTexture.levels; i++)
960 /* Create the volume */
961 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
962 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
964 /* Set it's container to this object */
965 IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)object);
967 /* calcualte the next mipmap level */
968 tmpW = max(1, tmpW >> 1);
969 tmpH = max(1, tmpH >> 1);
970 tmpD = max(1, tmpD >> 1);
973 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
974 TRACE("(%p) : Created volume texture %p\n", This, object);
978 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
979 UINT Width, UINT Height, UINT Depth,
981 WINED3DFORMAT Format, WINED3DPOOL Pool,
982 IWineD3DVolume** ppVolume,
983 HANDLE* pSharedHandle, IUnknown *parent) {
985 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
986 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
988 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, WINED3DRTYPE_VOLUME, ((Width * D3DFmtGetBpp(This, Format)) * Height * Depth))
990 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
991 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
993 object->currentDesc.Width = Width;
994 object->currentDesc.Height = Height;
995 object->currentDesc.Depth = Depth;
996 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
998 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
999 object->lockable = TRUE;
1000 object->locked = FALSE;
1001 memset(&object->lockedBox, 0, sizeof(WINED3DBOX));
1002 object->dirty = TRUE;
1004 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
1007 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
1008 UINT Levels, DWORD Usage,
1009 WINED3DFORMAT Format, WINED3DPOOL Pool,
1010 IWineD3DCubeTexture **ppCubeTexture,
1011 HANDLE *pSharedHandle, IUnknown *parent,
1012 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1014 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1015 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1019 unsigned int pow2EdgeLength = EdgeLength;
1021 /* TODO: It should only be possible to create textures for formats
1022 that are reported as supported */
1023 if (WINED3DFMT_UNKNOWN >= Format) {
1024 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
1025 return WINED3DERR_INVALIDCALL;
1028 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, WINED3DRTYPE_CUBETEXTURE, 0);
1029 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1031 TRACE("(%p) Create Cube Texture\n", This);
1033 /** Non-power2 support **/
1035 /* Find the nearest pow2 match */
1037 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
1039 object->edgeLength = EdgeLength;
1040 /* TODO: support for native non-power 2 */
1041 /* Precalculated scaling for 'faked' non power of two texture coords */
1042 object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
1044 /* Calculate levels for mip mapping */
1046 object->baseTexture.levels++;
1049 tmpW = max(1, tmpW >> 1);
1050 object->baseTexture.levels++;
1052 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1055 /* Generate all the surfaces */
1057 for (i = 0; i < object->baseTexture.levels; i++) {
1059 /* Create the 6 faces */
1060 for (j = 0; j < 6; j++) {
1062 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
1063 i /* Level */, &object->surfaces[j][i],pSharedHandle);
1065 if(hr!= WINED3D_OK) {
1069 for (l = 0; l < j; l++) {
1070 IWineD3DSurface_Release(object->surfaces[j][i]);
1072 for (k = 0; k < i; k++) {
1073 for (l = 0; l < 6; l++) {
1074 IWineD3DSurface_Release(object->surfaces[l][j]);
1078 FIXME("(%p) Failed to create surface\n",object);
1079 HeapFree(GetProcessHeap(),0,object);
1080 *ppCubeTexture = NULL;
1083 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IWineD3DBase *)object);
1084 TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1086 tmpW = max(1, tmpW >> 1);
1089 TRACE("(%p) : Created Cube Texture %p\n", This, object);
1090 *ppCubeTexture = (IWineD3DCubeTexture *) object;
1094 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1095 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1096 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1098 if (NULL == ppQuery) {
1099 /* Just a check to see if we support this type of query */
1100 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1102 case WINED3DQUERYTYPE_OCCLUSION:
1103 TRACE("(%p) occlusion query\n", This);
1104 if (GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY))
1107 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1109 case WINED3DQUERYTYPE_VCACHE:
1110 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1111 case WINED3DQUERYTYPE_VERTEXSTATS:
1112 case WINED3DQUERYTYPE_EVENT:
1113 case WINED3DQUERYTYPE_TIMESTAMP:
1114 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1115 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1116 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1117 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1118 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1119 case WINED3DQUERYTYPE_PIXELTIMINGS:
1120 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1121 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1123 FIXME("(%p) Unhandled query type %d\n", This, Type);
1128 D3DCREATEOBJECTINSTANCE(object, Query)
1129 object->type = Type;
1130 /* allocated the 'extended' data based on the type of query requested */
1132 case D3DQUERYTYPE_OCCLUSION:
1133 if(GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY)) {
1134 TRACE("(%p) Allocating data for an occlusion query\n", This);
1135 object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1138 case D3DQUERYTYPE_VCACHE:
1139 case D3DQUERYTYPE_RESOURCEMANAGER:
1140 case D3DQUERYTYPE_VERTEXSTATS:
1141 case D3DQUERYTYPE_EVENT:
1142 case D3DQUERYTYPE_TIMESTAMP:
1143 case D3DQUERYTYPE_TIMESTAMPDISJOINT:
1144 case D3DQUERYTYPE_TIMESTAMPFREQ:
1145 case D3DQUERYTYPE_PIPELINETIMINGS:
1146 case D3DQUERYTYPE_INTERFACETIMINGS:
1147 case D3DQUERYTYPE_VERTEXTIMINGS:
1148 case D3DQUERYTYPE_PIXELTIMINGS:
1149 case D3DQUERYTYPE_BANDWIDTHTIMINGS:
1150 case D3DQUERYTYPE_CACHEUTILIZATION:
1152 object->extendedData = 0;
1153 FIXME("(%p) Unhandled query type %d\n",This , Type);
1155 TRACE("(%p) : Created Query %p\n", This, object);
1159 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1160 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1162 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1163 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1164 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1167 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1169 XVisualInfo template;
1170 GLXContext oldContext;
1171 Drawable oldDrawable;
1172 HRESULT hr = WINED3D_OK;
1174 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1176 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1177 * does a device hold a reference to a swap chain giving them a lifetime of the device
1178 * or does the swap chain notify the device of its destruction.
1179 *******************************/
1181 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1183 /* Initialize other useful values */
1184 object->presentParms.BackBufferCount = 1; /* TODO:? support for gl_aux buffers */
1186 /*********************
1187 * Lookup the window Handle and the relating X window handle
1188 ********************/
1190 /* Setup hwnd we are using, plus which display this equates to */
1191 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1192 if (!object->win_handle) {
1193 object->win_handle = This->createParms.hFocusWindow;
1196 object->win_handle = GetAncestor(object->win_handle, GA_ROOT);
1197 if ( !( object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window") ) ) {
1198 ERR("Can't get drawable (window), HWND:%p doesn't have the property __wine_x11_whole_window\n", object->win_handle);
1199 return WINED3DERR_NOTAVAILABLE;
1201 hDc = GetDC(object->win_handle);
1202 object->display = get_display(hDc);
1203 ReleaseDC(object->win_handle, hDc);
1204 TRACE("Using a display of %p %p\n", object->display, hDc);
1206 if (NULL == object->display || NULL == hDc) {
1207 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1208 return WINED3DERR_NOTAVAILABLE;
1211 if (object->win == 0) {
1212 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1213 return WINED3DERR_NOTAVAILABLE;
1216 * Create an opengl context for the display visual
1217 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1218 * use different properties after that point in time. FIXME: How to handle when requested format
1219 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1220 * it chooses is identical to the one already being used!
1221 **********************************/
1223 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1226 /* Create a new context for this swapchain */
1227 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1228 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1229 (or the best possible if none is requested) */
1230 TRACE("Found x visual ID : %ld\n", template.visualid);
1232 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1233 if (NULL == object->visInfo) {
1234 ERR("cannot really get XVisual\n");
1236 return WINED3DERR_NOTAVAILABLE;
1239 /* Write out some debug info about the visual/s */
1240 TRACE("Using x visual ID : %ld\n", template.visualid);
1241 TRACE(" visual info: %p\n", object->visInfo);
1242 TRACE(" num items : %d\n", num);
1243 for (n = 0;n < num; n++) {
1244 TRACE("=====item=====: %d\n", n + 1);
1245 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1246 TRACE(" screen : %d\n", object->visInfo[n].screen);
1247 TRACE(" depth : %u\n", object->visInfo[n].depth);
1248 TRACE(" class : %d\n", object->visInfo[n].class);
1249 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1250 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1251 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1252 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1253 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1254 /* log some extra glx info */
1255 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1256 TRACE(" gl_aux_buffers : %d\n", value);
1257 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1258 TRACE(" gl_buffer_size : %d\n", value);
1259 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1260 TRACE(" gl_red_size : %d\n", value);
1261 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1262 TRACE(" gl_green_size : %d\n", value);
1263 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1264 TRACE(" gl_blue_size : %d\n", value);
1265 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1266 TRACE(" gl_alpha_size : %d\n", value);
1267 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1268 TRACE(" gl_depth_size : %d\n", value);
1269 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1270 TRACE(" gl_stencil_size : %d\n", value);
1272 /* Now choose a simila visual ID*/
1274 #ifdef USE_CONTEXT_MANAGER
1276 /** TODO: use a context mamager **/
1280 IWineD3DSwapChain *implSwapChain;
1281 if (WINED3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1282 /* The first time around we create the context that is shared with all other swapchains and render targets */
1283 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1284 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1287 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1288 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1289 /* and create a new context with the implicit swapchains context as the shared context */
1290 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1291 IWineD3DSwapChain_Release(implSwapChain);
1296 XFree(object->visInfo);
1297 object->visInfo = NULL;
1299 if (NULL == object->glCtx) {
1300 ERR("cannot create glxContext\n");
1302 return WINED3DERR_NOTAVAILABLE;
1306 if (object->glCtx == NULL) {
1307 ERR("Error in context creation !\n");
1308 return WINED3DERR_INVALIDCALL;
1310 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1311 object->win_handle, object->glCtx, object->win, object->visInfo);
1314 /*********************
1315 * Windowed / Fullscreen
1316 *******************/
1319 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1320 * so we should really check to see if there is a fullscreen swapchain already
1321 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1322 **************************************/
1324 if (!*(pPresentationParameters->Windowed)) {
1330 /* Get info on the current display setup */
1331 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1332 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1335 /* Change the display settings */
1336 memset(&devmode, 0, sizeof(DEVMODEW));
1337 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1338 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1339 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1340 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1341 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1342 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1344 /* Make popup window */
1345 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1346 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1347 *(pPresentationParameters->BackBufferWidth),
1348 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1354 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1355 * then the corresponding dimension of the client area of the hDeviceWindow
1356 * (or the focus window, if hDeviceWindow is NULL) is taken.
1357 **********************/
1359 if (*(pPresentationParameters->Windowed) &&
1360 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1361 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1364 GetClientRect(object->win_handle, &Rect);
1366 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1367 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1368 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1370 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1371 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1372 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1376 /*********************
1377 * finish off parameter initialization
1378 *******************/
1380 /* Put the correct figures in the presentation parameters */
1381 TRACE("Coppying accross presentaion paraneters\n");
1382 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1383 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1384 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1385 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1386 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1387 object->presentParms.MultiSampleQuality = NULL == pPresentationParameters->MultiSampleQuality ? 0 : *(pPresentationParameters->MultiSampleQuality);
1388 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1389 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1390 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1391 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1392 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1393 object->presentParms.Flags = *(pPresentationParameters->Flags);
1394 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1395 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1398 /*********************
1399 * Create the back, front and stencil buffers
1400 *******************/
1401 TRACE("calling rendertarget CB\n");
1402 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1403 object->presentParms.BackBufferWidth,
1404 object->presentParms.BackBufferHeight,
1405 object->presentParms.BackBufferFormat,
1406 object->presentParms.MultiSampleType,
1407 object->presentParms.MultiSampleQuality,
1408 TRUE /* Lockable */,
1409 &object->frontBuffer,
1410 NULL /* pShared (always null)*/);
1411 if (object->frontBuffer != NULL)
1412 IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
1413 TRACE("calling rendertarget CB\n");
1414 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1415 object->presentParms.BackBufferWidth,
1416 object->presentParms.BackBufferHeight,
1417 object->presentParms.BackBufferFormat,
1418 object->presentParms.MultiSampleType,
1419 object->presentParms.MultiSampleQuality,
1420 TRUE /* Lockable */,
1421 &object->backBuffer,
1422 NULL /* pShared (always null)*/);
1423 if (object->backBuffer != NULL)
1424 IWineD3DSurface_SetContainer(object->backBuffer, (IWineD3DBase *)object);
1426 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1427 if (pPresentationParameters->EnableAutoDepthStencil) {
1428 TRACE("Creating depth stencil buffer\n");
1429 if (This->depthStencilBuffer == NULL ) {
1430 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1431 object->presentParms.BackBufferWidth,
1432 object->presentParms.BackBufferHeight,
1433 object->presentParms.AutoDepthStencilFormat,
1434 object->presentParms.MultiSampleType,
1435 object->presentParms.MultiSampleQuality,
1436 FALSE /* FIXME: Discard */,
1437 &This->depthStencilBuffer,
1438 NULL /* pShared (always null)*/ );
1439 if (This->depthStencilBuffer != NULL)
1440 IWineD3DSurface_SetContainer(This->depthStencilBuffer, 0);
1443 /** TODO: A check on width, height and multisample types
1444 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1445 ****************************/
1446 object->wantsDepthStencilBuffer = TRUE;
1448 object->wantsDepthStencilBuffer = FALSE;
1451 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1454 /*********************
1455 * init the default renderTarget management
1456 *******************/
1457 object->drawable = object->win;
1458 object->render_ctx = object->glCtx;
1460 if (hr == WINED3D_OK) {
1461 /*********************
1462 * Setup some defaults and clear down the buffers
1463 *******************/
1465 /** save current context and drawable **/
1466 oldContext = glXGetCurrentContext();
1467 oldDrawable = glXGetCurrentDrawable();
1469 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1470 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1471 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1473 checkGLcall("glXMakeCurrent");
1475 TRACE("Setting up the screen\n");
1476 /* Clear the screen */
1477 glClearColor(1.0, 0.0, 0.0, 0.0);
1478 checkGLcall("glClearColor");
1481 glClearStencil(0xffff);
1483 checkGLcall("glClear");
1485 glColor3f(1.0, 1.0, 1.0);
1486 checkGLcall("glColor3f");
1488 glEnable(GL_LIGHTING);
1489 checkGLcall("glEnable");
1491 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1492 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1494 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1495 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1497 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1498 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1500 /* switch back to the original context (if there was one)*/
1501 if (This->swapchains != NULL) {
1502 /** TODO: restore the context and drawable **/
1503 glXMakeCurrent(object->display, oldDrawable, oldContext);
1508 { /* Finally add the swapchain to the end of the devices' swapchain list */
1509 SwapChainList **nextSwapchain;
1510 nextSwapchain = &This->swapchains;
1511 while (*nextSwapchain != NULL) {
1512 nextSwapchain = &((*nextSwapchain)->next);
1514 (*nextSwapchain) = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->swapchains));
1515 (*nextSwapchain)->swapchain = (IWineD3DSwapChain *)object;
1517 TRACE("Set swapchain to %p\n", object);
1518 } else { /* something went wrong so clean up */
1519 IUnknown* bufferParent;
1520 if (object->frontBuffer) {
1522 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1523 IUnknown_Release(bufferParent); /* once for the get parent */
1524 if (IUnknown_Release(bufferParent) > 0) {
1525 FIXME("(%p) Something's still holding the front buffer\n",This);
1528 if (object->backBuffer) {
1529 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1530 IUnknown_Release(bufferParent); /* once for the get parent */
1531 if (IUnknown_Release(bufferParent) > 0) {
1532 FIXME("(%p) Something's still holding the back buffer\n",This);
1535 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1536 /* Clean up the context */
1537 /* check that we are the current context first (we shouldn't be though!) */
1538 if (object->glCtx != 0) {
1539 if(glXGetCurrentContext() == object->glCtx) {
1540 glXMakeCurrent(object->display, None, NULL);
1542 glXDestroyContext(object->display, object->glCtx);
1544 HeapFree(GetProcessHeap(), 0, object);
1551 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1552 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1553 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1554 unsigned int numberOfSwapChains = 0;
1555 SwapChainList *swapchain;
1557 swapchain = This->swapchains;
1558 /* itterate through the list to get a count */
1559 while (swapchain != NULL) {
1560 swapchain = swapchain->next;
1561 numberOfSwapChains++;
1564 TRACE("(%p) returning %d\n", This, numberOfSwapChains);
1565 return numberOfSwapChains;
1568 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1569 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1570 SwapChainList *swapchain;
1572 HRESULT hr = WINED3DERR_INVALIDCALL;
1573 swapchain = This->swapchains;
1574 TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1577 TRACE("(%p) Finding swapchain %d\n", This, iSwapChain);
1578 while (i > 0 && swapchain != NULL) {
1579 swapchain = swapchain->next;
1584 FIXME("(%p) Unable to find swapchain %d\n", This, iSwapChain);
1586 } else if (swapchain != NULL) {
1587 /** TODO: move off to a linkesList implementation **/
1588 *pSwapChain = swapchain->swapchain;
1589 IWineD3DSwapChain_AddRef(*pSwapChain);
1593 TRACE("(%p) returning %p\n", This, *pSwapChain);
1597 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
1598 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1600 FIXME("(%p) : Stub\n",This);
1606 * Vertex Declaration
1608 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1609 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1610 IWineD3DVertexDeclarationImpl *object = NULL;
1611 HRESULT hr = WINED3D_OK;
1612 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1613 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1616 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1621 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1622 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pDeclaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1623 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1624 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1625 HRESULT hr = WINED3D_OK;
1626 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1627 object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins;
1629 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1631 /* If a vertex declaration has been passed, save it to the vertex shader, this affects d3d8 only. */
1632 /* Further it needs to be set before calling SetFunction as SetFunction needs the declaration. */
1633 if (pDeclaration != NULL) {
1634 IWineD3DVertexDeclaration *vertexDeclaration;
1635 hr = IWineD3DDevice_CreateVertexDeclaration(iface, pDeclaration, &vertexDeclaration ,NULL);
1636 if (WINED3D_OK == hr) {
1637 TRACE("(%p) : Setting vertex declaration to %p\n", This, vertexDeclaration);
1638 object->vertexDeclaration = vertexDeclaration;
1640 FIXME("(%p) : Failed to set the declaration, returning WINED3DERR_INVALIDCALL\n", iface);
1641 IWineD3DVertexShader_Release(*ppVertexShader);
1642 return WINED3DERR_INVALIDCALL;
1646 hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1648 if (WINED3D_OK != hr) {
1649 FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface);
1650 IWineD3DVertexShader_Release(*ppVertexShader);
1651 return WINED3DERR_INVALIDCALL;
1654 #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. */
1655 if(Usage == WINED3DUSAGE_SOFTWAREVERTEXPROCESSING) {
1666 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
1667 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1668 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1669 HRESULT hr = WINED3D_OK;
1671 D3DCREATEOBJECTINSTANCE(object, PixelShader)
1672 object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins;
1673 hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
1674 if (WINED3D_OK == hr) {
1675 TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
1677 WARN("(%p) : Failed to create pixel shader\n", This);
1683 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
1684 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1685 *ppD3D= This->wineD3D;
1686 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1687 IWineD3D_AddRef(*ppD3D);
1691 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1692 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1693 * Into the video ram as possible and seeing how many fit
1694 * you can also get the correct initial value from via X and ATI's driver
1695 *******************/
1696 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1697 static BOOL showfixmes = TRUE;
1699 FIXME("(%p) : stub, emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1700 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1703 TRACE("(%p) : emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1704 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1705 /* videomemory is simulated videomemory + AGP memory left */
1706 return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1714 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1715 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1716 HRESULT hr = WINED3D_OK;
1718 /* Update the current state block */
1719 This->updateStateBlock->fvf = fvf;
1720 This->updateStateBlock->changed.fvf = TRUE;
1721 This->updateStateBlock->set.fvf = TRUE;
1723 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1726 /* clear down the vertex declaration
1727 NOTE: Axis and Allies doesn't work properly otherwise
1728 (may be a stateblock problem though!)
1730 hr = IWineD3DDevice_SetVertexDeclaration(iface, NULL);
1737 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1738 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1739 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1740 *pfvf = This->stateBlock->fvf;
1745 * Get / Set Stream Source
1747 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1748 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1749 IWineD3DVertexBuffer *oldSrc;
1751 /**TODO: instance and index data, see
1752 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1754 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
1757 /* D3d9 only, but shouldn't hurt d3d8 */
1760 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1762 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1763 FIXME("stream index data not supported\n");
1765 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1766 FIXME("stream instance data not supported\n");
1770 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1772 if (StreamNumber >= MAX_STREAMS) {
1773 WARN("Stream out of range %d\n", StreamNumber);
1774 return WINED3DERR_INVALIDCALL;
1777 oldSrc = This->stateBlock->streamSource[StreamNumber];
1778 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1780 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
1781 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
1782 This->updateStateBlock->streamStride[StreamNumber] = Stride;
1783 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
1784 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
1785 This->updateStateBlock->streamFlags[StreamNumber] = streamFlags;
1787 /* Handle recording of state blocks */
1788 if (This->isRecordingState) {
1789 TRACE("Recording... not performing anything\n");
1793 /* Not recording... */
1794 /* Need to do a getParent and pass the reffs up */
1795 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
1796 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
1797 so for now, just count internally */
1798 if (pStreamData != NULL) {
1799 IWineD3DVertexBuffer_AddRef(pStreamData);
1801 if (oldSrc != NULL) {
1802 IWineD3DVertexBuffer_Release(oldSrc);
1808 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
1809 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1812 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
1813 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
1816 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1818 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1819 FIXME("stream index data not supported\n");
1821 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1822 FIXME("stream instance data not supported\n");
1826 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1828 if (StreamNumber >= MAX_STREAMS) {
1829 WARN("Stream out of range %d\n", StreamNumber);
1830 return WINED3DERR_INVALIDCALL;
1832 *pStream = This->stateBlock->streamSource[StreamNumber];
1833 *pStride = This->stateBlock->streamStride[StreamNumber];
1834 *pOffset = This->stateBlock->streamOffset[StreamNumber];
1836 if (*pStream == NULL) {
1837 FIXME("Attempting to get an empty stream %d, returning WINED3DERR_INVALIDCALL\n", StreamNumber);
1838 return WINED3DERR_INVALIDCALL;
1841 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
1845 /*Should be quite easy, just an extension of vertexdata
1847 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1849 The divider is a bit odd though
1851 VertexOffset = StartVertex / Divider * StreamStride +
1852 VertexIndex / Divider * StreamStride + StreamOffset
1855 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
1856 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1858 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
1859 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (D3DSTREAMSOURCE_INSTANCEDATA | D3DSTREAMSOURCE_INDEXEDDATA );
1861 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
1862 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
1863 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
1865 if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
1866 FIXME("Stream indexing not fully supported\n");
1872 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
1873 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1875 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
1876 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
1878 TRACE("(%p) : returning %d\n", This, *Divider);
1884 * Get / Set & Multiply Transform
1886 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1887 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1889 /* Most of this routine, comments included copied from ddraw tree initially: */
1890 TRACE("(%p) : Transform State=%d\n", This, d3dts);
1892 /* Handle recording of state blocks */
1893 if (This->isRecordingState) {
1894 TRACE("Recording... not performing anything\n");
1895 This->updateStateBlock->changed.transform[d3dts] = TRUE;
1896 This->updateStateBlock->set.transform[d3dts] = TRUE;
1897 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1902 * If the new matrix is the same as the current one,
1903 * we cut off any further processing. this seems to be a reasonable
1904 * optimization because as was noticed, some apps (warcraft3 for example)
1905 * tend towards setting the same matrix repeatedly for some reason.
1907 * From here on we assume that the new matrix is different, wherever it matters.
1909 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1910 TRACE("The app is setting the same matrix over again\n");
1913 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1917 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1918 where ViewMat = Camera space, WorldMat = world space.
1920 In OpenGL, camera and world space is combined into GL_MODELVIEW
1921 matrix. The Projection matrix stay projection matrix.
1924 /* Capture the times we can just ignore the change for now */
1925 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1926 This->modelview_valid = FALSE;
1929 } else if (d3dts == D3DTS_PROJECTION) {
1930 This->proj_valid = FALSE;
1933 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1934 /* Indexed Vertex Blending Matrices 256 -> 511 */
1935 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1936 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1940 /* Now we really are going to have to change a matrix */
1943 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1944 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
1945 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1948 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1949 * NOTE: We have to reset the positions even if the light/plane is not currently
1950 * enabled, since the call to enable it will not reset the position.
1951 * NOTE2: Apparently texture transforms do NOT need reapplying
1954 PLIGHTINFOEL *lightChain = NULL;
1955 This->modelview_valid = FALSE;
1956 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
1958 glMatrixMode(GL_MODELVIEW);
1959 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1961 glLoadMatrixf((float *)lpmatrix);
1962 checkGLcall("glLoadMatrixf(...)");
1965 lightChain = This->stateBlock->lights;
1966 while (lightChain && lightChain->glIndex != -1) {
1967 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1968 checkGLcall("glLightfv posn");
1969 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1970 checkGLcall("glLightfv dirn");
1971 lightChain = lightChain->next;
1974 /* Reset Clipping Planes if clipping is enabled */
1975 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1976 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1977 checkGLcall("glClipPlane");
1981 } else { /* What was requested!?? */
1982 WARN("invalid matrix specified: %i\n", d3dts);
1985 /* Release lock, all done */
1990 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1991 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1992 TRACE("(%p) : for Transform State %d\n", This, State);
1993 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1997 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1998 D3DMATRIX *mat = NULL;
2001 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2002 * below means it will be recorded in a state block change, but it
2003 * works regardless where it is recorded.
2004 * If this is found to be wrong, change to StateBlock.
2006 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2007 TRACE("(%p) : For state %u\n", This, State);
2009 if (State < HIGHEST_TRANSFORMSTATE)
2011 mat = &This->updateStateBlock->transforms[State];
2013 FIXME("Unhandled transform state!!\n");
2016 /* Copied from ddraw code: */
2017 temp.u.s._11 = (mat->u.s._11 * pMatrix->u.s._11) + (mat->u.s._21 * pMatrix->u.s._12) +
2018 (mat->u.s._31 * pMatrix->u.s._13) + (mat->u.s._41 * pMatrix->u.s._14);
2019 temp.u.s._21 = (mat->u.s._11 * pMatrix->u.s._21) + (mat->u.s._21 * pMatrix->u.s._22) +
2020 (mat->u.s._31 * pMatrix->u.s._23) + (mat->u.s._41 * pMatrix->u.s._24);
2021 temp.u.s._31 = (mat->u.s._11 * pMatrix->u.s._31) + (mat->u.s._21 * pMatrix->u.s._32) +
2022 (mat->u.s._31 * pMatrix->u.s._33) + (mat->u.s._41 * pMatrix->u.s._34);
2023 temp.u.s._41 = (mat->u.s._11 * pMatrix->u.s._41) + (mat->u.s._21 * pMatrix->u.s._42) +
2024 (mat->u.s._31 * pMatrix->u.s._43) + (mat->u.s._41 * pMatrix->u.s._44);
2026 temp.u.s._12 = (mat->u.s._12 * pMatrix->u.s._11) + (mat->u.s._22 * pMatrix->u.s._12) +
2027 (mat->u.s._32 * pMatrix->u.s._13) + (mat->u.s._42 * pMatrix->u.s._14);
2028 temp.u.s._22 = (mat->u.s._12 * pMatrix->u.s._21) + (mat->u.s._22 * pMatrix->u.s._22) +
2029 (mat->u.s._32 * pMatrix->u.s._23) + (mat->u.s._42 * pMatrix->u.s._24);
2030 temp.u.s._32 = (mat->u.s._12 * pMatrix->u.s._31) + (mat->u.s._22 * pMatrix->u.s._32) +
2031 (mat->u.s._32 * pMatrix->u.s._33) + (mat->u.s._42 * pMatrix->u.s._34);
2032 temp.u.s._42 = (mat->u.s._12 * pMatrix->u.s._41) + (mat->u.s._22 * pMatrix->u.s._42) +
2033 (mat->u.s._32 * pMatrix->u.s._43) + (mat->u.s._42 * pMatrix->u.s._44);
2035 temp.u.s._13 = (mat->u.s._13 * pMatrix->u.s._11) + (mat->u.s._23 * pMatrix->u.s._12) +
2036 (mat->u.s._33 * pMatrix->u.s._13) + (mat->u.s._43 * pMatrix->u.s._14);
2037 temp.u.s._23 = (mat->u.s._13 * pMatrix->u.s._21) + (mat->u.s._23 * pMatrix->u.s._22) +
2038 (mat->u.s._33 * pMatrix->u.s._23) + (mat->u.s._43 * pMatrix->u.s._24);
2039 temp.u.s._33 = (mat->u.s._13 * pMatrix->u.s._31) + (mat->u.s._23 * pMatrix->u.s._32) +
2040 (mat->u.s._33 * pMatrix->u.s._33) + (mat->u.s._43 * pMatrix->u.s._34);
2041 temp.u.s._43 = (mat->u.s._13 * pMatrix->u.s._41) + (mat->u.s._23 * pMatrix->u.s._42) +
2042 (mat->u.s._33 * pMatrix->u.s._43) + (mat->u.s._43 * pMatrix->u.s._44);
2044 temp.u.s._14 = (mat->u.s._14 * pMatrix->u.s._11) + (mat->u.s._24 * pMatrix->u.s._12) +
2045 (mat->u.s._34 * pMatrix->u.s._13) + (mat->u.s._44 * pMatrix->u.s._14);
2046 temp.u.s._24 = (mat->u.s._14 * pMatrix->u.s._21) + (mat->u.s._24 * pMatrix->u.s._22) +
2047 (mat->u.s._34 * pMatrix->u.s._23) + (mat->u.s._44 * pMatrix->u.s._24);
2048 temp.u.s._34 = (mat->u.s._14 * pMatrix->u.s._31) + (mat->u.s._24 * pMatrix->u.s._32) +
2049 (mat->u.s._34 * pMatrix->u.s._33) + (mat->u.s._44 * pMatrix->u.s._34);
2050 temp.u.s._44 = (mat->u.s._14 * pMatrix->u.s._41) + (mat->u.s._24 * pMatrix->u.s._42) +
2051 (mat->u.s._34 * pMatrix->u.s._43) + (mat->u.s._44 * pMatrix->u.s._44);
2053 /* Apply change via set transform - will reapply to eg. lights this way */
2054 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2059 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
2061 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2062 you can reference any indexes you want as long as that number max are enabled at any
2063 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2064 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2065 but when recording, just build a chain pretty much of commands to be replayed. */
2067 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2069 PLIGHTINFOEL *object, *temp;
2071 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2072 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2074 /* If recording state block, just add to end of lights chain */
2075 if (This->isRecordingState) {
2076 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2077 if (NULL == object) {
2078 return WINED3DERR_OUTOFVIDEOMEMORY;
2080 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2081 object->OriginalIndex = Index;
2082 object->glIndex = -1;
2083 object->changed = TRUE;
2085 /* Add to the END of the chain of lights changes to be replayed */
2086 if (This->updateStateBlock->lights == NULL) {
2087 This->updateStateBlock->lights = object;
2089 temp = This->updateStateBlock->lights;
2090 while (temp->next != NULL) temp=temp->next;
2091 temp->next = object;
2093 TRACE("Recording... not performing anything more\n");
2097 /* Ok, not recording any longer so do real work */
2098 object = This->stateBlock->lights;
2099 while (object != NULL && object->OriginalIndex != Index) object = object->next;
2101 /* If we didn't find it in the list of lights, time to add it */
2102 if (object == NULL) {
2103 PLIGHTINFOEL *insertAt,*prevPos;
2105 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2106 if (NULL == object) {
2107 return WINED3DERR_OUTOFVIDEOMEMORY;
2109 object->OriginalIndex = Index;
2110 object->glIndex = -1;
2112 /* Add it to the front of list with the idea that lights will be changed as needed
2113 BUT after any lights currently assigned GL indexes */
2114 insertAt = This->stateBlock->lights;
2116 while (insertAt != NULL && insertAt->glIndex != -1) {
2118 insertAt = insertAt->next;
2121 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2122 This->stateBlock->lights = object;
2123 } else if (insertAt == NULL) { /* End of list */
2124 prevPos->next = object;
2125 object->prev = prevPos;
2126 } else { /* Middle of chain */
2127 if (prevPos == NULL) {
2128 This->stateBlock->lights = object;
2130 prevPos->next = object;
2132 object->prev = prevPos;
2133 object->next = insertAt;
2134 insertAt->prev = object;
2138 /* Initialize the object */
2139 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,
2140 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2141 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2142 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2143 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2144 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2145 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2147 /* Save away the information */
2148 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2150 switch (pLight->Type) {
2151 case D3DLIGHT_POINT:
2153 object->lightPosn[0] = pLight->Position.x;
2154 object->lightPosn[1] = pLight->Position.y;
2155 object->lightPosn[2] = pLight->Position.z;
2156 object->lightPosn[3] = 1.0f;
2157 object->cutoff = 180.0f;
2161 case D3DLIGHT_DIRECTIONAL:
2163 object->lightPosn[0] = -pLight->Direction.x;
2164 object->lightPosn[1] = -pLight->Direction.y;
2165 object->lightPosn[2] = -pLight->Direction.z;
2166 object->lightPosn[3] = 0.0;
2167 object->exponent = 0.0f;
2168 object->cutoff = 180.0f;
2173 object->lightPosn[0] = pLight->Position.x;
2174 object->lightPosn[1] = pLight->Position.y;
2175 object->lightPosn[2] = pLight->Position.z;
2176 object->lightPosn[3] = 1.0;
2179 object->lightDirn[0] = pLight->Direction.x;
2180 object->lightDirn[1] = pLight->Direction.y;
2181 object->lightDirn[2] = pLight->Direction.z;
2182 object->lightDirn[3] = 1.0;
2185 * opengl-ish and d3d-ish spot lights use too different models for the
2186 * light "intensity" as a function of the angle towards the main light direction,
2187 * so we only can approximate very roughly.
2188 * however spot lights are rather rarely used in games (if ever used at all).
2189 * furthermore if still used, probably nobody pays attention to such details.
2191 if (pLight->Falloff == 0) {
2194 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2196 if (rho < 0.0001) rho = 0.0001f;
2197 object->exponent = -0.3/log(cos(rho/2));
2198 object->cutoff = pLight->Phi*90/M_PI;
2204 FIXME("Unrecognized light type %d\n", pLight->Type);
2207 /* Update the live definitions if the light is currently assigned a glIndex */
2208 if (object->glIndex != -1) {
2209 setup_light(iface, object->glIndex, object);
2214 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2215 PLIGHTINFOEL *lightInfo = NULL;
2216 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2217 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2219 /* Locate the light in the live lights */
2220 lightInfo = This->stateBlock->lights;
2221 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2223 if (lightInfo == NULL) {
2224 TRACE("Light information requested but light not defined\n");
2225 return WINED3DERR_INVALIDCALL;
2228 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
2233 * Get / Set Light Enable
2234 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2236 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2237 PLIGHTINFOEL *lightInfo = NULL;
2238 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2239 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2241 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2242 if (This->isRecordingState) {
2243 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2244 if (NULL == lightInfo) {
2245 return WINED3DERR_OUTOFVIDEOMEMORY;
2247 lightInfo->OriginalIndex = Index;
2248 lightInfo->glIndex = -1;
2249 lightInfo->enabledChanged = TRUE;
2251 /* Add to the END of the chain of lights changes to be replayed */
2252 if (This->updateStateBlock->lights == NULL) {
2253 This->updateStateBlock->lights = lightInfo;
2255 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2256 while (temp->next != NULL) temp=temp->next;
2257 temp->next = lightInfo;
2259 TRACE("Recording... not performing anything more\n");
2263 /* Not recording... So, locate the light in the live lights */
2264 lightInfo = This->stateBlock->lights;
2265 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2267 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2268 if (lightInfo == NULL) {
2269 D3DLIGHT9 lightParms;
2270 /* Warning - untested code :-) Prob safe to change fixme to a trace but
2271 wait until someone confirms it seems to work! */
2272 TRACE("Light enabled requested but light not defined, so defining one!\n");
2273 lightParms.Type = D3DLIGHT_DIRECTIONAL;
2274 lightParms.Diffuse.r = 1.0;
2275 lightParms.Diffuse.g = 1.0;
2276 lightParms.Diffuse.b = 1.0;
2277 lightParms.Diffuse.a = 0.0;
2278 lightParms.Specular.r = 0.0;
2279 lightParms.Specular.g = 0.0;
2280 lightParms.Specular.b = 0.0;
2281 lightParms.Specular.a = 0.0;
2282 lightParms.Ambient.r = 0.0;
2283 lightParms.Ambient.g = 0.0;
2284 lightParms.Ambient.b = 0.0;
2285 lightParms.Ambient.a = 0.0;
2286 lightParms.Position.x = 0.0;
2287 lightParms.Position.y = 0.0;
2288 lightParms.Position.z = 0.0;
2289 lightParms.Direction.x = 0.0;
2290 lightParms.Direction.y = 0.0;
2291 lightParms.Direction.z = 1.0;
2292 lightParms.Range = 0.0;
2293 lightParms.Falloff = 0.0;
2294 lightParms.Attenuation0 = 0.0;
2295 lightParms.Attenuation1 = 0.0;
2296 lightParms.Attenuation2 = 0.0;
2297 lightParms.Theta = 0.0;
2298 lightParms.Phi = 0.0;
2299 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
2301 /* Search for it again! Should be fairly quick as near head of list */
2302 lightInfo = This->stateBlock->lights;
2303 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2304 if (lightInfo == NULL) {
2305 FIXME("Adding default lights has failed dismally\n");
2306 return WINED3DERR_INVALIDCALL;
2310 /* OK, we now have a light... */
2311 if (Enable == FALSE) {
2313 /* If we are disabling it, check it was enabled, and
2314 still only do something if it has assigned a glIndex (which it should have!) */
2315 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2316 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2318 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2319 checkGLcall("glDisable GL_LIGHT0+Index");
2322 TRACE("Nothing to do as light was not enabled\n");
2324 lightInfo->lightEnabled = FALSE;
2327 /* We are enabling it. If it is enabled, it's really simple */
2328 if (lightInfo->lightEnabled) {
2330 TRACE("Nothing to do as light was enabled\n");
2332 /* If it already has a glIndex, it's still simple */
2333 } else if (lightInfo->glIndex != -1) {
2334 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2335 lightInfo->lightEnabled = TRUE;
2337 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2338 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2341 /* Otherwise got to find space - lights are ordered gl indexes first */
2343 PLIGHTINFOEL *bsf = NULL;
2344 PLIGHTINFOEL *pos = This->stateBlock->lights;
2345 PLIGHTINFOEL *prev = NULL;
2349 /* Try to minimize changes as much as possible */
2350 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2352 /* Try to remember which index can be replaced if necessary */
2353 if (bsf==NULL && pos->lightEnabled == FALSE) {
2354 /* Found a light we can replace, save as best replacement */
2358 /* Step to next space */
2364 /* If we have too many active lights, fail the call */
2365 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2366 FIXME("Program requests too many concurrent lights\n");
2367 return WINED3DERR_INVALIDCALL;
2369 /* If we have allocated all lights, but not all are enabled,
2370 reuse one which is not enabled */
2371 } else if (Index == This->maxConcurrentLights) {
2372 /* use bsf - Simply swap the new light and the BSF one */
2373 PLIGHTINFOEL *bsfNext = bsf->next;
2374 PLIGHTINFOEL *bsfPrev = bsf->prev;
2377 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2378 if (bsf->prev != NULL) {
2379 bsf->prev->next = lightInfo;
2381 This->stateBlock->lights = lightInfo;
2384 /* If not side by side, lots of chains to update */
2385 if (bsf->next != lightInfo) {
2386 lightInfo->prev->next = bsf;
2387 bsf->next->prev = lightInfo;
2388 bsf->next = lightInfo->next;
2389 bsf->prev = lightInfo->prev;
2390 lightInfo->next = bsfNext;
2391 lightInfo->prev = bsfPrev;
2395 bsf->prev = lightInfo;
2396 bsf->next = lightInfo->next;
2397 lightInfo->next = bsf;
2398 lightInfo->prev = bsfPrev;
2403 glIndex = bsf->glIndex;
2405 lightInfo->glIndex = glIndex;
2406 lightInfo->lightEnabled = TRUE;
2408 /* Finally set up the light in gl itself */
2409 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2411 setup_light(iface, glIndex, lightInfo);
2412 glEnable(GL_LIGHT0 + glIndex);
2413 checkGLcall("glEnable GL_LIGHT0 new setup");
2416 /* If we reached the end of the allocated lights, with space in the
2417 gl lights, setup a new light */
2418 } else if (pos->glIndex == -1) {
2420 /* We reached the end of the allocated gl lights, so already
2421 know the index of the next one! */
2423 lightInfo->glIndex = glIndex;
2424 lightInfo->lightEnabled = TRUE;
2426 /* In an ideal world, it's already in the right place */
2427 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2428 /* No need to move it */
2430 /* Remove this light from the list */
2431 lightInfo->prev->next = lightInfo->next;
2432 if (lightInfo->next != NULL) {
2433 lightInfo->next->prev = lightInfo->prev;
2436 /* Add in at appropriate place (inbetween prev and pos) */
2437 lightInfo->prev = prev;
2438 lightInfo->next = pos;
2440 This->stateBlock->lights = lightInfo;
2442 prev->next = lightInfo;
2445 pos->prev = lightInfo;
2449 /* Finally set up the light in gl itself */
2450 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2452 setup_light(iface, glIndex, lightInfo);
2453 glEnable(GL_LIGHT0 + glIndex);
2454 checkGLcall("glEnable GL_LIGHT0 new setup");
2463 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2465 PLIGHTINFOEL *lightInfo = NULL;
2466 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2467 TRACE("(%p) : for idx(%ld)\n", This, Index);
2469 /* Locate the light in the live lights */
2470 lightInfo = This->stateBlock->lights;
2471 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2473 if (lightInfo == NULL) {
2474 TRACE("Light enabled state requested but light not defined\n");
2475 return WINED3DERR_INVALIDCALL;
2477 *pEnable = lightInfo->lightEnabled;
2482 * Get / Set Clip Planes
2484 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2485 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2486 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2488 /* Validate Index */
2489 if (Index >= GL_LIMITS(clipplanes)) {
2490 TRACE("Application has requested clipplane this device doesn't support\n");
2491 return WINED3DERR_INVALIDCALL;
2494 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2495 This->updateStateBlock->set.clipplane[Index] = TRUE;
2496 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2497 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2498 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2499 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2501 /* Handle recording of state blocks */
2502 if (This->isRecordingState) {
2503 TRACE("Recording... not performing anything\n");
2511 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2512 glMatrixMode(GL_MODELVIEW);
2514 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2516 TRACE("Clipplane [%f,%f,%f,%f]\n",
2517 This->updateStateBlock->clipplane[Index][0],
2518 This->updateStateBlock->clipplane[Index][1],
2519 This->updateStateBlock->clipplane[Index][2],
2520 This->updateStateBlock->clipplane[Index][3]);
2521 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2522 checkGLcall("glClipPlane");
2530 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2531 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2532 TRACE("(%p) : for idx %ld\n", This, Index);
2534 /* Validate Index */
2535 if (Index >= GL_LIMITS(clipplanes)) {
2536 TRACE("Application has requested clipplane this device doesn't support\n");
2537 return WINED3DERR_INVALIDCALL;
2540 pPlane[0] = This->stateBlock->clipplane[Index][0];
2541 pPlane[1] = This->stateBlock->clipplane[Index][1];
2542 pPlane[2] = This->stateBlock->clipplane[Index][2];
2543 pPlane[3] = This->stateBlock->clipplane[Index][3];
2548 * Get / Set Clip Plane Status
2549 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2551 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2552 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2553 FIXME("(%p) : stub\n", This);
2554 if (NULL == pClipStatus) {
2555 return WINED3DERR_INVALIDCALL;
2557 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2558 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2562 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2563 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2564 FIXME("(%p) : stub\n", This);
2565 if (NULL == pClipStatus) {
2566 return WINED3DERR_INVALIDCALL;
2568 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2569 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2574 * Get / Set Material
2575 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2577 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2578 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2580 This->updateStateBlock->changed.material = TRUE;
2581 This->updateStateBlock->set.material = TRUE;
2582 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2584 /* Handle recording of state blocks */
2585 if (This->isRecordingState) {
2586 TRACE("Recording... not performing anything\n");
2591 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2592 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2593 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2594 pMaterial->Ambient.b, pMaterial->Ambient.a);
2595 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2596 pMaterial->Specular.b, pMaterial->Specular.a);
2597 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2598 pMaterial->Emissive.b, pMaterial->Emissive.a);
2599 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2601 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2602 checkGLcall("glMaterialfv(GL_AMBIENT)");
2603 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2604 checkGLcall("glMaterialfv(GL_DIFFUSE)");
2606 /* Only change material color if specular is enabled, otherwise it is set to black */
2607 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2608 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2609 checkGLcall("glMaterialfv(GL_SPECULAR");
2611 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2612 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2613 checkGLcall("glMaterialfv(GL_SPECULAR");
2615 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2616 checkGLcall("glMaterialfv(GL_EMISSION)");
2617 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2618 checkGLcall("glMaterialf(GL_SHININESS");
2624 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2625 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2626 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2627 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2628 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2629 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2630 pMaterial->Ambient.b, pMaterial->Ambient.a);
2631 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2632 pMaterial->Specular.b, pMaterial->Specular.a);
2633 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2634 pMaterial->Emissive.b, pMaterial->Emissive.a);
2635 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2643 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2644 UINT BaseVertexIndex) {
2645 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2646 IWineD3DIndexBuffer *oldIdxs;
2648 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2649 oldIdxs = This->updateStateBlock->pIndexData;
2651 This->updateStateBlock->changed.indices = TRUE;
2652 This->updateStateBlock->set.indices = TRUE;
2653 This->updateStateBlock->pIndexData = pIndexData;
2654 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2656 /* Handle recording of state blocks */
2657 if (This->isRecordingState) {
2658 TRACE("Recording... not performing anything\n");
2662 if (NULL != pIndexData) {
2663 IWineD3DIndexBuffer_AddRef(pIndexData);
2665 if (NULL != oldIdxs) {
2666 IWineD3DIndexBuffer_Release(oldIdxs);
2671 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2672 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2674 *ppIndexData = This->stateBlock->pIndexData;
2676 /* up ref count on ppindexdata */
2678 IWineD3DIndexBuffer_AddRef(*ppIndexData);
2679 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2680 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
2682 TRACE("(%p) No index data set\n", This);
2684 TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
2690 * Get / Set Viewports
2692 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2693 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2695 TRACE("(%p)\n", This);
2696 This->updateStateBlock->changed.viewport = TRUE;
2697 This->updateStateBlock->set.viewport = TRUE;
2698 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2700 /* Handle recording of state blocks */
2701 if (This->isRecordingState) {
2702 TRACE("Recording... not performing anything\n");
2705 This->viewport_changed = TRUE;
2709 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2710 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2712 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2713 checkGLcall("glDepthRange");
2714 /* Note: GL requires lower left, DirectX supplies upper left */
2715 /* TODO: replace usage of renderTarget with context management */
2716 glViewport(pViewport->X,
2717 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2718 pViewport->Width, pViewport->Height);
2720 checkGLcall("glViewport");
2728 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2729 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2730 TRACE("(%p)\n", This);
2731 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2736 * Get / Set Render States
2737 * TODO: Verify against dx9 definitions
2739 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2741 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2742 DWORD OldValue = This->stateBlock->renderState[State];
2744 /* Simple way of referring to either a DWORD or a 4 byte float */
2750 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2751 This->updateStateBlock->changed.renderState[State] = TRUE;
2752 This->updateStateBlock->set.renderState[State] = TRUE;
2753 This->updateStateBlock->renderState[State] = Value;
2755 /* Handle recording of state blocks */
2756 if (This->isRecordingState) {
2757 TRACE("Recording... not performing anything\n");
2764 case WINED3DRS_FILLMODE :
2765 switch ((D3DFILLMODE) Value) {
2766 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2767 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2768 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2770 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
2772 checkGLcall("glPolygonMode (fillmode)");
2775 case WINED3DRS_LIGHTING :
2777 glEnable(GL_LIGHTING);
2778 checkGLcall("glEnable GL_LIGHTING");
2780 glDisable(GL_LIGHTING);
2781 checkGLcall("glDisable GL_LIGHTING");
2785 case WINED3DRS_ZENABLE :
2786 switch ((D3DZBUFFERTYPE) Value) {
2788 glDisable(GL_DEPTH_TEST);
2789 checkGLcall("glDisable GL_DEPTH_TEST");
2792 glEnable(GL_DEPTH_TEST);
2793 checkGLcall("glEnable GL_DEPTH_TEST");
2796 glEnable(GL_DEPTH_TEST);
2797 checkGLcall("glEnable GL_DEPTH_TEST");
2798 FIXME("W buffer is not well handled\n");
2801 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2805 case WINED3DRS_CULLMODE :
2807 /* If we are culling "back faces with clockwise vertices" then
2808 set front faces to be counter clockwise and enable culling
2810 switch ((D3DCULL) Value) {
2812 glDisable(GL_CULL_FACE);
2813 checkGLcall("glDisable GL_CULL_FACE");
2816 glEnable(GL_CULL_FACE);
2817 checkGLcall("glEnable GL_CULL_FACE");
2818 if (This->renderUpsideDown) {
2820 checkGLcall("glFrontFace GL_CW");
2822 glFrontFace(GL_CCW);
2823 checkGLcall("glFrontFace GL_CCW");
2825 glCullFace(GL_BACK);
2828 glEnable(GL_CULL_FACE);
2829 checkGLcall("glEnable GL_CULL_FACE");
2830 if (This->renderUpsideDown) {
2831 glFrontFace(GL_CCW);
2832 checkGLcall("glFrontFace GL_CCW");
2835 checkGLcall("glFrontFace GL_CW");
2837 glCullFace(GL_BACK);
2840 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2844 case WINED3DRS_SHADEMODE :
2845 switch ((D3DSHADEMODE) Value) {
2847 glShadeModel(GL_FLAT);
2848 checkGLcall("glShadeModel");
2850 case D3DSHADE_GOURAUD:
2851 glShadeModel(GL_SMOOTH);
2852 checkGLcall("glShadeModel");
2854 case D3DSHADE_PHONG:
2855 FIXME("D3DSHADE_PHONG isn't supported?\n");
2858 return WINED3DERR_INVALIDCALL;
2860 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2864 case WINED3DRS_DITHERENABLE :
2866 glEnable(GL_DITHER);
2867 checkGLcall("glEnable GL_DITHER");
2869 glDisable(GL_DITHER);
2870 checkGLcall("glDisable GL_DITHER");
2874 case WINED3DRS_ZWRITEENABLE :
2877 checkGLcall("glDepthMask");
2880 checkGLcall("glDepthMask");
2884 case WINED3DRS_ZFUNC :
2886 int glParm = GL_LESS;
2888 switch ((D3DCMPFUNC) Value) {
2889 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2890 case D3DCMP_LESS: glParm=GL_LESS; break;
2891 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2892 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2893 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2894 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2895 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2896 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2898 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2900 glDepthFunc(glParm);
2901 checkGLcall("glDepthFunc");
2905 case WINED3DRS_AMBIENT :
2908 D3DCOLORTOGLFLOAT4(Value, col);
2909 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2910 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2911 checkGLcall("glLightModel for MODEL_AMBIENT");
2916 case WINED3DRS_ALPHABLENDENABLE :
2919 checkGLcall("glEnable GL_BLEND");
2921 glDisable(GL_BLEND);
2922 checkGLcall("glDisable GL_BLEND");
2926 case WINED3DRS_SRCBLEND :
2927 case WINED3DRS_DESTBLEND :
2929 int newVal = GL_ZERO;
2931 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2932 case D3DBLEND_ONE : newVal = GL_ONE; break;
2933 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2934 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2935 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2936 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2937 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2938 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2939 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2940 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2941 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2943 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2944 This->srcBlend = newVal;
2945 This->dstBlend = newVal;
2948 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2949 This->srcBlend = newVal;
2950 This->dstBlend = newVal;
2953 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2956 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2957 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2958 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2959 glBlendFunc(This->srcBlend, This->dstBlend);
2961 checkGLcall("glBlendFunc");
2965 case WINED3DRS_ALPHATESTENABLE :
2967 glEnable(GL_ALPHA_TEST);
2968 checkGLcall("glEnable GL_ALPHA_TEST");
2970 glDisable(GL_ALPHA_TEST);
2971 checkGLcall("glDisable GL_ALPHA_TEST");
2975 case WINED3DRS_ALPHAFUNC :
2977 int glParm = GL_LESS;
2978 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2980 switch ((D3DCMPFUNC) Value) {
2981 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2982 case D3DCMP_LESS: glParm = GL_LESS; break;
2983 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2984 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2985 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2986 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2987 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2988 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2990 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2992 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2993 glAlphaFunc(glParm, ref);
2994 This->alphafunc = glParm;
2995 checkGLcall("glAlphaFunc");
2999 case WINED3DRS_ALPHAREF :
3001 int glParm = This->alphafunc;
3004 ref = ((float) Value) / 255.0f;
3005 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
3006 glAlphaFunc(glParm, ref);
3007 checkGLcall("glAlphaFunc");
3011 case WINED3DRS_CLIPPLANEENABLE :
3012 case WINED3DRS_CLIPPING :
3014 /* Ensure we only do the changed clip planes */
3015 DWORD enable = 0xFFFFFFFF;
3016 DWORD disable = 0x00000000;
3018 /* If enabling / disabling all */
3019 if (State == WINED3DRS_CLIPPING) {
3021 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3024 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3028 enable = Value & ~OldValue;
3029 disable = ~Value & OldValue;
3032 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
3033 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
3034 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
3035 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
3036 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
3037 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
3039 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
3040 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
3041 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
3042 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
3043 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
3044 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
3046 /** update clipping status */
3048 This->stateBlock->clip_status.ClipUnion = 0;
3049 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
3051 This->stateBlock->clip_status.ClipUnion = 0;
3052 This->stateBlock->clip_status.ClipIntersection = 0;
3057 case WINED3DRS_BLENDOP :
3059 int glParm = GL_FUNC_ADD;
3061 switch ((D3DBLENDOP) Value) {
3062 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
3063 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
3064 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3065 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
3066 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
3068 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
3070 TRACE("glBlendEquation(%x)\n", glParm);
3071 glBlendEquation(glParm);
3072 checkGLcall("glBlendEquation");
3076 case WINED3DRS_TEXTUREFACTOR :
3080 /* Note the texture color applies to all textures whereas
3081 GL_TEXTURE_ENV_COLOR applies to active only */
3083 D3DCOLORTOGLFLOAT4(Value, col);
3084 /* Set the default alpha blend color */
3085 glBlendColor(col[0], col[1], col[2], col[3]);
3086 checkGLcall("glBlendColor");
3088 /* And now the default texture color as well */
3089 for (i = 0; i < GL_LIMITS(textures); i++) {
3091 /* Note the D3DRS value applies to all textures, but GL has one
3092 per texture, so apply it now ready to be used! */
3093 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3096 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3099 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3100 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3105 case WINED3DRS_SPECULARENABLE :
3107 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3108 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3109 specular color. This is wrong:
3110 Separate specular color means the specular colour is maintained separately, whereas
3111 single color means it is merged in. However in both cases they are being used to
3113 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3114 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3118 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3119 checkGLcall("glMaterialfv");
3120 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3121 glEnable(GL_COLOR_SUM_EXT);
3123 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3125 checkGLcall("glEnable(GL_COLOR_SUM)");
3127 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3129 /* for the case of enabled lighting: */
3130 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3131 checkGLcall("glMaterialfv");
3133 /* for the case of disabled lighting: */
3134 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3135 glDisable(GL_COLOR_SUM_EXT);
3137 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3139 checkGLcall("glDisable(GL_COLOR_SUM)");
3144 case WINED3DRS_STENCILENABLE :
3146 glEnable(GL_STENCIL_TEST);
3147 checkGLcall("glEnable GL_STENCIL_TEST");
3149 glDisable(GL_STENCIL_TEST);
3150 checkGLcall("glDisable GL_STENCIL_TEST");
3154 case WINED3DRS_STENCILFUNC :
3157 GLint ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3158 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3161 switch ((D3DCMPFUNC)Value) {
3162 case D3DCMP_NEVER: func = GL_NEVER; break;
3163 case D3DCMP_LESS: func = GL_LESS; break;
3164 case D3DCMP_EQUAL: func = GL_EQUAL; break;
3165 case D3DCMP_LESSEQUAL: func = GL_LEQUAL; break;
3166 case D3DCMP_GREATER: func = GL_GREATER; break;
3167 case D3DCMP_NOTEQUAL: func = GL_NOTEQUAL; break;
3168 case D3DCMP_GREATEREQUAL: func = GL_GEQUAL; break;
3169 case D3DCMP_ALWAYS: func = GL_ALWAYS; break;
3171 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3173 This->stencilfunc = func;
3174 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3175 #if 0 /* Don't use OpenGL 2.0 calls for now */
3176 if(GL_EXTCALL(glStencilFuncSeparate)) {
3177 GL_EXTCALL(glStencilFuncSeparate(GL_FRONT, func, ref, mask));
3178 checkGLcall("glStencilFuncSeparate(GL_FRONT,...)");
3182 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3183 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3184 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3185 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
3186 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
3187 glStencilFunc(func, ref, mask);
3188 checkGLcall("glStencilFunc(...)");
3190 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3191 GL_EXTCALL(glStencilFuncSeparateATI(GL_FRONT, func, ref, mask));
3192 checkGLcall("glStencilFuncSeparateATI(GL_FRONT,...)");
3194 TRACE("Separate stencil function not supported on this version of opengl");
3195 glStencilFunc(func, ref, mask);
3196 checkGLcall("glStencilFunc(...)");
3199 glStencilFunc(func, ref, mask);
3200 checkGLcall("glStencilFunc(...)");
3204 case WINED3DRS_STENCILREF :
3206 int glParm = This->stencilfunc;
3208 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3211 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3212 glStencilFunc(glParm, ref, mask);
3213 checkGLcall("glStencilFunc");
3217 case WINED3DRS_STENCILMASK :
3219 int glParm = This->stencilfunc;
3220 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3221 GLuint mask = Value;
3223 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3224 glStencilFunc(glParm, ref, mask);
3225 checkGLcall("glStencilFunc");
3229 case WINED3DRS_STENCILFAIL :
3230 case WINED3DRS_STENCILZFAIL :
3231 case WINED3DRS_STENCILPASS :
3237 GLint action = StencilOp(Value);
3239 glGetIntegerv(GL_STENCIL_FAIL, &stencilFail);
3240 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &depthFail);
3241 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &stencilPass);
3243 if(WINED3DRS_STENCILFAIL == State) {
3244 stencilFail = action;
3246 else if(WINED3DRS_STENCILZFAIL == State) {
3249 else if(WINED3DRS_STENCILPASS == State) {
3250 stencilPass = action;
3253 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3254 #if 0 /* Don't use OpenGL 2.0 calls for now */
3255 if(GL_EXTCALL(glStencilOpSeparate)) {
3256 GL_EXTCALL(glStencilOpSeparate(GL_FRONT, stencilFail, depthFail, stencilPass));
3257 checkGLcall("glStencilOpSeparate(GL_FRONT,...)");
3261 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3262 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3263 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3264 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
3265 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
3266 glStencilOp(stencilFail, depthFail, stencilPass);
3267 checkGLcall("glStencilOp(...)");
3269 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3270 GL_EXTCALL(glStencilOpSeparateATI(GL_FRONT, stencilFail, depthFail, stencilPass));
3271 checkGLcall("glStencilOpSeparateATI(GL_FRONT,...)");
3273 TRACE("Separate stencil operation not supported on this version of opengl");
3274 glStencilOp(stencilFail, depthFail, stencilPass);
3275 checkGLcall("glStencilOp(...)");
3278 glStencilOp(stencilFail, depthFail, stencilPass);
3279 checkGLcall("glStencilOp(...)");
3283 case WINED3DRS_STENCILWRITEMASK :
3285 glStencilMask(Value);
3286 TRACE("glStencilMask(%lu)\n", Value);
3287 checkGLcall("glStencilMask");
3291 case WINED3DRS_FOGENABLE :
3293 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
3295 checkGLcall("glEnable GL_FOG");
3298 checkGLcall("glDisable GL_FOG");
3303 case WINED3DRS_RANGEFOGENABLE :
3306 TRACE("Enabled RANGEFOG");
3308 TRACE("Disabled RANGEFOG");
3313 case WINED3DRS_FOGCOLOR :
3316 D3DCOLORTOGLFLOAT4(Value, col);
3317 /* Set the default alpha blend color */
3318 glFogfv(GL_FOG_COLOR, &col[0]);
3319 checkGLcall("glFog GL_FOG_COLOR");
3323 case WINED3DRS_FOGTABLEMODE :
3325 glHint(GL_FOG_HINT, GL_NICEST);
3327 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3328 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3329 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3330 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3332 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3334 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3335 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3340 case WINED3DRS_FOGVERTEXMODE :
3342 glHint(GL_FOG_HINT, GL_FASTEST);
3344 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3345 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3346 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3347 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3349 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3351 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3352 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
3357 case WINED3DRS_FOGSTART :
3360 glFogfv(GL_FOG_START, &tmpvalue.f);
3361 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3362 TRACE("Fog Start == %f\n", tmpvalue.f);
3366 case WINED3DRS_FOGEND :
3369 glFogfv(GL_FOG_END, &tmpvalue.f);
3370 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3371 TRACE("Fog End == %f\n", tmpvalue.f);
3375 case WINED3DRS_FOGDENSITY :
3378 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3379 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3383 case WINED3DRS_VERTEXBLEND :
3385 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3386 TRACE("Vertex Blending state to %ld\n", Value);
3390 case WINED3DRS_TWEENFACTOR :
3393 This->updateStateBlock->tween_factor = tmpvalue.f;
3394 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3398 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
3400 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3404 case WINED3DRS_COLORVERTEX :
3405 case WINED3DRS_DIFFUSEMATERIALSOURCE :
3406 case WINED3DRS_SPECULARMATERIALSOURCE :
3407 case WINED3DRS_AMBIENTMATERIALSOURCE :
3408 case WINED3DRS_EMISSIVEMATERIALSOURCE :
3410 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3412 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3413 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3414 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3415 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3416 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3417 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3419 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3420 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3421 Parm = GL_AMBIENT_AND_DIFFUSE;
3425 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3427 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3429 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3436 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3438 This->tracking_color = NEEDS_TRACKING;
3439 This->tracking_parm = Parm;
3443 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3448 case WINED3DRS_LINEPATTERN :
3454 tmppattern.d = Value;
3456 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3458 if (tmppattern.lp.wRepeatFactor) {
3459 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3460 checkGLcall("glLineStipple(repeat, linepattern)");
3461 glEnable(GL_LINE_STIPPLE);
3462 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3464 glDisable(GL_LINE_STIPPLE);
3465 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3470 case WINED3DRS_ZBIAS : /* D3D8 only */
3474 TRACE("ZBias value %f\n", tmpvalue.f);
3475 glPolygonOffset(0, -tmpvalue.f);
3476 checkGLcall("glPolygonOffset(0, -Value)");
3477 glEnable(GL_POLYGON_OFFSET_FILL);
3478 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3479 glEnable(GL_POLYGON_OFFSET_LINE);
3480 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3481 glEnable(GL_POLYGON_OFFSET_POINT);
3482 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3484 glDisable(GL_POLYGON_OFFSET_FILL);
3485 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3486 glDisable(GL_POLYGON_OFFSET_LINE);
3487 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3488 glDisable(GL_POLYGON_OFFSET_POINT);
3489 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3494 case WINED3DRS_NORMALIZENORMALS :
3496 glEnable(GL_NORMALIZE);
3497 checkGLcall("glEnable(GL_NORMALIZE);");
3499 glDisable(GL_NORMALIZE);
3500 checkGLcall("glDisable(GL_NORMALIZE);");
3504 case WINED3DRS_POINTSIZE :
3505 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
3507 TRACE("Set point size to %f\n", tmpvalue.f);
3508 glPointSize(tmpvalue.f);
3509 checkGLcall("glPointSize(...);");
3512 case WINED3DRS_POINTSIZE_MIN :
3513 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3515 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3516 checkGLcall("glPointParameterfEXT(...);");
3518 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3522 case WINED3DRS_POINTSIZE_MAX :
3523 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3525 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3526 checkGLcall("glPointParameterfEXT(...);");
3528 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3532 case WINED3DRS_POINTSCALE_A :
3533 case WINED3DRS_POINTSCALE_B :
3534 case WINED3DRS_POINTSCALE_C :
3535 case WINED3DRS_POINTSCALEENABLE :
3538 * POINTSCALEENABLE controls how point size value is treated. If set to
3539 * true, the point size is scaled with respect to height of viewport.
3540 * When set to false point size is in pixels.
3542 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
3545 /* Default values */
3546 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3549 * Minimum valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
3550 * This means that OpenGL will clamp really small point sizes to 1.0f.
3551 * To correct for this we need to multiply by the scale factor when sizes
3552 * are less than 1.0f. scale_factor = 1.0f / point_size.
3554 GLfloat pointSize = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSIZE]);
3555 if(pointSize > 0.0f) {
3556 GLfloat scaleFactor;
3558 if(pointSize < 1.0f) {
3559 scaleFactor = pointSize * pointSize;
3564 if(This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3565 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]) /
3566 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3567 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]) /
3568 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3569 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) /
3570 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3574 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
3575 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
3576 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
3578 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3579 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3580 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
3582 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
3586 case WINED3DRS_COLORWRITEENABLE :
3588 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3589 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3590 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3591 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3592 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3593 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3594 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3595 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3596 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3597 checkGLcall("glColorMask(...)");
3601 case WINED3DRS_LOCALVIEWER :
3603 GLint state = (Value) ? 1 : 0;
3604 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3605 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3609 case WINED3DRS_LASTPIXEL :
3612 TRACE("Last Pixel Drawing Enabled\n");
3614 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3619 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3622 TRACE("Software Processing Enabled\n");
3624 TRACE("Software Processing Disabled\n");
3629 /** not supported */
3630 case WINED3DRS_ZVISIBLE :
3633 return WINED3DERR_INVALIDCALL;
3635 case WINED3DRS_POINTSPRITEENABLE :
3637 /* TODO: NV_POINT_SPRITE */
3638 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
3639 TRACE("Point sprites not supported\n");
3644 * Point sprites are always enabled. Value controls texture coordinate
3645 * replacement mode. Must be set true for point sprites to use
3648 glEnable(GL_POINT_SPRITE_ARB);
3649 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
3652 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
3653 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, TRUE)");
3655 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, FALSE);
3656 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, FALSE)");
3660 case WINED3DRS_EDGEANTIALIAS :
3663 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3665 checkGLcall("glEnable(GL_BLEND)");
3666 glEnable(GL_LINE_SMOOTH);
3667 checkGLcall("glEnable(GL_LINE_SMOOTH)");
3669 glDisable(GL_BLEND);
3670 checkGLcall("glDisable(GL_BLEND)");
3671 glDisable(GL_LINE_SMOOTH);
3672 checkGLcall("glDisable(GL_LINE_SMOOTH)");
3676 case WINED3DRS_WRAP0 :
3677 case WINED3DRS_WRAP1 :
3678 case WINED3DRS_WRAP2 :
3679 case WINED3DRS_WRAP3 :
3680 case WINED3DRS_WRAP4 :
3681 case WINED3DRS_WRAP5 :
3682 case WINED3DRS_WRAP6 :
3683 case WINED3DRS_WRAP7 :
3684 case WINED3DRS_WRAP8 :
3685 case WINED3DRS_WRAP9 :
3686 case WINED3DRS_WRAP10 :
3687 case WINED3DRS_WRAP11 :
3688 case WINED3DRS_WRAP12 :
3689 case WINED3DRS_WRAP13 :
3690 case WINED3DRS_WRAP14 :
3691 case WINED3DRS_WRAP15 :
3693 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
3694 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
3695 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
3696 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
3697 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
3699 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
3701 TRACE("(%p)->(%s,%ld) Texture wraping not yet supported\n",This, debug_d3drenderstate(State), Value);
3703 case WINED3DRS_MULTISAMPLEANTIALIAS :
3705 if (!GL_SUPPORT(ARB_MULTISAMPLE)) {
3706 TRACE("Multisample antialiasing not supported\n");
3711 glEnable(GL_MULTISAMPLE_ARB);
3712 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
3714 glDisable(GL_MULTISAMPLE_ARB);
3715 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
3719 case WINED3DRS_SCISSORTESTENABLE :
3722 glEnable(GL_SCISSOR_TEST);
3723 checkGLcall("glEnable(GL_SCISSOR_TEST)");
3725 glDisable(GL_SCISSOR_TEST);
3726 checkGLcall("glDisable(GL_SCISSOR_TEST)");
3730 case WINED3DRS_SLOPESCALEDEPTHBIAS :
3734 glEnable(GL_POLYGON_OFFSET_FILL);
3735 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
3736 glPolygonOffset(tmpvalue.f, *((float*)&This->stateBlock->renderState[WINED3DRS_DEPTHBIAS]));
3737 checkGLcall("glPolygonOffset(...)");
3739 glDisable(GL_POLYGON_OFFSET_FILL);
3740 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
3744 case WINED3DRS_ANTIALIASEDLINEENABLE :
3747 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3749 checkGLcall("glEnable(GL_BLEND)");
3750 glEnable(GL_LINE_SMOOTH);
3751 checkGLcall("glEnable(GL_LINE_SMOOTH)");
3753 glDisable(GL_BLEND);
3754 checkGLcall("glDisable(GL_BLEND)");
3755 glDisable(GL_LINE_SMOOTH);
3756 checkGLcall("glDisable(GL_LINE_SMOOTH)");
3760 case WINED3DRS_MULTISAMPLEMASK :
3761 case WINED3DRS_PATCHEDGESTYLE :
3762 case WINED3DRS_PATCHSEGMENTS :
3763 case WINED3DRS_DEBUGMONITORTOKEN :
3764 case WINED3DRS_POSITIONORDER :
3765 case WINED3DRS_NORMALORDER :
3766 /* Direct3D9 render states */
3767 case WINED3DRS_MINTESSELLATIONLEVEL :
3768 case WINED3DRS_MAXTESSELLATIONLEVEL :
3769 case WINED3DRS_ADAPTIVETESS_X :
3770 case WINED3DRS_ADAPTIVETESS_Y :
3771 case WINED3DRS_ADAPTIVETESS_Z :
3772 case WINED3DRS_ADAPTIVETESS_W :
3773 case WINED3DRS_ENABLEADAPTIVETESSELLATION :
3775 FIXME("(%p)->(%s,%ld) not handled yet\n", This, debug_d3drenderstate(State), Value);
3778 case WINED3DRS_TWOSIDEDSTENCILMODE :
3781 TRACE("Two-sided stencil mode enabled\n");
3783 TRACE("Two-sided stencil mode disabled\n");
3787 case WINED3DRS_CCW_STENCILFAIL :
3788 case WINED3DRS_CCW_STENCILZFAIL :
3789 case WINED3DRS_CCW_STENCILPASS :
3795 GLint action = StencilOp(Value);
3797 glGetIntegerv(GL_STENCIL_BACK_FAIL, &stencilFail);
3798 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &depthFail);
3799 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS, &stencilPass);
3801 if(WINED3DRS_CCW_STENCILFAIL == State) {
3802 stencilFail = action;
3804 else if(WINED3DRS_CCW_STENCILZFAIL == State) {
3807 else if(WINED3DRS_CCW_STENCILPASS == State) {
3808 stencilPass = action;
3811 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3812 #if 0 /* Don't use OpenGL 2.0 calls for now */
3813 if(GL_EXTCALL(glStencilOpSeparate)) {
3814 GL_EXTCALL(glStencilOpSeparate(GL_BACK, stencilFail, depthFail, stencilPass));
3815 checkGLcall("glStencilOpSeparate(GL_BACK,...)");
3819 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3820 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3821 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3822 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
3823 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
3824 glStencilOp(stencilFail, depthFail, stencilPass);
3825 checkGLcall("glStencilOp(...)");
3827 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3828 GL_EXTCALL(glStencilOpSeparateATI(GL_BACK, stencilFail, depthFail, stencilPass));
3829 checkGLcall("glStencilOpSeparateATI(GL_BACK,...)");
3831 TRACE("Separate stencil operation not supported on this version of opengl");
3832 glStencilOp(stencilFail, depthFail, stencilPass);
3833 checkGLcall("glStencilOp(...)");
3836 glStencilOp(stencilFail, depthFail, stencilPass);
3837 checkGLcall("glStencilOp(...)");
3841 case WINED3DRS_CCW_STENCILFUNC :
3844 GLint ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3845 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3848 switch ((D3DCMPFUNC)Value) {
3849 case D3DCMP_NEVER: func = GL_NEVER; break;
3850 case D3DCMP_LESS: func = GL_LESS; break;
3851 case D3DCMP_EQUAL: func = GL_EQUAL; break;
3852 case D3DCMP_LESSEQUAL: func = GL_LEQUAL; break;
3853 case D3DCMP_GREATER: func = GL_GREATER; break;
3854 case D3DCMP_NOTEQUAL: func = GL_NOTEQUAL; break;
3855 case D3DCMP_GREATEREQUAL: func = GL_GEQUAL; break;
3856 case D3DCMP_ALWAYS: func = GL_ALWAYS; break;
3858 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3860 This->stencilfunc = func;
3861 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3862 #if 0 /* Don't use OpenGL 2.0 calls for now */
3863 if(GL_EXTCALL(glStencilFuncSeparate)) {
3864 GL_EXTCALL(glStencilFuncSeparate(GL_BACK, func, ref, mask));
3865 checkGLcall("glStencilFuncSeparate(GL_BACK,...)");
3869 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3870 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3871 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3872 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
3873 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
3874 glStencilFunc(func, ref, mask);
3875 checkGLcall("glStencilFunc(...)");
3877 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3878 GL_EXTCALL(glStencilFuncSeparateATI(GL_BACK, func, ref, mask));
3879 checkGLcall("glStencilFuncSeparateATI(GL_BACK,...)");
3881 TRACE("Separate stencil function not supported on this version of opengl");
3882 glStencilFunc(func, ref, mask);
3883 checkGLcall("glStencilFunc(...)");
3886 glStencilFunc(func, ref, mask);
3887 checkGLcall("glStencilFunc(...)");
3891 case WINED3DRS_COLORWRITEENABLE1 :
3892 case WINED3DRS_COLORWRITEENABLE2 :
3893 case WINED3DRS_COLORWRITEENABLE3 :
3894 case WINED3DRS_BLENDFACTOR :
3895 case WINED3DRS_SRGBWRITEENABLE :
3897 FIXME("(%p)->(%s,%ld) not handled yet\n", This, debug_d3drenderstate(State), Value);
3900 case WINED3DRS_DEPTHBIAS :
3904 glEnable(GL_POLYGON_OFFSET_FILL);
3905 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
3906 glPolygonOffset(*((float*)&This->stateBlock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS]), tmpvalue.f);
3907 checkGLcall("glPolygonOffset(...)");
3909 glDisable(GL_POLYGON_OFFSET_FILL);
3910 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
3914 case WINED3DRS_SEPARATEALPHABLENDENABLE :
3915 case WINED3DRS_SRCBLENDALPHA :
3916 case WINED3DRS_DESTBLENDALPHA :
3917 case WINED3DRS_BLENDOPALPHA :
3918 FIXME("(%p)->(%s,%ld) not handled yet\n", This, debug_d3drenderstate(State), Value);
3921 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3929 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3930 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3931 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3932 *pValue = This->stateBlock->renderState[State];
3937 * Get / Set Sampler States
3938 * TODO: Verify against dx9 definitions
3941 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3942 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3944 * SetSampler is designed to allow for more than the standard up to 8 textures
3945 * and Geforce has stopped supporting more than 6 standard textures in openGL.
3946 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3948 * http://developer.nvidia.com/object/General_FAQ.html#t6
3950 * There are two new settings for GForce
3952 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3953 * and the texture one:
3954 * GL_MAX_TEXTURE_COORDS_ARB.
3955 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3957 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
3958 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
3960 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
3961 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE, Sampler, Type);
3962 return WINED3DERR_INVALIDCALL;
3964 TRACE("Setting sampler %ld %d to %ld\n", Sampler, Type, Value);
3965 This->updateStateBlock->samplerState[Sampler][Type] = Value;
3966 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
3967 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
3969 /* Handle recording of state blocks */
3970 if (This->isRecordingState) {
3971 TRACE("Recording... not performing anything\n");
3978 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3979 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3980 /** TODO: check that sampler is in range **/
3981 *Value = This->updateStateBlock->samplerState[Sampler][Type];
3982 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
3987 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3988 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3991 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3992 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3993 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3999 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
4000 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4001 GLint scissorBox[4];
4004 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4005 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
4006 pRect->left = scissorBox[1];
4007 pRect->top = scissorBox[2];
4008 pRect->right = scissorBox[1] + scissorBox[3];
4009 pRect->bottom = scissorBox[2] + scissorBox[4];
4010 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4015 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
4016 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4017 IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
4019 TRACE("(%p) : pDecl=%p\n", This, pDecl);
4021 This->updateStateBlock->vertexDecl = pDecl;
4022 This->updateStateBlock->changed.vertexDecl = TRUE;
4023 This->updateStateBlock->set.vertexDecl = TRUE;
4025 if (This->isRecordingState) {
4026 TRACE("Recording... not performing anything\n");
4029 if (NULL != pDecl) {
4030 IWineD3DVertexDeclaration_AddRef(pDecl);
4032 if (NULL != oldDecl) {
4033 IWineD3DVertexDeclaration_Release(oldDecl);
4038 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
4039 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4041 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
4043 *ppDecl = This->stateBlock->vertexDecl;
4044 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
4048 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
4049 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4050 IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
4052 This->updateStateBlock->vertexShader = pShader;
4053 This->updateStateBlock->changed.vertexShader = TRUE;
4054 This->updateStateBlock->set.vertexShader = TRUE;
4056 if (This->isRecordingState) {
4057 TRACE("Recording... not performing anything\n");
4060 if (NULL != pShader) {
4061 IWineD3DVertexShader_AddRef(pShader);
4063 if (NULL != oldShader) {
4064 IWineD3DVertexShader_Release(oldShader);
4067 if (pShader != NULL && ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration != NULL) {
4068 TRACE("(%p) : setting vertexDeclaration(%p)\n", This, ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration);
4069 IWineD3DDevice_SetVertexDeclaration(iface, ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration);
4072 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4074 * TODO: merge HAL shaders context switching from prototype
4079 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
4080 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4082 if (NULL == ppShader) {
4083 return WINED3DERR_INVALIDCALL;
4085 *ppShader = This->stateBlock->vertexShader;
4086 if( NULL != *ppShader)
4087 IWineD3DVertexShader_AddRef(*ppShader);
4089 TRACE("(%p) : returning %p\n", This, *ppShader);
4093 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4094 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4097 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4099 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4100 iface, dstData, srcData, type, start, count, registersize);
4102 if (type != WINESHADERCNST_NONE) {
4103 if (srcData == NULL || cnt < 0) {
4104 return WINED3DERR_INVALIDCALL;
4107 CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
4110 for (i = start; i < cnt + start; ++i) {
4111 This->updateStateBlock->changed.vertexShaderConstants[i] = TRUE;
4112 This->updateStateBlock->set.vertexShaderConstants[i] = TRUE;
4113 This->updateStateBlock->vertexShaderConstantT[i] = type;
4119 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4120 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4123 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4125 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4126 iface, dstData, srcData, type, start, count, registersize);
4128 /* Verify that the requested shader constant was populated with the correct type */
4129 for (i = start; i < cnt + start; ++i) {
4130 if (This->updateStateBlock->vertexShaderConstantT[i] != type) {
4131 TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning WINED3DERR_INVALIDCALL\n",
4132 This, type, This->updateStateBlock->vertexShaderConstantT[i]);
4133 return WINED3DERR_INVALIDCALL;
4137 if (dstData == NULL || cnt < 0) {
4138 return WINED3DERR_INVALIDCALL;
4141 CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
4146 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
4147 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4149 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4150 This->updateStateBlock->vertexShaderConstantB,
4152 WINESHADERCNST_BOOL,
4155 sizeof(*pConstantData));
4158 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
4159 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4161 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4163 This->updateStateBlock->vertexShaderConstantB,
4164 WINESHADERCNST_BOOL,
4167 sizeof(*pConstantData));
4170 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
4171 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4173 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4174 This->updateStateBlock->vertexShaderConstantI,
4176 WINESHADERCNST_INTEGER,
4179 4 * sizeof(*pConstantData));
4182 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
4183 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4185 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4187 This->updateStateBlock->vertexShaderConstantI,
4188 WINESHADERCNST_INTEGER,
4191 4 * sizeof(*pConstantData));
4195 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
4196 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4198 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4199 This->updateStateBlock->vertexShaderConstantF,
4201 WINESHADERCNST_FLOAT,
4204 4 * sizeof(*pConstantData));
4207 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
4208 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4210 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4212 This->updateStateBlock->vertexShaderConstantF,
4213 WINESHADERCNST_FLOAT,
4216 4 * sizeof(*pConstantData));
4219 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
4220 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4223 WINESHADERCNST_NONE,
4229 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
4230 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4231 IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader;
4232 This->updateStateBlock->pixelShader = pShader;
4233 This->updateStateBlock->changed.pixelShader = TRUE;
4234 This->updateStateBlock->set.pixelShader = TRUE;
4236 /* Handle recording of state blocks */
4237 if (This->isRecordingState) {
4238 TRACE("Recording... not performing anything\n");
4241 if (NULL != pShader) {
4242 IWineD3DPixelShader_AddRef(pShader);
4244 if (NULL != oldShader) {
4245 IWineD3DPixelShader_Release(oldShader);
4248 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4250 * TODO: merge HAL shaders context switching from prototype
4255 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
4256 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4258 if (NULL == ppShader) {
4259 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
4260 return WINED3DERR_INVALIDCALL;
4263 *ppShader = This->stateBlock->pixelShader;
4264 if (NULL != ppShader) {
4265 IWineD3DPixelShader_AddRef(*ppShader);
4267 TRACE("(%p) : returning %p\n", This, *ppShader);
4271 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4272 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4275 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4277 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4278 iface, dstData, srcData, type, start, count, registersize);
4280 if (type != WINESHADERCNST_NONE) {
4281 if (srcData == NULL || cnt < 0) {
4282 return WINED3DERR_INVALIDCALL;
4285 CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
4288 for (i = start; i < cnt + start; ++i) {
4289 This->updateStateBlock->changed.pixelShaderConstants[i] = TRUE;
4290 This->updateStateBlock->set.pixelShaderConstants[i] = TRUE;
4291 This->updateStateBlock->pixelShaderConstantT[i] = type;
4297 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4298 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4301 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4303 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4304 iface, dstData, srcData, type, start, count, registersize);
4306 /* Verify that the requested shader constant was populated with the correct type */
4307 for (i = start; i < cnt + start; ++i) {
4308 if (This->updateStateBlock->pixelShaderConstantT[i] != type) {
4309 TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning WINED3DERR_INVALIDCALL\n",
4310 This, type, This->updateStateBlock->pixelShaderConstantT[i]);
4311 return WINED3DERR_INVALIDCALL;
4315 if (dstData == NULL || cnt < 0) {
4316 return WINED3DERR_INVALIDCALL;
4319 CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
4324 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
4325 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4327 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4328 This->updateStateBlock->pixelShaderConstantB,
4330 WINESHADERCNST_BOOL,
4333 sizeof(*pConstantData));
4336 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
4337 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4339 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4341 This->updateStateBlock->pixelShaderConstantB,
4342 WINESHADERCNST_BOOL,
4345 sizeof(*pConstantData));
4348 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
4349 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4351 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4352 This->updateStateBlock->pixelShaderConstantI,
4354 WINESHADERCNST_INTEGER,
4357 4 * sizeof(*pConstantData));
4360 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
4361 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4363 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4365 This->updateStateBlock->pixelShaderConstantI,
4366 WINESHADERCNST_INTEGER,
4369 4 * sizeof(*pConstantData));
4372 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
4373 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4375 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4376 This->updateStateBlock->pixelShaderConstantF,
4378 WINESHADERCNST_FLOAT,
4381 4 * sizeof(*pConstantData));
4384 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
4385 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4387 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4389 This->updateStateBlock->pixelShaderConstantF,
4390 WINESHADERCNST_FLOAT,
4393 4 * sizeof(*pConstantData));
4396 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
4397 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4400 WINESHADERCNST_NONE,
4406 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
4407 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4408 FIXME("(%p) : stub\n", This);
4413 * Apply / Get / Set Texture Stage States
4414 * TODO: Verify against dx9 definitions
4417 /* 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 */
4418 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
4419 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4420 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
4421 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4423 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4425 /* Check that the stage is within limits */
4426 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4427 TRACE("Attempt to access invalid texture rejected\n");
4434 case WINED3DTSS_ALPHAOP :
4435 case WINED3DTSS_COLOROP :
4436 /* nothing to do as moved to drawprim for now */
4438 case WINED3DTSS_ADDRESSW :
4439 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
4440 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
4441 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
4444 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
4445 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
4446 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
4447 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
4450 case WINED3DTSS_TEXCOORDINDEX :
4452 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
4454 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
4455 one flag, you can still specify an index value, which the system uses to
4456 determine the texture wrapping mode.
4457 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
4458 means use the vertex position (camera-space) as the input texture coordinates
4459 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
4460 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
4461 to the TEXCOORDINDEX value */
4464 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
4466 switch (Value & 0xFFFF0000) {
4467 case D3DTSS_TCI_PASSTHRU:
4468 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
4469 glDisable(GL_TEXTURE_GEN_S);
4470 glDisable(GL_TEXTURE_GEN_T);
4471 glDisable(GL_TEXTURE_GEN_R);
4472 glDisable(GL_TEXTURE_GEN_Q);
4473 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
4476 case D3DTSS_TCI_CAMERASPACEPOSITION:
4477 /* CameraSpacePosition means use the vertex position, transformed to camera space,
4478 as the input texture coordinates for this stage's texture transformation. This
4479 equates roughly to EYE_LINEAR */
4481 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4482 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4483 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4484 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4485 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4487 glMatrixMode(GL_MODELVIEW);
4490 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4491 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4492 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4493 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4496 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
4497 glEnable(GL_TEXTURE_GEN_S);
4498 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4499 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4500 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4501 glEnable(GL_TEXTURE_GEN_T);
4502 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4503 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4504 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4505 glEnable(GL_TEXTURE_GEN_R);
4506 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4507 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4508 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4512 case D3DTSS_TCI_CAMERASPACENORMAL:
4514 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4515 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4516 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4517 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4518 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4519 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
4521 glMatrixMode(GL_MODELVIEW);
4524 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4525 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4526 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4527 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4530 glEnable(GL_TEXTURE_GEN_S);
4531 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4532 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4533 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4534 glEnable(GL_TEXTURE_GEN_T);
4535 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4536 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4537 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4538 glEnable(GL_TEXTURE_GEN_R);
4539 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4540 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4541 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4546 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
4548 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4549 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4550 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4551 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4552 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4553 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
4555 glMatrixMode(GL_MODELVIEW);
4558 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4559 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4560 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4561 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4564 glEnable(GL_TEXTURE_GEN_S);
4565 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4566 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4567 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4568 glEnable(GL_TEXTURE_GEN_T);
4569 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4570 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4571 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4572 glEnable(GL_TEXTURE_GEN_R);
4573 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4574 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4575 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4580 /* Unhandled types: */
4583 /* ? disable GL_TEXTURE_GEN_n ? */
4584 glDisable(GL_TEXTURE_GEN_S);
4585 glDisable(GL_TEXTURE_GEN_T);
4586 glDisable(GL_TEXTURE_GEN_R);
4587 glDisable(GL_TEXTURE_GEN_Q);
4588 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
4595 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
4596 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);
4599 case WINED3DTSS_BUMPENVMAT00 :
4600 case WINED3DTSS_BUMPENVMAT01 :
4601 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
4603 case WINED3DTSS_BUMPENVMAT10 :
4604 case WINED3DTSS_BUMPENVMAT11 :
4605 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
4608 case WINED3DTSS_BUMPENVLSCALE :
4609 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4612 case WINED3DTSS_BUMPENVLOFFSET :
4613 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4616 case WINED3DTSS_RESULTARG :
4617 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4621 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
4622 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4631 * Get / Set Texture Stage States
4632 * TODO: Verify against dx9 definitions
4634 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
4635 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4637 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4639 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4641 /* Reject invalid texture units */
4642 if (Stage >= GL_LIMITS(textures)) {
4643 TRACE("Attempt to access invalid texture rejected\n");
4644 return WINED3DERR_INVALIDCALL;
4647 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
4648 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
4649 This->updateStateBlock->textureState[Stage][Type] = Value;
4654 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4655 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4656 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4657 *pValue = This->updateStateBlock->textureState[Stage][Type];
4664 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4666 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4667 IWineD3DBaseTexture *oldTexture;
4669 oldTexture = This->updateStateBlock->textures[Stage];
4670 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
4672 #if 0 /* TODO: check so vertex textures */
4673 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
4674 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
4679 /* Reject invalid texture units */
4680 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4681 WARN("Attempt to access invalid texture rejected\n");
4682 return WINED3DERR_INVALIDCALL;
4685 if(pTexture != NULL) {
4686 /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH; The same is
4687 * the case for WINED3DPOOL_SYSTEMMEM textures unless WINED3DDEVCAPS_TEXTURESYSTEMMORY is set.
4688 * We don't check the caps as GetDeviceCaps is inefficient and we don't set the cap anyway.
4690 if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH || ((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SYSTEMMEM) {
4691 WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
4692 return WINED3DERR_INVALIDCALL;
4696 oldTexture = This->updateStateBlock->textures[Stage];
4697 TRACE("GL_LIMITS %d\n",GL_LIMITS(textures));
4698 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
4700 This->updateStateBlock->set.textures[Stage] = TRUE;
4701 This->updateStateBlock->changed.textures[Stage] = TRUE;
4702 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
4703 This->updateStateBlock->textures[Stage] = pTexture;
4705 /* Handle recording of state blocks */
4706 if (This->isRecordingState) {
4707 TRACE("Recording... not performing anything\n");
4711 /** NOTE: MSDN says that setTexture increases the reference count,
4712 * and the the application nust set the texture back to null (or have a leaky application),
4713 * This means we should pass the refcount up to the parent
4714 *******************************/
4715 if (NULL != This->updateStateBlock->textures[Stage]) {
4716 IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
4719 if (NULL != oldTexture) {
4720 IWineD3DBaseTexture_Release(oldTexture);
4726 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4727 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4728 TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
4730 /* Reject invalid texture units */
4731 if (Stage >= GL_LIMITS(textures)) {
4732 TRACE("Attempt to access invalid texture rejected\n");
4733 return WINED3DERR_INVALIDCALL;
4735 *ppTexture=This->updateStateBlock->textures[Stage];
4737 IWineD3DBaseTexture_AddRef(*ppTexture);
4739 return WINED3DERR_INVALIDCALL;
4746 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
4747 IWineD3DSurface **ppBackBuffer) {
4748 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4749 IWineD3DSwapChain *swapChain;
4752 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4754 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4755 if (hr == WINED3D_OK) {
4756 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4757 IWineD3DSwapChain_Release(swapChain);
4759 *ppBackBuffer = NULL;
4764 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4765 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4766 WARN("(%p) : stub, calling idirect3d for now\n", This);
4767 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4770 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
4771 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4772 IWineD3DSwapChain *swapChain;
4775 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4776 if (hr == WINED3D_OK) {
4777 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4778 IWineD3DSwapChain_Release(swapChain);
4780 FIXME("(%p) Error getting display mode\n", This);
4785 * Stateblock related functions
4788 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4789 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4790 IWineD3DStateBlockImpl *object;
4791 TRACE("(%p)", This);
4793 if (This->isRecordingState) {
4794 return WINED3DERR_INVALIDCALL;
4797 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4798 if (NULL == object ) {
4799 FIXME("(%p)Error allocating memory for stateblock\n", This);
4800 return E_OUTOFMEMORY;
4802 TRACE("(%p) creted object %p\n", This, object);
4803 object->wineD3DDevice= This;
4804 /** FIXME: object->parent = parent; **/
4805 object->parent = NULL;
4806 object->blockType = WINED3DSBT_ALL;
4808 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
4810 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4811 This->updateStateBlock = object;
4812 This->isRecordingState = TRUE;
4814 TRACE("(%p) recording stateblock %p\n",This , object);
4818 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4819 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4821 if (!This->isRecordingState) {
4822 FIXME("(%p) not recording! returning error\n", This);
4823 *ppStateBlock = NULL;
4824 return WINED3DERR_INVALIDCALL;
4827 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4828 This->isRecordingState = FALSE;
4829 This->updateStateBlock = This->stateBlock;
4830 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4831 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4832 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4837 * Scene related functions
4839 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4840 /* At the moment we have no need for any functionality at the beginning
4842 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4843 TRACE("(%p) : stub\n", This);
4847 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4848 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4849 TRACE("(%p)\n", This);
4851 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4853 checkGLcall("glFlush");
4855 TRACE("End Scene\n");
4856 if(This->renderTarget != NULL) {
4858 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4859 IUnknown *targetContainer = NULL;
4860 if (WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
4861 || WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
4862 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
4863 /** always dirtify for now. we must find a better way to see that surface have been modified
4864 (Modifications should will only occur via draw-primitive, but we do need better locking
4865 switching to render-to-texture should remove the overhead though.
4867 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4868 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
4869 IWineD3DSurface_PreLoad(This->renderTarget);
4870 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4871 IUnknown_Release(targetContainer);
4874 This->sceneEnded = TRUE;
4879 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4880 CONST RECT* pSourceRect, CONST RECT* pDestRect,
4881 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4882 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4883 IWineD3DSwapChain *swapChain = NULL;
4885 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4887 TRACE("(%p) Presenting the frame\n", This);
4889 for(i = 0 ; i < swapchains ; i ++) {
4891 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4892 TRACE("presentinng chain %d, %p\n", i, swapChain);
4893 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4894 IWineD3DSwapChain_Release(swapChain);
4900 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4901 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4902 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4904 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4905 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4906 when the depth-buffer format does not contain stencil buffer information, this method fails. */
4907 GLbitfield glMask = 0;
4908 GLboolean old_ztest;
4909 GLfloat old_z_clear_value;
4910 GLint old_stencil_clear_value;
4911 GLfloat old_color_clear_value[4];
4913 CONST D3DRECT* curRect;
4915 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4916 Count, pRects, Flags, Z, Stencil);
4920 glEnable(GL_SCISSOR_TEST);
4921 checkGLcall("glEnable GL_SCISSOR_TEST");
4923 if (Count > 0 && pRects) {
4929 /* Only set the values up once, as they are not changing */
4930 if (Flags & D3DCLEAR_STENCIL) {
4931 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4932 glClearStencil(Stencil);
4933 checkGLcall("glClearStencil");
4934 glMask = glMask | GL_STENCIL_BUFFER_BIT;
4935 glStencilMask(0xFFFFFFFF);
4938 if (Flags & D3DCLEAR_ZBUFFER) {
4939 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4940 glDepthMask(GL_TRUE);
4941 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4943 checkGLcall("glClearDepth");
4944 glMask = glMask | GL_DEPTH_BUFFER_BIT;
4947 if (Flags & D3DCLEAR_TARGET) {
4948 TRACE("Clearing screen with glClear to color %lx\n", Color);
4949 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4950 glClearColor(D3DCOLOR_R(Color),
4954 checkGLcall("glClearColor");
4956 /* Clear ALL colors! */
4957 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4958 glMask = glMask | GL_COLOR_BUFFER_BIT;
4961 /* Now process each rect in turn */
4962 for (i = 0; i < Count || i == 0; i++) {
4965 /* Note gl uses lower left, width/height */
4966 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4967 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4968 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4969 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4970 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4971 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4972 checkGLcall("glScissor");
4974 glScissor(This->stateBlock->viewport.X,
4975 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
4976 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4977 This->stateBlock->viewport.Width,
4978 This->stateBlock->viewport.Height);
4979 checkGLcall("glScissor");
4982 /* Clear the selected rectangle (or full screen) */
4984 checkGLcall("glClear");
4986 /* Step to the next rectangle */
4987 if (curRect) curRect = curRect + sizeof(D3DRECT);
4990 /* Restore the old values (why..?) */
4991 if (Flags & D3DCLEAR_STENCIL) {
4992 glClearStencil(old_stencil_clear_value);
4993 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4995 if (Flags & D3DCLEAR_ZBUFFER) {
4996 glDepthMask(old_ztest);
4997 glClearDepth(old_z_clear_value);
4999 if (Flags & D3DCLEAR_TARGET) {
5000 glClearColor(old_color_clear_value[0],
5001 old_color_clear_value[1],
5002 old_color_clear_value[2],
5003 old_color_clear_value[3]);
5004 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
5005 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
5006 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
5007 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
5010 glDisable(GL_SCISSOR_TEST);
5011 checkGLcall("glDisable");
5020 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
5021 UINT PrimitiveCount) {
5023 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5024 This->stateBlock->streamIsUP = FALSE;
5026 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
5027 debug_d3dprimitivetype(PrimitiveType),
5028 StartVertex, PrimitiveCount);
5029 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
5030 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
5036 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
5037 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
5038 D3DPRIMITIVETYPE PrimitiveType,
5039 INT baseVIndex, UINT minIndex,
5040 UINT NumVertices, UINT startIndex, UINT primCount) {
5042 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5044 IWineD3DIndexBuffer *pIB;
5045 WINED3DINDEXBUFFER_DESC IdxBufDsc;
5047 pIB = This->stateBlock->pIndexData;
5048 This->stateBlock->streamIsUP = FALSE;
5050 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
5051 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5052 minIndex, NumVertices, startIndex, baseVIndex, primCount);
5054 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
5055 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
5061 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
5062 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
5067 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
5068 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
5069 UINT VertexStreamZeroStride) {
5070 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5072 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
5073 debug_d3dprimitivetype(PrimitiveType),
5074 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
5076 /* release the stream source */
5077 if (This->stateBlock->streamSource[0] != NULL) {
5078 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5081 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5082 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5083 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5084 This->stateBlock->streamIsUP = TRUE;
5086 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
5087 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
5088 /* stream zero settings set to null at end, as per the msdn
5089 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
5091 This->stateBlock->streamStride[0] = 0;
5092 This->stateBlock->streamSource[0] = NULL;
5094 /*stream zero settings set to null at end, as per the msdn */
5098 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
5099 UINT MinVertexIndex, UINT NumVertices,
5100 UINT PrimitiveCount, CONST void* pIndexData,
5101 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
5102 UINT VertexStreamZeroStride) {
5104 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5106 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
5107 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5108 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
5109 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
5111 if (IndexDataFormat == WINED3DFMT_INDEX16) {
5117 /* release the stream and index data */
5118 if (This->stateBlock->streamSource[0] != NULL) {
5119 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5121 if (This->stateBlock->pIndexData) {
5122 IWineD3DIndexBuffer_Release(This->stateBlock->pIndexData);
5125 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5126 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5127 This->stateBlock->streamIsUP = TRUE;
5128 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5130 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
5131 /* stream zero settings set to null at end as per the msdn
5132 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
5135 /* stream zero settings set to null at end as per the msdn */
5136 This->stateBlock->streamSource[0] = NULL;
5137 This->stateBlock->streamStride[0] = 0;
5142 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
5143 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
5144 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5145 HRESULT hr = WINED3D_OK;
5146 WINED3DRESOURCETYPE sourceType;
5147 WINED3DRESOURCETYPE destinationType;
5150 /* TODO: think about moving the code into IWineD3DBaseTexture */
5152 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
5154 /* verify that the source and destination textures aren't NULL */
5155 if (NULL == pSourceTexture || NULL == pDestinationTexture) {
5156 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
5157 This, pSourceTexture, pDestinationTexture);
5158 hr = WINED3DERR_INVALIDCALL;
5161 if (pSourceTexture == pDestinationTexture) {
5162 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
5163 This, pSourceTexture, pDestinationTexture);
5164 hr = WINED3DERR_INVALIDCALL;
5166 /* Verify that the source and destination textures are the same type */
5167 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
5168 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
5170 if (sourceType != destinationType) {
5171 WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
5173 hr = WINED3DERR_INVALIDCALL;
5176 /* check that both textures have the identical numbers of levels */
5177 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
5178 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
5179 hr = WINED3DERR_INVALIDCALL;
5182 if (WINED3D_OK == hr) {
5184 /* Make sure that the destination texture is loaded */
5185 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
5187 /* Update every surface level of the texture */
5188 levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
5190 switch (sourceType) {
5191 case WINED3DRTYPE_TEXTURE:
5193 IWineD3DSurface *srcSurface;
5194 IWineD3DSurface *destSurface;
5196 for (i = 0 ; i < levels ; ++i) {
5197 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture, i, &srcSurface);
5198 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
5199 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5200 IWineD3DSurface_Release(srcSurface);
5201 IWineD3DSurface_Release(destSurface);
5202 if (WINED3D_OK != hr) {
5203 WARN("(%p) : Call to update surface failed\n", This);
5209 case WINED3DRTYPE_CUBETEXTURE:
5211 IWineD3DSurface *srcSurface;
5212 IWineD3DSurface *destSurface;
5213 WINED3DCUBEMAP_FACES faceType;
5215 for (i = 0 ; i < levels ; ++i) {
5216 /* Update each cube face */
5217 for (faceType = D3DCUBEMAP_FACE_POSITIVE_X; faceType <= D3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
5218 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture, faceType, i, &srcSurface);
5219 if (WINED3D_OK != hr) {
5220 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5222 TRACE("Got srcSurface %p\n", srcSurface);
5224 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
5225 if (WINED3D_OK != hr) {
5226 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5228 TRACE("Got desrSurface %p\n", destSurface);
5230 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5231 IWineD3DSurface_Release(srcSurface);
5232 IWineD3DSurface_Release(destSurface);
5233 if (WINED3D_OK != hr) {
5234 WARN("(%p) : Call to update surface failed\n", This);
5241 #if 0 /* TODO: Add support for volume textures */
5242 case WINED3DRTYPE_VOLUMETEXTURE:
5244 IWineD3DVolume srcVolume = NULL;
5245 IWineD3DSurface destVolume = NULL;
5247 for (i = 0 ; i < levels ; ++i) {
5248 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture, i, &srcVolume);
5249 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
5250 hr = IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
5251 IWineD3DVolume_Release(srcSurface);
5252 IWineD3DVolume_Release(destSurface);
5253 if (WINED3D_OK != hr) {
5254 WARN("(%p) : Call to update volume failed\n", This);
5262 FIXME("(%p) : Unsupported source and destination type\n", This);
5263 hr = WINED3DERR_INVALIDCALL;
5270 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
5271 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
5272 CONST RECT* pDestRect, WINED3DTEXTUREFILTERTYPE Filter) {
5273 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5275 TRACE("(%p) : stub\n", This);
5278 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
5279 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5280 /** TODO: remove remove casts to IWineD3DSurfaceImpl *
5281 * NOTE It may be best to move the code into surface to occomplish this
5282 ****************************************/
5284 WINED3DSURFACE_DESC surfaceDesc;
5285 unsigned int surfaceWidth, surfaceHeight;
5286 glDescriptor *targetGlDescription = NULL;
5287 glDescriptor *surfaceGlDescription = NULL;
5288 IWineD3DSwapChainImpl *container = NULL;
5290 IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
5291 IWineD3DSurface_GetGlDesc(pSurface, &surfaceGlDescription);
5292 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5294 surfaceDesc.Width = &surfaceWidth;
5295 surfaceDesc.Height = &surfaceHeight;
5296 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5297 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
5299 /* Ok, I may need to setup some kind of active swapchain reference on the device */
5300 IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
5302 /* TODO: opengl Context switching for swapchains etc... */
5303 if (NULL != container || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
5304 if (NULL != container && (pRenderTarget == container->backBuffer)) {
5305 glReadBuffer(GL_BACK);
5306 vcheckGLcall("glReadBuffer(GL_BACK)");
5307 } else if ((NULL != container && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
5308 glReadBuffer(GL_FRONT);
5309 vcheckGLcall("glReadBuffer(GL_FRONT)");
5310 } else if (pRenderTarget == This->depthStencilBuffer) {
5311 FIXME("Reading of depthstencil not yet supported\n");
5314 glReadPixels(surfaceGlDescription->target,
5315 surfaceGlDescription->level,
5318 surfaceGlDescription->glFormat,
5319 surfaceGlDescription->glType,
5320 (void *)IWineD3DSurface_GetData(pSurface));
5321 vcheckGLcall("glReadPixels(...)");
5322 if(NULL != container ){
5323 IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
5326 IWineD3DBaseTexture *container;
5327 GLenum textureDimensions = GL_TEXTURE_2D;
5329 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
5330 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
5331 IWineD3DBaseTexture_Release(container);
5333 /* TODO: 2D -> Cube surface coppies etc.. */
5334 if (surfaceGlDescription->target != textureDimensions) {
5335 FIXME("(%p) : Texture dimension mismatch\n", This);
5337 glEnable(textureDimensions);
5338 vcheckGLcall("glEnable(GL_TEXTURE_...)");
5339 /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
5340 glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
5341 vcheckGLcall("glBindTexture");
5342 glGetTexImage(surfaceGlDescription->target,
5343 surfaceGlDescription->level,
5344 surfaceGlDescription->glFormat,
5345 surfaceGlDescription->glType,
5346 (void *)IWineD3DSurface_GetData(pSurface));
5347 glDisable(textureDimensions);
5348 vcheckGLcall("glDisable(GL_TEXTURE_...)");
5355 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
5356 IWineD3DSwapChain *swapChain;
5358 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5359 if(hr == WINED3D_OK) {
5360 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
5361 IWineD3DSwapChain_Release(swapChain);
5366 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5367 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5368 /* return a sensible default */
5370 /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
5371 FIXME("(%p) : stub\n", This);
5375 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5376 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5378 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5379 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5380 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5381 return WINED3DERR_INVALIDCALL;
5383 for (j = 0; j < 256; ++j) {
5384 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
5385 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5386 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
5387 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5389 TRACE("(%p) : returning\n", This);
5393 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5394 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5396 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5397 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5398 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5399 return WINED3DERR_INVALIDCALL;
5401 for (j = 0; j < 256; ++j) {
5402 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
5403 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5404 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
5405 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5407 TRACE("(%p) : returning\n", This);
5411 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5412 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5413 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5414 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5415 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5416 return WINED3DERR_INVALIDCALL;
5418 /*TODO: stateblocks */
5419 This->currentPalette = PaletteNumber;
5420 TRACE("(%p) : returning\n", This);
5424 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
5425 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5426 if (PaletteNumber == NULL) {
5427 WARN("(%p) : returning Invalid Call\n", This);
5428 return WINED3DERR_INVALIDCALL;
5430 /*TODO: stateblocks */
5431 *PaletteNumber = This->currentPalette;
5432 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
5436 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
5437 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5438 static BOOL showFixmes = TRUE;
5440 FIXME("(%p) : stub\n", This);
5444 This->softwareVertexProcessing = bSoftware;
5449 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
5450 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5451 static BOOL showFixmes = TRUE;
5453 FIXME("(%p) : stub\n", This);
5456 return This->softwareVertexProcessing;
5460 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
5461 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5462 IWineD3DSwapChain *swapChain;
5465 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
5467 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5468 if(hr == WINED3D_OK){
5469 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
5470 IWineD3DSwapChain_Release(swapChain);
5472 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
5478 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
5479 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5480 static BOOL showfixmes = TRUE;
5481 if(nSegments != 0.0f) {
5483 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
5490 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
5491 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5492 static BOOL showfixmes = TRUE;
5494 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
5500 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
5501 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5502 /** TODO: remove casts to IWineD3DSurfaceImpl
5503 * NOTE: move code to surface to accomplish this
5504 ****************************************/
5505 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
5506 int srcWidth, srcHeight;
5507 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
5508 WINED3DFORMAT destFormat, srcFormat;
5510 int destLeft, destTop;
5511 WINED3DPOOL srcPool, destPool;
5513 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
5514 glDescriptor *glDescription = NULL;
5515 GLenum textureDimensions = GL_TEXTURE_2D;
5516 IWineD3DBaseTexture *baseTexture;
5518 WINED3DSURFACE_DESC winedesc;
5520 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
5521 memset(&winedesc, 0, sizeof(winedesc));
5522 winedesc.Width = &srcSurfaceWidth;
5523 winedesc.Height = &srcSurfaceHeight;
5524 winedesc.Pool = &srcPool;
5525 winedesc.Format = &srcFormat;
5527 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5529 winedesc.Width = &destSurfaceWidth;
5530 winedesc.Height = &destSurfaceHeight;
5531 winedesc.Pool = &destPool;
5532 winedesc.Format = &destFormat;
5533 winedesc.Size = &destSize;
5535 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5537 if(srcPool != WINED3DPOOL_SYSTEMMEM || destPool != WINED3DPOOL_DEFAULT){
5538 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
5539 return WINED3DERR_INVALIDCALL;
5542 if (destFormat == WINED3DFMT_UNKNOWN) {
5543 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5544 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5546 /* Get the update surface description */
5547 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5550 /* Make sure the surface is loaded and up to date */
5551 IWineD3DSurface_PreLoad(pDestinationSurface);
5553 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
5557 /* this needs to be done in lines if the sourceRect != the sourceWidth */
5558 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
5559 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
5560 destLeft = pDestPoint ? pDestPoint->x : 0;
5561 destTop = pDestPoint ? pDestPoint->y : 0;
5564 /* This function doesn't support compressed textures
5565 the pitch is just bytesPerPixel * width */
5566 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
5567 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
5568 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
5569 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
5571 /* TODO DXT formats */
5573 if(pSourceRect != NULL && pSourceRect->top != 0){
5574 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
5576 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
5578 ,glDescription->level
5583 ,glDescription->glFormat
5584 ,glDescription->glType
5585 ,IWineD3DSurface_GetData(pSourceSurface)
5589 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
5591 /* need to lock the surface to get the data */
5592 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5595 /* TODO: Cube and volume support */
5597 /* not a whole row so we have to do it a line at a time */
5600 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
5601 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5603 for(j = destTop ; j < (srcHeight + destTop) ; j++){
5605 glTexSubImage2D(glDescription->target
5606 ,glDescription->level
5611 ,glDescription->glFormat
5612 ,glDescription->glType
5613 ,data /* could be quicker using */
5618 } else { /* Full width, so just write out the whole texture */
5620 if (WINED3DFMT_DXT1 == destFormat ||
5621 WINED3DFMT_DXT2 == destFormat ||
5622 WINED3DFMT_DXT3 == destFormat ||
5623 WINED3DFMT_DXT4 == destFormat ||
5624 WINED3DFMT_DXT5 == destFormat) {
5625 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
5626 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
5627 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
5628 FIXME("Updating part of a compressed texture is not supported at the moment\n");
5629 } if (destFormat != srcFormat) {
5630 FIXME("Updating mixed format compressed texture is not curretly support\n");
5632 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
5633 glDescription->level,
5634 glDescription->glFormatInternal,
5639 IWineD3DSurface_GetData(pSourceSurface));
5642 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
5647 if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
5649 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
5650 to repack the data from pow2Width/Height to expected Width,Height, this makes the
5651 data returned by GetData non-power2 width/height with hardware non-power2
5652 pow2Width/height are set to surface width height, repacking isn't needed so it
5653 doesn't matter which function gets called. */
5654 glTexSubImage2D(glDescription->target
5655 ,glDescription->level
5660 ,glDescription->glFormat
5661 ,glDescription->glType
5662 ,IWineD3DSurface_GetData(pSourceSurface)
5666 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
5667 glTexSubImage2D(glDescription->target
5668 ,glDescription->level
5671 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
5672 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
5673 ,glDescription->glFormat
5674 ,glDescription->glType
5675 ,IWineD3DSurface_GetData(pSourceSurface)
5681 checkGLcall("glTexSubImage2D");
5683 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
5684 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
5685 * surface bigger than it needs to be hmm.. */
5686 if (WINED3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
5687 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
5688 IWineD3DBaseTexture_Release(baseTexture);
5691 glDisable(textureDimensions); /* This needs to be managed better.... */
5697 /* Used by DirectX 8 */
5698 HRESULT WINAPI IWineD3DDeviceImpl_CopyRects(IWineD3DDevice *iface,
5699 IWineD3DSurface* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
5700 IWineD3DSurface* pDestinationSurface, CONST POINT* pDestPointsArray) {
5702 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5703 HRESULT hr = WINED3D_OK;
5704 WINED3DFORMAT srcFormat, destFormat;
5705 UINT srcWidth, destWidth;
5706 UINT srcHeight, destHeight;
5708 WINED3DSURFACE_DESC winedesc;
5710 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
5711 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
5714 /* Check that the source texture is in WINED3DPOOL_SYSTEMMEM and the destination texture is in WINED3DPOOL_DEFAULT */
5715 memset(&winedesc, 0, sizeof(winedesc));
5717 winedesc.Format = &srcFormat;
5718 winedesc.Width = &srcWidth;
5719 winedesc.Height = &srcHeight;
5720 winedesc.Size = &srcSize;
5721 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5723 winedesc.Format = &destFormat;
5724 winedesc.Width = &destWidth;
5725 winedesc.Height = &destHeight;
5726 winedesc.Size = NULL;
5727 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5729 /* Check that the source and destination formats match */
5730 if (srcFormat != destFormat && WINED3DFMT_UNKNOWN != destFormat) {
5731 WARN("(%p) source %p format must match the dest %p format, returning WINED3DERR_INVALIDCALL\n", This, pSourceSurface, pDestinationSurface);
5732 return WINED3DERR_INVALIDCALL;
5733 } else if (WINED3DFMT_UNKNOWN == destFormat) {
5734 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5735 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5736 destFormat = srcFormat;
5739 /* Quick if complete copy ... */
5740 if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
5742 if (srcWidth == destWidth && srcHeight == destHeight) {
5743 WINED3DLOCKED_RECT lrSrc;
5744 WINED3DLOCKED_RECT lrDst;
5745 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, NULL, WINED3DLOCK_READONLY);
5746 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, NULL, 0L);
5747 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", srcWidth, srcHeight);
5749 memcpy(lrDst.pBits, lrSrc.pBits, srcSize);
5751 IWineD3DSurface_UnlockRect(pSourceSurface);
5752 IWineD3DSurface_UnlockRect(pDestinationSurface);
5753 TRACE("Unlocked src and dst\n");
5757 FIXME("Wanted to copy all surfaces but size not compatible, returning WINED3DERR_INVALIDCALL\n");
5758 hr = WINED3DERR_INVALIDCALL;
5763 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
5765 int bytesPerPixel = ((IWineD3DSurfaceImpl *) pSourceSurface)->bytesPerPixel;
5768 /* Copy rect by rect */
5769 for (i = 0; i < cRects; ++i) {
5770 CONST RECT* r = &pSourceRectsArray[i];
5771 CONST POINT* p = &pDestPointsArray[i];
5774 WINED3DLOCKED_RECT lrSrc;
5775 WINED3DLOCKED_RECT lrDst;
5778 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
5779 if (srcFormat == WINED3DFMT_DXT1) {
5780 copyperline = ((r->right - r->left) * bytesPerPixel) / 2; /* DXT1 is half byte per pixel */
5782 copyperline = ((r->right - r->left) * bytesPerPixel);
5785 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, r, WINED3DLOCK_READONLY);
5786 dest_rect.left = p->x;
5787 dest_rect.top = p->y;
5788 dest_rect.right = p->x + (r->right - r->left);
5789 dest_rect.bottom= p->y + (r->bottom - r->top);
5790 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, &dest_rect, 0L);
5791 TRACE("Locked src and dst\n");
5793 /* Find where to start */
5794 for (j = 0; j < (r->bottom - r->top - 1); ++j) {
5795 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
5797 IWineD3DSurface_UnlockRect(pSourceSurface);
5798 IWineD3DSurface_UnlockRect(pDestinationSurface);
5799 TRACE("Unlocked src and dst\n");
5802 FIXME("Wanted to copy partial surfaces not implemented, returning WINED3DERR_INVALIDCALL\n");
5803 hr = WINED3DERR_INVALIDCALL;
5810 /* Implementation details at http://developer.nvidia.com/attach/6494
5812 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
5813 hmm.. no longer supported use
5814 OpenGL evaluators or tessellate surfaces within your application.
5817 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
5818 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
5819 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5820 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
5821 FIXME("(%p) : Stub\n", This);
5826 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
5827 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
5828 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5829 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
5830 FIXME("(%p) : Stub\n", This);
5834 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5835 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5836 TRACE("(%p) Handle(%d)\n", This, Handle);
5837 FIXME("(%p) : Stub\n", This);
5841 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
5842 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
5843 fill a surface with a block of color! */
5844 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5845 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
5846 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
5847 IWineD3DSwapChainImpl *container = NULL;
5848 BOOL isRenderTarget = FALSE;
5849 unsigned int width, height;
5850 unsigned int top, left;
5853 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
5855 if (surface->resource.pool != WINED3DPOOL_DEFAULT) {
5856 FIXME("call to colorfill with non WINED3DPOOL_DEFAULT surface\n");
5857 return WINED3DERR_INVALIDCALL;
5860 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
5861 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
5862 if (WINED3DUSAGE_RENDERTARGET & surface->resource.usage) {
5863 /* TODO: make sure we set everything back to the way it was, and context management!
5864 glGetIntegerv(GL_READ_BUFFER, &prev_read);
5865 vcheckGLcall("glIntegerv");
5866 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
5867 vcheckGLcall("glIntegerv");
5869 TRACE("Color fill to render targets may cause some graphics issues\n");
5870 if (pSurface == container->frontBuffer) {
5871 glDrawBuffer(GL_FRONT);
5873 glDrawBuffer(GL_BACK);
5876 if (WINED3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
5877 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld\n", surface, surface->resource.usage);
5879 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
5881 if (container != NULL) {
5882 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5884 /* we can use GL_STENCIL_INDEX etc...*/
5887 if (container != NULL) {
5888 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5890 isRenderTarget = TRUE;
5892 /* TODO: drawing to GL_FRONT and GL_BACK */
5893 /* TODO: see if things can be speeded up by using the correct
5894 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
5895 if (pRect == NULL) {
5898 width = surface->currentDesc.Width;
5899 height = surface->currentDesc.Height;
5903 width = pRect->x2 - left;
5904 height = pRect->y2 - top;
5907 data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
5908 /* Create a 'line' of color color, in the correct format for the surface */
5909 for (u = 0 ; u < width ; u ++) {
5914 if (isRenderTarget == FALSE) {
5915 glDescriptor *glDesc;
5916 IWineD3DSurface_PreLoad(pSurface);
5918 /* draw a block of the coloured line on the sufrace */
5919 IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
5920 for (v = 0 ; v< height;v++) {
5921 glTexSubImage2D(glDesc->target
5922 ,glDesc->level /* level */
5932 checkGLcall("glTexSubImage2D");
5934 glDisable(glDesc->target);
5936 /** FIXME: Using GLClear may be faster **/
5937 glRasterPos2i(left, top);
5938 glPixelZoom((float)width ,(float)height);
5939 glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
5940 checkGLcall("glDrawPixels");
5942 HeapFree(GetProcessHeap(), 0, data);
5948 /* rendertarget and deptth stencil functions */
5949 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
5950 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5952 /* FIXME: Implelent RenderTargetIndex >0 */
5953 if(RenderTargetIndex > 0)
5954 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
5956 *ppRenderTarget = This->renderTarget;
5957 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
5958 /* Note inc ref on returned surface */
5959 if(*ppRenderTarget != NULL)
5960 IWineD3DSurface_AddRef(*ppRenderTarget);
5964 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5965 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5966 *ppZStencilSurface = This->depthStencilBuffer;
5967 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
5969 if(*ppZStencilSurface != NULL) {
5970 /* Note inc ref on returned surface */
5971 IWineD3DSurface_AddRef(*ppZStencilSurface);
5976 /* internal static helper functions */
5977 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5978 IWineD3DSurface *RenderSurface);
5980 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5981 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5982 HRESULT hr = WINED3D_OK;
5983 WINED3DVIEWPORT viewport;
5985 TRACE("(%p) Swapping rendertarget\n",This);
5986 if (RenderTargetIndex > 0) {
5987 FIXME("(%p) Render targets other than the first are not supported\n",This);
5988 RenderTargetIndex = 0;
5991 /* MSDN says that null disables the render target
5992 but a device must always be associated with a render target
5993 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5995 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5998 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5999 FIXME("Trying to set render target 0 to NULL\n");
6000 return WINED3DERR_INVALIDCALL;
6002 /* TODO: replace Impl* usage with interface usage */
6003 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
6004 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);
6005 return WINED3DERR_INVALIDCALL;
6007 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
6008 * builds, but I think wine counts as a 'debug' build for now.
6009 ******************************/
6010 /* If we are trying to set what we already have, don't bother */
6011 if (pRenderTarget == This->renderTarget) {
6012 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6014 /* Otherwise, set the render target up */
6016 if (FALSE == This->sceneEnded) {
6017 IWineD3DDevice_EndScene(iface);
6019 TRACE("clearing renderer\n");
6020 /* IWineD3DDeviceImpl_CleanRender(iface); */
6021 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6022 depending on the renter target implementation being used.
6023 A shared context implementation will share all buffers between all rendertargets (including swapchains),
6024 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6025 stencil buffer and incure an extra memory overhead */
6026 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
6029 if (SUCCEEDED(hr)) {
6030 /* Finally, reset the viewport as the MSDN states. */
6031 /* TODO: Replace impl usage */
6032 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
6033 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
6036 viewport.MaxZ = 1.0f;
6037 viewport.MinZ = 0.0f;
6038 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
6040 FIXME("Unknown error setting the render target\n");
6042 This->sceneEnded = FALSE;
6046 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
6047 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6048 HRESULT hr = WINED3D_OK;
6049 IWineD3DSurface *tmp;
6051 TRACE("(%p) Swapping z-buffer\n",This);
6053 if (pNewZStencil == This->stencilBufferTarget) {
6054 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6056 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6057 * depending on the renter target implementation being used.
6058 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
6059 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6060 * stencil buffer and incure an extra memory overhead
6061 ******************************************************/
6064 tmp = This->stencilBufferTarget;
6065 This->stencilBufferTarget = pNewZStencil;
6066 /* should we be calling the parent or the wined3d surface? */
6067 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
6068 if (NULL != tmp) IWineD3DSurface_Release(tmp);
6070 /** TODO: glEnable/glDisable on depth/stencil depending on
6071 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
6072 **********************************************************/
6079 #ifdef GL_VERSION_1_3
6080 /* Internal functions not in DirectX */
6081 /** TODO: move this off to the opengl context manager
6082 *(the swapchain doesn't need to know anything about offscreen rendering!)
6083 ****************************************************/
6085 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
6087 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6089 TRACE("(%p), %p\n", This, swapchain);
6091 if (swapchain->win != swapchain->drawable) {
6092 /* Set everything back the way it ws */
6093 swapchain->render_ctx = swapchain->glCtx;
6094 swapchain->drawable = swapchain->win;
6099 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
6100 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
6101 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6104 unsigned int height;
6105 WINED3DFORMAT format;
6106 WINED3DSURFACE_DESC surfaceDesc;
6107 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
6108 surfaceDesc.Width = &width;
6109 surfaceDesc.Height = &height;
6110 surfaceDesc.Format = &format;
6111 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
6113 /* I need a get width/height function (and should do something with the format) */
6114 for (i = 0; i < CONTEXT_CACHE; ++i) {
6115 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
6116 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
6117 the pSurface can be set to 0 allowing it to be reused from cache **/
6118 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
6119 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
6120 *context = &This->contextCache[i];
6123 if (This->contextCache[i].Width == 0) {
6124 This->contextCache[i].pSurface = pSurface;
6125 This->contextCache[i].Width = width;
6126 This->contextCache[i].Height = height;
6127 *context = &This->contextCache[i];
6131 if (i == CONTEXT_CACHE) {
6132 int minUsage = 0x7FFFFFFF; /* MAX_INT */
6133 glContext *dropContext = 0;
6134 for (i = 0; i < CONTEXT_CACHE; i++) {
6135 if (This->contextCache[i].usedcount < minUsage) {
6136 dropContext = &This->contextCache[i];
6137 minUsage = This->contextCache[i].usedcount;
6140 /* clean up the context (this doesn't work for ATI at the moment */
6142 glXDestroyContext(swapchain->display, dropContext->context);
6143 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
6146 dropContext->Width = 0;
6147 dropContext->pSurface = pSurface;
6148 *context = dropContext;
6150 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
6151 for (i = 0; i < CONTEXT_CACHE; i++) {
6152 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
6156 if (*context != NULL)
6159 return E_OUTOFMEMORY;
6163 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
6164 * the functionality needs splitting up so that we don't do more than we should do.
6165 * this only seems to impact performance a little.
6166 ******************************/
6167 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
6168 IWineD3DSurface *RenderSurface) {
6169 HRESULT ret = WINED3DERR_INVALIDCALL;
6172 * Currently only active for GLX >= 1.3
6173 * for others versions we'll have to use GLXPixmaps
6175 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
6176 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
6177 * so only check OpenGL version
6178 * ..........................
6179 * I don't believe that it is a problem with NVidia headers,
6180 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
6181 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
6183 * Your application will report GLX version 1.2 on glXQueryVersion.
6184 * However, it is safe to call the GLX 1.3 functions as described below.
6186 #if defined(GL_VERSION_1_3)
6188 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6189 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
6190 IWineD3DSurface *tmp;
6191 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
6192 GLXFBConfig* cfgs = NULL;
6196 IWineD3DSwapChain *currentSwapchain;
6197 IWineD3DSwapChainImpl *swapchain;
6198 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
6199 * but switch them off if the StencilSurface is set to NULL
6200 ** *********************************************************/
6201 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
6202 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
6205 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
6206 it StencilSurface != NULL && zBufferTarget == NULL switch it on
6209 #define PUSH1(att) attribs[nAttribs++] = (att);
6210 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
6212 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
6214 /** TODO: remove the reff to Impl (context manager should fix this!) **/
6215 IWineD3DSwapChainImpl *impSwapChain;
6216 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
6217 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
6218 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
6223 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
6224 PUSH2(GLX_X_RENDERABLE, TRUE);
6225 PUSH2(GLX_DOUBLEBUFFER, TRUE);
6226 TRACE("calling makeglcfg\n");
6227 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
6230 TRACE("calling chooseFGConfig\n");
6231 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
6234 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
6235 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
6236 why we failed and only show this message once! */
6237 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"); /**/
6239 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
6240 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
6241 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
6242 PUSH2(GLX_DOUBLEBUFFER, FALSE);
6243 TRACE("calling makeglcfg\n");
6244 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
6246 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
6253 for (i = 0; i < nCfgs; ++i) {
6254 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
6255 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
6256 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
6259 if (NULL != This->renderTarget) {
6261 vcheckGLcall("glFlush");
6262 /** This is only useful if the old render target was a swapchain,
6263 * we need to supercede this with a function that displays
6264 * the current buffer on the screen. This is easy to do in glx1.3 but
6265 * we need to do copy-write pixels in glx 1.2.
6266 ************************************************/
6267 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
6269 printf("Hit Enter to get next frame ...\n");
6275 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain) != WINED3D_OK) {
6276 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
6277 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
6281 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
6282 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
6283 **********************************************************************/
6284 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == WINED3D_OK) {
6285 /* We also need to make sure that the lights &co are also in the context of the swapchains */
6286 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
6287 TRACE("making swapchain active\n");
6288 if (RenderSurface != This->renderTarget) {
6289 if (RenderSurface == swapchain->backBuffer) {
6291 /* This could be flagged so that some operations work directly with the front buffer */
6292 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
6294 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
6296 TRACE("Error in setting current context: context %p drawable %ld !\n",
6297 impSwapChain->glCtx, impSwapChain->win);
6300 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
6302 checkGLcall("glXMakeContextCurrent");
6304 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
6306 else if (pbuffer_support == TRUE && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
6308 /** ********************************************************************
6309 * This is a quickly hacked out implementation of offscreen textures.
6310 * It will work in most cases but there may be problems if the client
6311 * modifies the texture directly, or expects the contents of the rendertarget
6314 * There are some real speed vs compatibility issues here:
6315 * we should really use a new context for every texture, but that eats ram.
6316 * we should also be restoring the texture to the pbuffer but that eats CPU
6317 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
6318 * but if this means reusing the display backbuffer then we need to make sure that
6319 * states are correctly preserved.
6320 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
6321 * and gain a good performance increase at the cost of compatibility.
6322 * I would suggest that, when this is the case, a user configurable flag be made
6323 * available, allowing the user to choose the best emulated experience for them.
6324 *********************************************************************/
6326 XVisualInfo *visinfo;
6327 glContext *newContext;
6329 /* Here were using a shared context model */
6330 if (WINED3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
6331 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6334 /* If the context doesn't exist then create a new one */
6335 /* TODO: This should really be part of findGlContext */
6336 if (NULL == newContext->context) {
6338 TRACE("making new buffer\n");
6340 PUSH2(GLX_PBUFFER_WIDTH, newContext->Width);
6341 PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
6344 newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
6346 /** ****************************************
6347 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
6349 * In future releases, we may provide the calls glXCreateNewContext,
6350 * glXQueryDrawable and glXMakeContextCurrent.
6351 * so until then we have to use glXGetVisualFromFBConfig &co..
6352 ********************************************/
6355 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
6357 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
6359 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
6363 if (NULL == newContext || NULL == newContext->context) {
6364 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6366 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
6367 if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
6368 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
6371 /* Clean up the old context */
6372 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
6373 /* Set the current context of the swapchain to the new context */
6374 impSwapChain->drawable = newContext->drawable;
6375 impSwapChain->render_ctx = newContext->context;
6379 #if 1 /* Apply the stateblock to the new context
6380 FIXME: This is a bit of a hack, each context should know it's own state,
6381 the directX current directX state should then be applied to the context */
6384 IWineD3DStateBlockImpl *oldUpdateStateBlock;
6385 oldUpdateStateBlock = This->updateStateBlock;
6386 oldRecording= This->isRecordingState;
6387 This->isRecordingState = FALSE;
6388 This->updateStateBlock = This->stateBlock;
6389 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
6391 This->isRecordingState = oldRecording;
6392 This->updateStateBlock = oldUpdateStateBlock;
6397 /* clean up the current rendertargets swapchain (if it belonged to one) */
6398 if (currentSwapchain != NULL) {
6399 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
6402 /* Were done with the opengl context management, setup the rendertargets */
6404 tmp = This->renderTarget;
6405 This->renderTarget = RenderSurface;
6406 IWineD3DSurface_AddRef(This->renderTarget);
6407 IWineD3DSurface_Release(tmp);
6413 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
6414 /* Check that the container is not a swapchain member */
6416 IWineD3DSwapChain *tmpSwapChain;
6417 if (WINED3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
6418 This->renderUpsideDown = TRUE;
6420 This->renderUpsideDown = FALSE;
6421 IWineD3DSwapChain_Release(tmpSwapChain);
6423 /* Force updating the cull mode */
6424 TRACE("setting render state\n");
6425 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
6426 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
6428 /* Force updating projection matrix */
6429 This->last_was_rhw = FALSE;
6430 This->proj_valid = FALSE;
6438 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
6439 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
6444 if ( NULL != impSwapChain) {
6445 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
6453 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
6454 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
6455 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6456 /* TODO: the use of Impl is deprecated. */
6457 /* some basic validation checks */
6458 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
6460 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
6462 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
6463 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
6464 return WINED3DERR_INVALIDCALL;
6466 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
6467 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
6468 return WINED3DERR_INVALIDCALL;
6470 /* TODO: make the cursor 'real' */
6472 This->xHotSpot = XHotSpot;
6473 This->yHotSpot = YHotSpot;
6478 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
6479 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6480 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
6482 This->xScreenSpace = XScreenSpace;
6483 This->yScreenSpace = YScreenSpace;
6489 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
6490 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6491 TRACE("(%p) : visible(%d)\n", This, bShow);
6493 This->bCursorVisible = bShow;
6498 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
6499 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6500 TRACE("(%p) : state (%lu)\n", This, This->state);
6501 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
6502 switch (This->state) {
6505 case WINED3DERR_DEVICELOST:
6507 ResourceList *resourceList = This->resources;
6508 while (NULL != resourceList) {
6509 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
6510 return WINED3DERR_DEVICENOTRESET;
6511 resourceList = resourceList->next;
6513 return WINED3DERR_DEVICELOST;
6515 case WINED3DERR_DRIVERINTERNALERROR:
6516 return WINED3DERR_DRIVERINTERNALERROR;
6520 return WINED3DERR_DRIVERINTERNALERROR;
6524 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
6525 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6526 /** FIXME: Resource tracking needs to be done,
6527 * The closes we can do to this is set the priorities of all managed textures low
6528 * and then reset them.
6529 ***********************************************************/
6530 FIXME("(%p) : stub\n", This);
6534 HRESULT WINAPI IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
6535 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6536 /** FIXME: Resource trascking needs to be done.
6537 * in effect this pulls all non only default
6538 * textures out of video memory and deletes all glTextures (glDeleteTextures)
6539 * and should clear down the context and set it up according to pPresentationParameters
6540 ***********************************************************/
6541 FIXME("(%p) : stub\n", This);
6545 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
6546 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6547 /** FIXME: always true at the moment **/
6548 if(bEnableDialogs == FALSE) {
6549 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
6555 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
6556 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6557 TRACE("(%p) : pParameters %p\n", This, pParameters);
6559 *pParameters = This->createParms;
6563 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
6564 IWineD3DSwapChain *swapchain;
6565 HRESULT hrc = WINED3D_OK;
6567 TRACE("Relaying to swapchain\n");
6569 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
6570 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
6571 IWineD3DSwapChain_Release(swapchain);
6576 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
6577 IWineD3DSwapChain *swapchain;
6578 HRESULT hrc = WINED3D_OK;
6580 TRACE("Relaying to swapchain\n");
6582 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
6583 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
6584 IWineD3DSwapChain_Release(swapchain);
6590 /** ********************************************************
6591 * Notification functions
6592 ** ********************************************************/
6593 /** This function must be called in the release of a resource when ref == 0,
6594 * the contents of resource must still be correct,
6595 * any handels to other resource held by the caller must be closed
6596 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
6597 *****************************************************/
6598 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6599 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6600 ResourceList* resourceList;
6602 TRACE("(%p) : resource %p\n", This, resource);
6604 EnterCriticalSection(&resourceStoreCriticalSection);
6606 /* add a new texture to the frot of the linked list */
6607 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
6608 resourceList->resource = resource;
6610 /* Get the old head */
6611 resourceList->next = This->resources;
6613 This->resources = resourceList;
6614 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
6617 LeaveCriticalSection(&resourceStoreCriticalSection);
6622 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6623 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6624 ResourceList* resourceList = NULL;
6625 ResourceList* previousResourceList = NULL;
6627 TRACE("(%p) : resource %p\n", This, resource);
6630 EnterCriticalSection(&resourceStoreCriticalSection);
6632 resourceList = This->resources;
6634 while (resourceList != NULL) {
6635 if(resourceList->resource == resource) break;
6636 previousResourceList = resourceList;
6637 resourceList = resourceList->next;
6640 if (resourceList == NULL) {
6641 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
6643 LeaveCriticalSection(&resourceStoreCriticalSection);
6647 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
6649 /* make sure we don't leave a hole in the list */
6650 if (previousResourceList != NULL) {
6651 previousResourceList->next = resourceList->next;
6653 This->resources = resourceList->next;
6657 LeaveCriticalSection(&resourceStoreCriticalSection);
6663 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
6664 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6667 TRACE("(%p) : resource %p\n", This, resource);
6668 switch(IWineD3DResource_GetType(resource)){
6669 case WINED3DRTYPE_SURFACE:
6670 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
6672 case WINED3DRTYPE_TEXTURE:
6673 case WINED3DRTYPE_CUBETEXTURE:
6674 case WINED3DRTYPE_VOLUMETEXTURE:
6675 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
6676 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6677 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6678 This->stateBlock->textures[counter] = NULL;
6680 if (This->updateStateBlock != This->stateBlock ){
6681 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6682 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6683 This->updateStateBlock->textures[counter] = NULL;
6688 case WINED3DRTYPE_VOLUME:
6689 /* TODO: nothing really? */
6691 case WINED3DRTYPE_VERTEXBUFFER:
6692 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
6695 TRACE("Cleaning up stream pointers\n");
6697 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
6698 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
6699 FINDOUT: should changes.streamSource[StreamNumber] be set ?
6701 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6702 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
6703 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
6704 This->updateStateBlock->streamSource[streamNumber] = 0;
6705 /* Set changed flag? */
6708 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) */
6709 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
6710 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
6711 This->stateBlock->streamSource[streamNumber] = 0;
6714 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
6715 else { /* This shouldn't happen */
6716 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
6723 case WINED3DRTYPE_INDEXBUFFER:
6724 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
6725 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6726 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6727 This->updateStateBlock->pIndexData = NULL;
6730 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
6731 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6732 This->stateBlock->pIndexData = NULL;
6738 FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
6743 /* Remove the resoruce from the resourceStore */
6744 IWineD3DDeviceImpl_RemoveResource(iface, resource);
6746 TRACE("Resource released\n");
6751 /** This function is to be called by the swapchain when it is released and it's ref = 0
6752 *****************************************************/
6753 void WINAPI IWineD3DDeviceImpl_SwapChainReleased(IWineD3DDevice *iface, IWineD3DSwapChain *swapChain){
6754 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6755 SwapChainList **nextSwapchain;
6756 nextSwapchain = &This->swapchains;
6758 /* Check to see if the swapchian is being used as the render target */
6759 if (This->renderTarget != NULL) {
6760 IWineD3DSurface *swapchainBackBuffer;
6762 IWineD3DSwapChain_GetBackBuffer(swapChain, 0 ,( D3DBACKBUFFER_TYPE) 0, &swapchainBackBuffer);
6763 if (This->renderTarget == swapchainBackBuffer) {
6764 /* Don't know what to do, so warn and carry on as usual (which in this case leaves the renderterget in limbo) */
6765 FIXME("Atempting to release a swapchain that is currently beuing used as a render target, behaviour is undefined\n");
6769 /* Go through the swapchain list and try to find the swapchain being released */
6770 while(*nextSwapchain != NULL && (*nextSwapchain)->swapchain != swapChain) {
6771 nextSwapchain = &(*nextSwapchain)->next;
6774 /* Check to see if we found the swapchain */
6775 if (NULL != *nextSwapchain) {
6776 /* We found the swapchain so remove it from the list */
6777 TRACE("(%p) releasing swapchain(%p)\n", iface, swapChain);
6778 HeapFree(GetProcessHeap(), 0 , *nextSwapchain);
6779 *nextSwapchain = (*nextSwapchain)->next;
6781 /* We didn't find the swapchain on the list, this can only heppen because of a programming error in wined3d */
6782 FIXME("(%p) Attempting to release a swapchain (%p) that hasn't been stored\n", iface, swapChain);
6785 TRACE("swapchain (%p) released\n", swapChain);
6789 /**********************************************************
6790 * IWineD3DDevice VTbl follows
6791 **********************************************************/
6793 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
6795 /*** IUnknown methods ***/
6796 IWineD3DDeviceImpl_QueryInterface,
6797 IWineD3DDeviceImpl_AddRef,
6798 IWineD3DDeviceImpl_Release,
6799 /*** IWineD3DDevice methods ***/
6800 IWineD3DDeviceImpl_GetParent,
6801 /*** Creation methods**/
6802 IWineD3DDeviceImpl_CreateVertexBuffer,
6803 IWineD3DDeviceImpl_CreateIndexBuffer,
6804 IWineD3DDeviceImpl_CreateStateBlock,
6805 IWineD3DDeviceImpl_CreateSurface,
6806 IWineD3DDeviceImpl_CreateTexture,
6807 IWineD3DDeviceImpl_CreateVolumeTexture,
6808 IWineD3DDeviceImpl_CreateVolume,
6809 IWineD3DDeviceImpl_CreateCubeTexture,
6810 IWineD3DDeviceImpl_CreateQuery,
6811 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
6812 IWineD3DDeviceImpl_CreateVertexDeclaration,
6813 IWineD3DDeviceImpl_CreateVertexShader,
6814 IWineD3DDeviceImpl_CreatePixelShader,
6815 /*** Odd functions **/
6816 IWineD3DDeviceImpl_EvictManagedResources,
6817 IWineD3DDeviceImpl_GetAvailableTextureMem,
6818 IWineD3DDeviceImpl_GetBackBuffer,
6819 IWineD3DDeviceImpl_GetCreationParameters,
6820 IWineD3DDeviceImpl_GetDeviceCaps,
6821 IWineD3DDeviceImpl_GetDirect3D,
6822 IWineD3DDeviceImpl_GetDisplayMode,
6823 IWineD3DDeviceImpl_GetNumberOfSwapChains,
6824 IWineD3DDeviceImpl_GetRasterStatus,
6825 IWineD3DDeviceImpl_GetSwapChain,
6826 IWineD3DDeviceImpl_Reset,
6827 IWineD3DDeviceImpl_SetDialogBoxMode,
6828 IWineD3DDeviceImpl_SetCursorProperties,
6829 IWineD3DDeviceImpl_SetCursorPosition,
6830 IWineD3DDeviceImpl_ShowCursor,
6831 IWineD3DDeviceImpl_TestCooperativeLevel,
6832 /*** Getters and setters **/
6833 IWineD3DDeviceImpl_SetClipPlane,
6834 IWineD3DDeviceImpl_GetClipPlane,
6835 IWineD3DDeviceImpl_SetClipStatus,
6836 IWineD3DDeviceImpl_GetClipStatus,
6837 IWineD3DDeviceImpl_SetCurrentTexturePalette,
6838 IWineD3DDeviceImpl_GetCurrentTexturePalette,
6839 IWineD3DDeviceImpl_SetDepthStencilSurface,
6840 IWineD3DDeviceImpl_GetDepthStencilSurface,
6841 IWineD3DDeviceImpl_SetFVF,
6842 IWineD3DDeviceImpl_GetFVF,
6843 IWineD3DDeviceImpl_SetGammaRamp,
6844 IWineD3DDeviceImpl_GetGammaRamp,
6845 IWineD3DDeviceImpl_SetIndices,
6846 IWineD3DDeviceImpl_GetIndices,
6847 IWineD3DDeviceImpl_SetLight,
6848 IWineD3DDeviceImpl_GetLight,
6849 IWineD3DDeviceImpl_SetLightEnable,
6850 IWineD3DDeviceImpl_GetLightEnable,
6851 IWineD3DDeviceImpl_SetMaterial,
6852 IWineD3DDeviceImpl_GetMaterial,
6853 IWineD3DDeviceImpl_SetNPatchMode,
6854 IWineD3DDeviceImpl_GetNPatchMode,
6855 IWineD3DDeviceImpl_SetPaletteEntries,
6856 IWineD3DDeviceImpl_GetPaletteEntries,
6857 IWineD3DDeviceImpl_SetPixelShader,
6858 IWineD3DDeviceImpl_GetPixelShader,
6859 IWineD3DDeviceImpl_SetPixelShaderConstant,
6860 IWineD3DDeviceImpl_GetPixelShaderConstant,
6861 IWineD3DDeviceImpl_SetPixelShaderConstantB,
6862 IWineD3DDeviceImpl_GetPixelShaderConstantB,
6863 IWineD3DDeviceImpl_SetPixelShaderConstantI,
6864 IWineD3DDeviceImpl_GetPixelShaderConstantI,
6865 IWineD3DDeviceImpl_SetPixelShaderConstantF,
6866 IWineD3DDeviceImpl_GetPixelShaderConstantF,
6867 IWineD3DDeviceImpl_SetPixelShaderConstantN,
6868 IWineD3DDeviceImpl_SetRenderState,
6869 IWineD3DDeviceImpl_GetRenderState,
6870 IWineD3DDeviceImpl_SetRenderTarget,
6871 IWineD3DDeviceImpl_GetRenderTarget,
6872 IWineD3DDeviceImpl_SetSamplerState,
6873 IWineD3DDeviceImpl_GetSamplerState,
6874 IWineD3DDeviceImpl_SetScissorRect,
6875 IWineD3DDeviceImpl_GetScissorRect,
6876 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
6877 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
6878 IWineD3DDeviceImpl_SetStreamSource,
6879 IWineD3DDeviceImpl_GetStreamSource,
6880 IWineD3DDeviceImpl_SetStreamSourceFreq,
6881 IWineD3DDeviceImpl_GetStreamSourceFreq,
6882 IWineD3DDeviceImpl_SetTexture,
6883 IWineD3DDeviceImpl_GetTexture,
6884 IWineD3DDeviceImpl_SetTextureStageState,
6885 IWineD3DDeviceImpl_GetTextureStageState,
6886 IWineD3DDeviceImpl_SetTransform,
6887 IWineD3DDeviceImpl_GetTransform,
6888 IWineD3DDeviceImpl_SetVertexDeclaration,
6889 IWineD3DDeviceImpl_GetVertexDeclaration,
6890 IWineD3DDeviceImpl_SetVertexShader,
6891 IWineD3DDeviceImpl_GetVertexShader,
6892 IWineD3DDeviceImpl_SetVertexShaderConstant,
6893 IWineD3DDeviceImpl_GetVertexShaderConstant,
6894 IWineD3DDeviceImpl_SetVertexShaderConstantB,
6895 IWineD3DDeviceImpl_GetVertexShaderConstantB,
6896 IWineD3DDeviceImpl_SetVertexShaderConstantI,
6897 IWineD3DDeviceImpl_GetVertexShaderConstantI,
6898 IWineD3DDeviceImpl_SetVertexShaderConstantF,
6899 IWineD3DDeviceImpl_GetVertexShaderConstantF,
6900 IWineD3DDeviceImpl_SetVertexShaderConstantN,
6901 IWineD3DDeviceImpl_SetViewport,
6902 IWineD3DDeviceImpl_GetViewport,
6903 IWineD3DDeviceImpl_MultiplyTransform,
6904 IWineD3DDeviceImpl_ValidateDevice,
6905 IWineD3DDeviceImpl_ProcessVertices,
6906 /*** State block ***/
6907 IWineD3DDeviceImpl_BeginStateBlock,
6908 IWineD3DDeviceImpl_EndStateBlock,
6909 /*** Scene management ***/
6910 IWineD3DDeviceImpl_BeginScene,
6911 IWineD3DDeviceImpl_EndScene,
6912 IWineD3DDeviceImpl_Present,
6913 IWineD3DDeviceImpl_Clear,
6915 IWineD3DDeviceImpl_DrawPrimitive,
6916 IWineD3DDeviceImpl_DrawIndexedPrimitive,
6917 IWineD3DDeviceImpl_DrawPrimitiveUP,
6918 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
6919 IWineD3DDeviceImpl_DrawRectPatch,
6920 IWineD3DDeviceImpl_DrawTriPatch,
6921 IWineD3DDeviceImpl_DeletePatch,
6922 IWineD3DDeviceImpl_ColorFill,
6923 IWineD3DDeviceImpl_UpdateTexture,
6924 IWineD3DDeviceImpl_UpdateSurface,
6925 IWineD3DDeviceImpl_CopyRects,
6926 IWineD3DDeviceImpl_StretchRect,
6927 IWineD3DDeviceImpl_GetRenderTargetData,
6928 IWineD3DDeviceImpl_GetFrontBufferData,
6929 /*** Internal use IWineD3DDevice methods ***/
6930 IWineD3DDeviceImpl_SetupTextureStates,
6931 /*** object tracking ***/
6932 IWineD3DDeviceImpl_SwapChainReleased,
6933 IWineD3DDeviceImpl_ResourceReleased
6937 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
6938 WINED3DRS_ALPHABLENDENABLE ,
6939 WINED3DRS_ALPHAFUNC ,
6940 WINED3DRS_ALPHAREF ,
6941 WINED3DRS_ALPHATESTENABLE ,
6943 WINED3DRS_COLORWRITEENABLE ,
6944 WINED3DRS_DESTBLEND ,
6945 WINED3DRS_DITHERENABLE ,
6946 WINED3DRS_FILLMODE ,
6947 WINED3DRS_FOGDENSITY ,
6949 WINED3DRS_FOGSTART ,
6950 WINED3DRS_LASTPIXEL ,
6951 WINED3DRS_SHADEMODE ,
6952 WINED3DRS_SRCBLEND ,
6953 WINED3DRS_STENCILENABLE ,
6954 WINED3DRS_STENCILFAIL ,
6955 WINED3DRS_STENCILFUNC ,
6956 WINED3DRS_STENCILMASK ,
6957 WINED3DRS_STENCILPASS ,
6958 WINED3DRS_STENCILREF ,
6959 WINED3DRS_STENCILWRITEMASK ,
6960 WINED3DRS_STENCILZFAIL ,
6961 WINED3DRS_TEXTUREFACTOR ,
6972 WINED3DRS_ZWRITEENABLE
6975 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
6976 WINED3DTSS_ADDRESSW ,
6977 WINED3DTSS_ALPHAARG0 ,
6978 WINED3DTSS_ALPHAARG1 ,
6979 WINED3DTSS_ALPHAARG2 ,
6980 WINED3DTSS_ALPHAOP ,
6981 WINED3DTSS_BUMPENVLOFFSET ,
6982 WINED3DTSS_BUMPENVLSCALE ,
6983 WINED3DTSS_BUMPENVMAT00 ,
6984 WINED3DTSS_BUMPENVMAT01 ,
6985 WINED3DTSS_BUMPENVMAT10 ,
6986 WINED3DTSS_BUMPENVMAT11 ,
6987 WINED3DTSS_COLORARG0 ,
6988 WINED3DTSS_COLORARG1 ,
6989 WINED3DTSS_COLORARG2 ,
6990 WINED3DTSS_COLOROP ,
6991 WINED3DTSS_RESULTARG ,
6992 WINED3DTSS_TEXCOORDINDEX ,
6993 WINED3DTSS_TEXTURETRANSFORMFLAGS
6996 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
6997 WINED3DSAMP_ADDRESSU ,
6998 WINED3DSAMP_ADDRESSV ,
6999 WINED3DSAMP_ADDRESSW ,
7000 WINED3DSAMP_BORDERCOLOR ,
7001 WINED3DSAMP_MAGFILTER ,
7002 WINED3DSAMP_MINFILTER ,
7003 WINED3DSAMP_MIPFILTER ,
7004 WINED3DSAMP_MIPMAPLODBIAS ,
7005 WINED3DSAMP_MAXMIPLEVEL ,
7006 WINED3DSAMP_MAXANISOTROPY ,
7007 WINED3DSAMP_SRGBTEXTURE ,
7008 WINED3DSAMP_ELEMENTINDEX
7011 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
7013 WINED3DRS_AMBIENTMATERIALSOURCE ,
7014 WINED3DRS_CLIPPING ,
7015 WINED3DRS_CLIPPLANEENABLE ,
7016 WINED3DRS_COLORVERTEX ,
7017 WINED3DRS_DIFFUSEMATERIALSOURCE ,
7018 WINED3DRS_EMISSIVEMATERIALSOURCE ,
7019 WINED3DRS_FOGDENSITY ,
7021 WINED3DRS_FOGSTART ,
7022 WINED3DRS_FOGTABLEMODE ,
7023 WINED3DRS_FOGVERTEXMODE ,
7024 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
7025 WINED3DRS_LIGHTING ,
7026 WINED3DRS_LOCALVIEWER ,
7027 WINED3DRS_MULTISAMPLEANTIALIAS ,
7028 WINED3DRS_MULTISAMPLEMASK ,
7029 WINED3DRS_NORMALIZENORMALS ,
7030 WINED3DRS_PATCHEDGESTYLE ,
7031 WINED3DRS_POINTSCALE_A ,
7032 WINED3DRS_POINTSCALE_B ,
7033 WINED3DRS_POINTSCALE_C ,
7034 WINED3DRS_POINTSCALEENABLE ,
7035 WINED3DRS_POINTSIZE ,
7036 WINED3DRS_POINTSIZE_MAX ,
7037 WINED3DRS_POINTSIZE_MIN ,
7038 WINED3DRS_POINTSPRITEENABLE ,
7039 WINED3DRS_RANGEFOGENABLE ,
7040 WINED3DRS_SPECULARMATERIALSOURCE ,
7041 WINED3DRS_TWEENFACTOR ,
7042 WINED3DRS_VERTEXBLEND
7045 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
7046 WINED3DTSS_TEXCOORDINDEX ,
7047 WINED3DTSS_TEXTURETRANSFORMFLAGS
7050 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
7051 WINED3DSAMP_DMAPOFFSET