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 D3DERR_OUTOFVIDEOMEMORY;}
70 #define D3DCREATEOBJECTINSTANCE(object, type) { \
71 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
72 D3DMEMCHECK(object, pp##type); \
73 object->lpVtbl = &IWineD3D##type##_Vtbl; \
74 object->wineD3DDevice = This; \
75 object->parent = parent; \
77 *pp##type = (IWineD3D##type *) object; \
80 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
81 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
82 D3DMEMCHECK(object, pp##type); \
83 object->lpVtbl = &IWineD3D##type##_Vtbl; \
84 object->resource.wineD3DDevice = This; \
85 object->resource.parent = parent; \
86 object->resource.resourceType = d3dtype; \
87 object->resource.ref = 1; \
88 object->resource.pool = Pool; \
89 object->resource.format = Format; \
90 object->resource.usage = Usage; \
91 object->resource.size = _size; \
92 /* Check that we have enough video ram left */ \
93 if (Pool == D3DPOOL_DEFAULT) { \
94 if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
95 WARN("Out of 'bogus' video memory\n"); \
96 HeapFree(GetProcessHeap(), 0, object); \
98 return D3DERR_OUTOFVIDEOMEMORY; \
100 globalChangeGlRam(_size); \
102 object->resource.allocatedMemory = (0 == _size ? NULL : Pool == D3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
103 if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != D3DPOOL_DEFAULT) { \
104 FIXME("Out of memory!\n"); \
105 HeapFree(GetProcessHeap(), 0, object); \
107 return D3DERR_OUTOFVIDEOMEMORY; \
109 *pp##type = (IWineD3D##type *) object; \
110 IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
111 TRACE("(%p) : Created resource %p\n", This, object); \
114 #define D3DINITIALIZEBASETEXTURE(_basetexture) { \
115 _basetexture.levels = Levels; \
116 _basetexture.filterType = (Usage & D3DUSAGE_AUTOGENMIPMAP) ? D3DTEXF_LINEAR : D3DTEXF_NONE; \
117 _basetexture.LOD = 0; \
118 _basetexture.dirty = TRUE; \
121 /**********************************************************
122 * Global variable / Constants follow
123 **********************************************************/
124 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
126 /**********************************************************
127 * Utility functions follow
128 **********************************************************/
129 /* Convert the D3DLIGHT properties into equivalent gl lights */
130 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
133 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
134 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
136 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
137 glMatrixMode(GL_MODELVIEW);
139 glLoadMatrixf((float *)&This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
142 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
143 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
144 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
145 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
146 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
147 checkGLcall("glLightfv");
150 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
151 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
152 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
153 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
154 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
155 checkGLcall("glLightfv");
158 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
159 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
160 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
161 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
162 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
163 checkGLcall("glLightfv");
165 /* Attenuation - Are these right? guessing... */
166 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
167 checkGLcall("glLightf");
168 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
169 checkGLcall("glLightf");
171 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= 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, D3DPOOL 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, D3DRTYPE_VERTEXBUFFER, Size)
473 if (Pool == D3DPOOL_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, D3DPOOL 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,D3DRTYPE_INDEXBUFFER, Length)
495 if (Pool == D3DPOOL_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 D3DERR_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,D3DRESOURCETYPE Type, DWORD Usage, D3DPOOL Pool, D3DMULTISAMPLE_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 D3DERR_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 D3DERR_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 D3DERR_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 D3DERR_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 D3DERR_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,D3DRTYPE_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, D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DPOOL_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 D3DPOOL_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 D3DPOOL_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 D3DPOOL_MANAGED:
788 if(Usage == D3DUSAGE_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 D3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
793 if(!(Usage & D3DUSAGE_DYNAMIC) && !(Usage & D3DUSAGE_RENDERTARGET)
794 && !(Usage && D3DUSAGE_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 & D3DUSAGE_RENDERTARGET && Pool != D3DPOOL_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, D3DPOOL 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 D3DERR_INVALIDCALL;
843 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, D3DRTYPE_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);
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, D3DPOOL 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 D3DERR_INVALIDCALL;
928 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, D3DRTYPE_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, D3DPOOL 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, D3DRTYPE_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(D3DBOX));
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, D3DPOOL 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 D3DERR_INVALIDCALL;
1028 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, D3DRTYPE_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);
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 = D3DERR_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 = D3D_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 = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window" );
1197 hDc = GetDC(object->win_handle);
1198 object->display = get_display(hDc);
1199 ReleaseDC(object->win_handle, hDc);
1200 TRACE("Using a display of %p %p\n", object->display, hDc);
1202 if (NULL == object->display || NULL == hDc) {
1203 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1204 return D3DERR_NOTAVAILABLE;
1207 if (object->win == 0) {
1208 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1209 return D3DERR_NOTAVAILABLE;
1212 * Create an opengl context for the display visual
1213 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1214 * use different properties after that point in time. FIXME: How to handle when requested format
1215 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1216 * it chooses is identical to the one already being used!
1217 **********************************/
1219 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1222 /* Create a new context for this swapchain */
1223 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1224 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1225 (or the best possible if none is requested) */
1226 TRACE("Found x visual ID : %ld\n", template.visualid);
1228 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1229 if (NULL == object->visInfo) {
1230 ERR("cannot really get XVisual\n");
1232 return D3DERR_NOTAVAILABLE;
1235 /* Write out some debug info about the visual/s */
1236 TRACE("Using x visual ID : %ld\n", template.visualid);
1237 TRACE(" visual info: %p\n", object->visInfo);
1238 TRACE(" num items : %d\n", num);
1239 for (n = 0;n < num; n++) {
1240 TRACE("=====item=====: %d\n", n + 1);
1241 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1242 TRACE(" screen : %d\n", object->visInfo[n].screen);
1243 TRACE(" depth : %u\n", object->visInfo[n].depth);
1244 TRACE(" class : %d\n", object->visInfo[n].class);
1245 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1246 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1247 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1248 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1249 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1250 /* log some extra glx info */
1251 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1252 TRACE(" gl_aux_buffers : %d\n", value);
1253 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1254 TRACE(" gl_buffer_size : %d\n", value);
1255 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1256 TRACE(" gl_red_size : %d\n", value);
1257 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1258 TRACE(" gl_green_size : %d\n", value);
1259 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1260 TRACE(" gl_blue_size : %d\n", value);
1261 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1262 TRACE(" gl_alpha_size : %d\n", value);
1263 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1264 TRACE(" gl_depth_size : %d\n", value);
1265 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1266 TRACE(" gl_stencil_size : %d\n", value);
1268 /* Now choose a simila visual ID*/
1270 #ifdef USE_CONTEXT_MANAGER
1272 /** TODO: use a context mamager **/
1276 IWineD3DSwapChain *implSwapChain;
1277 if (D3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1278 /* The first time around we create the context that is shared with all other swapchains and render targets */
1279 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1280 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1283 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1284 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1285 /* and create a new context with the implicit swapchains context as the shared context */
1286 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1287 IWineD3DSwapChain_Release(implSwapChain);
1292 XFree(object->visInfo);
1293 object->visInfo = NULL;
1295 if (NULL == object->glCtx) {
1296 ERR("cannot create glxContext\n");
1298 return D3DERR_NOTAVAILABLE;
1302 if (object->glCtx == NULL) {
1303 ERR("Error in context creation !\n");
1304 return D3DERR_INVALIDCALL;
1306 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1307 object->win_handle, object->glCtx, object->win, object->visInfo);
1310 /*********************
1311 * Windowed / Fullscreen
1312 *******************/
1315 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1316 * so we should really check to see if there is a fullscreen swapchain already
1317 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1318 **************************************/
1320 if (!*(pPresentationParameters->Windowed)) {
1326 /* Get info on the current display setup */
1327 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1328 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1331 /* Change the display settings */
1332 memset(&devmode, 0, sizeof(DEVMODEW));
1333 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1334 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1335 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1336 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1337 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1338 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1340 /* Make popup window */
1341 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1342 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1343 *(pPresentationParameters->BackBufferWidth),
1344 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1350 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1351 * then the corresponding dimension of the client area of the hDeviceWindow
1352 * (or the focus window, if hDeviceWindow is NULL) is taken.
1353 **********************/
1355 if (*(pPresentationParameters->Windowed) &&
1356 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1357 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1360 GetClientRect(object->win_handle, &Rect);
1362 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1363 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1364 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1366 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1367 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1368 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1372 /*********************
1373 * finish off parameter initialization
1374 *******************/
1376 /* Put the correct figures in the presentation parameters */
1377 TRACE("Coppying accross presentaion paraneters\n");
1378 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1379 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1380 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1381 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1382 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1383 object->presentParms.MultiSampleQuality = NULL == pPresentationParameters->MultiSampleQuality ? 0 : *(pPresentationParameters->MultiSampleQuality);
1384 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1385 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1386 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1387 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1388 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1389 object->presentParms.Flags = *(pPresentationParameters->Flags);
1390 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1391 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1394 /*********************
1395 * Create the back, front and stencil buffers
1396 *******************/
1397 TRACE("calling rendertarget CB\n");
1398 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1399 object->presentParms.BackBufferWidth,
1400 object->presentParms.BackBufferHeight,
1401 object->presentParms.BackBufferFormat,
1402 object->presentParms.MultiSampleType,
1403 object->presentParms.MultiSampleQuality,
1404 TRUE /* Lockable */,
1405 &object->frontBuffer,
1406 NULL /* pShared (always null)*/);
1407 if (object->frontBuffer != NULL)
1408 IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
1409 TRACE("calling rendertarget CB\n");
1410 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1411 object->presentParms.BackBufferWidth,
1412 object->presentParms.BackBufferHeight,
1413 object->presentParms.BackBufferFormat,
1414 object->presentParms.MultiSampleType,
1415 object->presentParms.MultiSampleQuality,
1416 TRUE /* Lockable */,
1417 &object->backBuffer,
1418 NULL /* pShared (always null)*/);
1419 if (object->backBuffer != NULL)
1420 IWineD3DSurface_SetContainer(object->backBuffer, (IWineD3DBase *)object);
1422 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1423 if (pPresentationParameters->EnableAutoDepthStencil) {
1424 TRACE("Creating depth stencil buffer\n");
1425 if (This->depthStencilBuffer == NULL ) {
1426 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1427 object->presentParms.BackBufferWidth,
1428 object->presentParms.BackBufferHeight,
1429 object->presentParms.AutoDepthStencilFormat,
1430 object->presentParms.MultiSampleType,
1431 object->presentParms.MultiSampleQuality,
1432 FALSE /* FIXME: Discard */,
1433 &This->depthStencilBuffer,
1434 NULL /* pShared (always null)*/ );
1435 if (This->depthStencilBuffer != NULL)
1436 IWineD3DSurface_SetContainer(This->depthStencilBuffer, (IWineD3DBase *)iface);
1439 /** TODO: A check on width, height and multisample types
1440 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1441 ****************************/
1442 object->wantsDepthStencilBuffer = TRUE;
1444 object->wantsDepthStencilBuffer = FALSE;
1447 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1450 /*********************
1451 * init the default renderTarget management
1452 *******************/
1453 object->drawable = object->win;
1454 object->render_ctx = object->glCtx;
1457 /*********************
1458 * Setup some defaults and clear down the buffers
1459 *******************/
1461 /** save current context and drawable **/
1462 oldContext = glXGetCurrentContext();
1463 oldDrawable = glXGetCurrentDrawable();
1465 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1466 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1467 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1469 checkGLcall("glXMakeCurrent");
1471 TRACE("Setting up the screen\n");
1472 /* Clear the screen */
1473 glClearColor(1.0, 0.0, 0.0, 0.0);
1474 checkGLcall("glClearColor");
1477 glClearStencil(0xffff);
1479 checkGLcall("glClear");
1481 glColor3f(1.0, 1.0, 1.0);
1482 checkGLcall("glColor3f");
1484 glEnable(GL_LIGHTING);
1485 checkGLcall("glEnable");
1487 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1488 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1490 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1491 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1493 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1494 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1496 /* switch back to the original context (if there was one)*/
1497 if (This->swapchains != NULL) {
1498 /** TODO: restore the context and drawable **/
1499 glXMakeCurrent(object->display, oldDrawable, oldContext);
1504 { /* Finally add the swapchain to the end of the devices' swapchain list */
1505 SwapChainList **nextSwapchain;
1506 nextSwapchain = &This->swapchains;
1507 while (*nextSwapchain != NULL) {
1508 nextSwapchain = &((*nextSwapchain)->next);
1510 (*nextSwapchain) = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->swapchains));
1511 (*nextSwapchain)->swapchain = (IWineD3DSwapChain *)object;
1513 TRACE("Set swapchain to %p\n", object);
1514 } else { /* something went wrong so clean up */
1515 IUnknown* bufferParent;
1516 if (object->frontBuffer) {
1518 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1519 IUnknown_Release(bufferParent); /* once for the get parent */
1520 if (IUnknown_Release(bufferParent) > 0) {
1521 FIXME("(%p) Something's still holding the front buffer\n",This);
1524 if (object->backBuffer) {
1525 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1526 IUnknown_Release(bufferParent); /* once for the get parent */
1527 if (IUnknown_Release(bufferParent) > 0) {
1528 FIXME("(%p) Something's still holding the back buffer\n",This);
1531 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1532 /* Clean up the context */
1533 /* check that we are the current context first (we shouldn't be though!) */
1534 if (object->glCtx != 0) {
1535 if(glXGetCurrentContext() == object->glCtx) {
1536 glXMakeCurrent(object->display, None, NULL);
1538 glXDestroyContext(object->display, object->glCtx);
1540 HeapFree(GetProcessHeap(), 0, object);
1547 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1548 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1549 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1550 unsigned int numberOfSwapChains = 0;
1551 SwapChainList *swapchain;
1553 swapchain = This->swapchains;
1554 /* itterate through the list to get a count */
1555 while (swapchain != NULL) {
1556 swapchain = swapchain->next;
1557 numberOfSwapChains++;
1560 TRACE("(%p) returning %d\n", This, numberOfSwapChains);
1561 return numberOfSwapChains;
1564 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1565 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1566 SwapChainList *swapchain;
1568 HRESULT hr = D3DERR_INVALIDCALL;
1569 swapchain = This->swapchains;
1570 TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1573 TRACE("(%p) Finding swapchain %d\n", This, iSwapChain);
1574 while (i > 0 && swapchain != NULL) {
1575 swapchain = swapchain->next;
1580 FIXME("(%p) Unable to find swapchain %d\n", This, iSwapChain);
1582 } else if (swapchain != NULL) {
1583 /** TODO: move off to a linkesList implementation **/
1584 *pSwapChain = swapchain->swapchain;
1585 IWineD3DSwapChain_AddRef(*pSwapChain);
1589 TRACE("(%p) returning %p\n", This, *pSwapChain);
1593 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
1594 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1596 FIXME("(%p) : Stub\n",This);
1602 * Vertex Declaration
1604 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1605 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1606 IWineD3DVertexDeclarationImpl *object = NULL;
1607 HRESULT hr = D3D_OK;
1608 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1609 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1612 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1617 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1618 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pDeclaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1619 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1620 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1621 HRESULT hr = D3D_OK;
1622 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1624 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1625 hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1628 FIXME("(%p) : Failed to set the function, returning D3DERR_INVALIDCALL\n", iface);
1629 IWineD3DVertexShader_Release(*ppVertexShader);
1630 return D3DERR_INVALIDCALL;
1633 #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. */
1634 if(Usage == WINED3DUSAGE_SOFTWAREVERTEXPROCESSING) {
1643 /* If a vertex declaration has been passed, save it to the vertex shader, this affects d3d8 only. */
1644 if (pDeclaration != NULL) {
1645 IWineD3DVertexDeclaration *vertexDeclaration;
1646 hr = IWineD3DDevice_CreateVertexDeclaration(iface, pDeclaration, &vertexDeclaration ,NULL);
1648 TRACE("(%p) : Setting vertex declaration to %p\n", This, vertexDeclaration);
1649 object->vertexDeclaration = vertexDeclaration;
1651 FIXME("(%p) : Failed to set the declaration, returning D3DERR_INVALIDCALL\n", iface);
1652 IWineD3DVertexShader_Release(*ppVertexShader);
1653 return D3DERR_INVALIDCALL;
1660 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
1661 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1662 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1663 HRESULT hr = D3D_OK;
1665 D3DCREATEOBJECTINSTANCE(object, PixelShader)
1666 hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
1668 TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
1670 WARN("(%p) : Failed to create pixel shader\n", This);
1676 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
1677 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1678 *ppD3D= This->wineD3D;
1679 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1680 IWineD3D_AddRef(*ppD3D);
1684 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1685 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1686 * Into the video ram as possible and seeing how many fit
1687 * you can also get the correct initial value from via X and ATI's driver
1688 *******************/
1689 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1690 static BOOL showfixmes = TRUE;
1692 FIXME("(%p) : stub, emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1693 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1696 TRACE("(%p) : emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1697 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1698 /* videomemory is simulated videomemory + AGP memory left */
1699 return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1707 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1708 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1709 HRESULT hr = D3D_OK;
1711 /* Update the current state block */
1712 This->updateStateBlock->fvf = fvf;
1713 This->updateStateBlock->changed.fvf = TRUE;
1714 This->updateStateBlock->set.fvf = TRUE;
1716 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1719 /* clear down the vertex declaration
1720 NOTE: Axis and Allies doesn't work properly otherwise
1721 (may be a stateblock problem though!)
1723 hr = IWineD3DDevice_SetVertexDeclaration(iface, NULL);
1730 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1731 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1732 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1733 *pfvf = This->stateBlock->fvf;
1738 * Get / Set Stream Source
1740 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1741 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1742 IWineD3DVertexBuffer *oldSrc;
1744 /**TODO: instance and index data, see
1745 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1747 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
1750 /* D3d9 only, but shouldn't hurt d3d8 */
1753 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1755 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1756 FIXME("stream index data not supported\n");
1758 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1759 FIXME("stream instance data not supported\n");
1763 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1765 if (StreamNumber >= MAX_STREAMS) {
1766 WARN("Stream out of range %d\n", StreamNumber);
1767 return D3DERR_INVALIDCALL;
1770 oldSrc = This->stateBlock->streamSource[StreamNumber];
1771 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1773 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
1774 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
1775 This->updateStateBlock->streamStride[StreamNumber] = Stride;
1776 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
1777 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
1778 This->updateStateBlock->streamFlags[StreamNumber] = streamFlags;
1780 /* Handle recording of state blocks */
1781 if (This->isRecordingState) {
1782 TRACE("Recording... not performing anything\n");
1786 /* Not recording... */
1787 /* Need to do a getParent and pass the reffs up */
1788 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
1789 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
1790 so for now, just count internally */
1791 if (pStreamData != NULL) {
1792 IWineD3DVertexBuffer_AddRef(pStreamData);
1794 if (oldSrc != NULL) {
1795 IWineD3DVertexBuffer_Release(oldSrc);
1801 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
1802 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1805 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
1806 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
1809 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1811 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1812 FIXME("stream index data not supported\n");
1814 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1815 FIXME("stream instance data not supported\n");
1819 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1821 if (StreamNumber >= MAX_STREAMS) {
1822 WARN("Stream out of range %d\n", StreamNumber);
1823 return D3DERR_INVALIDCALL;
1825 *pStream = This->stateBlock->streamSource[StreamNumber];
1826 *pStride = This->stateBlock->streamStride[StreamNumber];
1827 *pOffset = This->stateBlock->streamOffset[StreamNumber];
1829 if (*pStream == NULL) {
1830 FIXME("Attempting to get an empty stream %d, returning D3DERR_INVALIDCALL\n", StreamNumber);
1831 return D3DERR_INVALIDCALL;
1834 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
1838 /*Should be quite easy, just an extension of vertexdata
1840 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1842 The divider is a bit odd though
1844 VertexOffset = StartVertex / Divider * StreamStride +
1845 VertexIndex / Divider * StreamStride + StreamOffset
1848 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
1849 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1851 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
1852 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (D3DSTREAMSOURCE_INSTANCEDATA | D3DSTREAMSOURCE_INDEXEDDATA );
1854 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
1855 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
1856 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
1858 if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
1859 FIXME("Stream indexing not fully supported\n");
1865 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
1866 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1868 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
1869 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
1871 TRACE("(%p) : returning %d\n", This, *Divider);
1877 * Get / Set & Multiply Transform
1879 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1880 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1882 /* Most of this routine, comments included copied from ddraw tree initially: */
1883 TRACE("(%p) : Transform State=%d\n", This, d3dts);
1885 /* Handle recording of state blocks */
1886 if (This->isRecordingState) {
1887 TRACE("Recording... not performing anything\n");
1888 This->updateStateBlock->changed.transform[d3dts] = TRUE;
1889 This->updateStateBlock->set.transform[d3dts] = TRUE;
1890 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1895 * If the new matrix is the same as the current one,
1896 * we cut off any further processing. this seems to be a reasonable
1897 * optimization because as was noticed, some apps (warcraft3 for example)
1898 * tend towards setting the same matrix repeatedly for some reason.
1900 * From here on we assume that the new matrix is different, wherever it matters.
1902 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1903 TRACE("The app is setting the same matrix over again\n");
1906 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1910 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1911 where ViewMat = Camera space, WorldMat = world space.
1913 In OpenGL, camera and world space is combined into GL_MODELVIEW
1914 matrix. The Projection matrix stay projection matrix.
1917 /* Capture the times we can just ignore the change for now */
1918 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1919 This->modelview_valid = FALSE;
1922 } else if (d3dts == D3DTS_PROJECTION) {
1923 This->proj_valid = FALSE;
1926 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1927 /* Indexed Vertex Blending Matrices 256 -> 511 */
1928 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1929 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1933 /* Now we really are going to have to change a matrix */
1936 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1937 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
1938 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1941 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1942 * NOTE: We have to reset the positions even if the light/plane is not currently
1943 * enabled, since the call to enable it will not reset the position.
1944 * NOTE2: Apparently texture transforms do NOT need reapplying
1947 PLIGHTINFOEL *lightChain = NULL;
1948 This->modelview_valid = FALSE;
1949 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
1951 glMatrixMode(GL_MODELVIEW);
1952 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1954 glLoadMatrixf((float *)lpmatrix);
1955 checkGLcall("glLoadMatrixf(...)");
1958 lightChain = This->stateBlock->lights;
1959 while (lightChain && lightChain->glIndex != -1) {
1960 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1961 checkGLcall("glLightfv posn");
1962 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1963 checkGLcall("glLightfv dirn");
1964 lightChain = lightChain->next;
1967 /* Reset Clipping Planes if clipping is enabled */
1968 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1969 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1970 checkGLcall("glClipPlane");
1974 } else { /* What was requested!?? */
1975 WARN("invalid matrix specified: %i\n", d3dts);
1978 /* Release lock, all done */
1983 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1984 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1985 TRACE("(%p) : for Transform State %d\n", This, State);
1986 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1990 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1991 D3DMATRIX *mat = NULL;
1994 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1995 * below means it will be recorded in a state block change, but it
1996 * works regardless where it is recorded.
1997 * If this is found to be wrong, change to StateBlock.
1999 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2000 TRACE("(%p) : For state %u\n", This, State);
2002 if (State < HIGHEST_TRANSFORMSTATE)
2004 mat = &This->updateStateBlock->transforms[State];
2006 FIXME("Unhandled transform state!!\n");
2009 /* Copied from ddraw code: */
2010 temp.u.s._11 = (mat->u.s._11 * pMatrix->u.s._11) + (mat->u.s._21 * pMatrix->u.s._12) +
2011 (mat->u.s._31 * pMatrix->u.s._13) + (mat->u.s._41 * pMatrix->u.s._14);
2012 temp.u.s._21 = (mat->u.s._11 * pMatrix->u.s._21) + (mat->u.s._21 * pMatrix->u.s._22) +
2013 (mat->u.s._31 * pMatrix->u.s._23) + (mat->u.s._41 * pMatrix->u.s._24);
2014 temp.u.s._31 = (mat->u.s._11 * pMatrix->u.s._31) + (mat->u.s._21 * pMatrix->u.s._32) +
2015 (mat->u.s._31 * pMatrix->u.s._33) + (mat->u.s._41 * pMatrix->u.s._34);
2016 temp.u.s._41 = (mat->u.s._11 * pMatrix->u.s._41) + (mat->u.s._21 * pMatrix->u.s._42) +
2017 (mat->u.s._31 * pMatrix->u.s._43) + (mat->u.s._41 * pMatrix->u.s._44);
2019 temp.u.s._12 = (mat->u.s._12 * pMatrix->u.s._11) + (mat->u.s._22 * pMatrix->u.s._12) +
2020 (mat->u.s._32 * pMatrix->u.s._13) + (mat->u.s._42 * pMatrix->u.s._14);
2021 temp.u.s._22 = (mat->u.s._12 * pMatrix->u.s._21) + (mat->u.s._22 * pMatrix->u.s._22) +
2022 (mat->u.s._32 * pMatrix->u.s._23) + (mat->u.s._42 * pMatrix->u.s._24);
2023 temp.u.s._32 = (mat->u.s._12 * pMatrix->u.s._31) + (mat->u.s._22 * pMatrix->u.s._32) +
2024 (mat->u.s._32 * pMatrix->u.s._33) + (mat->u.s._42 * pMatrix->u.s._34);
2025 temp.u.s._42 = (mat->u.s._12 * pMatrix->u.s._41) + (mat->u.s._22 * pMatrix->u.s._42) +
2026 (mat->u.s._32 * pMatrix->u.s._43) + (mat->u.s._42 * pMatrix->u.s._44);
2028 temp.u.s._13 = (mat->u.s._13 * pMatrix->u.s._11) + (mat->u.s._23 * pMatrix->u.s._12) +
2029 (mat->u.s._33 * pMatrix->u.s._13) + (mat->u.s._43 * pMatrix->u.s._14);
2030 temp.u.s._23 = (mat->u.s._13 * pMatrix->u.s._21) + (mat->u.s._23 * pMatrix->u.s._22) +
2031 (mat->u.s._33 * pMatrix->u.s._23) + (mat->u.s._43 * pMatrix->u.s._24);
2032 temp.u.s._33 = (mat->u.s._13 * pMatrix->u.s._31) + (mat->u.s._23 * pMatrix->u.s._32) +
2033 (mat->u.s._33 * pMatrix->u.s._33) + (mat->u.s._43 * pMatrix->u.s._34);
2034 temp.u.s._43 = (mat->u.s._13 * pMatrix->u.s._41) + (mat->u.s._23 * pMatrix->u.s._42) +
2035 (mat->u.s._33 * pMatrix->u.s._43) + (mat->u.s._43 * pMatrix->u.s._44);
2037 temp.u.s._14 = (mat->u.s._14 * pMatrix->u.s._11) + (mat->u.s._24 * pMatrix->u.s._12) +
2038 (mat->u.s._34 * pMatrix->u.s._13) + (mat->u.s._44 * pMatrix->u.s._14);
2039 temp.u.s._24 = (mat->u.s._14 * pMatrix->u.s._21) + (mat->u.s._24 * pMatrix->u.s._22) +
2040 (mat->u.s._34 * pMatrix->u.s._23) + (mat->u.s._44 * pMatrix->u.s._24);
2041 temp.u.s._34 = (mat->u.s._14 * pMatrix->u.s._31) + (mat->u.s._24 * pMatrix->u.s._32) +
2042 (mat->u.s._34 * pMatrix->u.s._33) + (mat->u.s._44 * pMatrix->u.s._34);
2043 temp.u.s._44 = (mat->u.s._14 * pMatrix->u.s._41) + (mat->u.s._24 * pMatrix->u.s._42) +
2044 (mat->u.s._34 * pMatrix->u.s._43) + (mat->u.s._44 * pMatrix->u.s._44);
2046 /* Apply change via set transform - will reapply to eg. lights this way */
2047 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2052 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
2054 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2055 you can reference any indexes you want as long as that number max are enabled at any
2056 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2057 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2058 but when recording, just build a chain pretty much of commands to be replayed. */
2060 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2062 PLIGHTINFOEL *object, *temp;
2064 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2065 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2067 /* If recording state block, just add to end of lights chain */
2068 if (This->isRecordingState) {
2069 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2070 if (NULL == object) {
2071 return D3DERR_OUTOFVIDEOMEMORY;
2073 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2074 object->OriginalIndex = Index;
2075 object->glIndex = -1;
2076 object->changed = TRUE;
2078 /* Add to the END of the chain of lights changes to be replayed */
2079 if (This->updateStateBlock->lights == NULL) {
2080 This->updateStateBlock->lights = object;
2082 temp = This->updateStateBlock->lights;
2083 while (temp->next != NULL) temp=temp->next;
2084 temp->next = object;
2086 TRACE("Recording... not performing anything more\n");
2090 /* Ok, not recording any longer so do real work */
2091 object = This->stateBlock->lights;
2092 while (object != NULL && object->OriginalIndex != Index) object = object->next;
2094 /* If we didn't find it in the list of lights, time to add it */
2095 if (object == NULL) {
2096 PLIGHTINFOEL *insertAt,*prevPos;
2098 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2099 if (NULL == object) {
2100 return D3DERR_OUTOFVIDEOMEMORY;
2102 object->OriginalIndex = Index;
2103 object->glIndex = -1;
2105 /* Add it to the front of list with the idea that lights will be changed as needed
2106 BUT after any lights currently assigned GL indexes */
2107 insertAt = This->stateBlock->lights;
2109 while (insertAt != NULL && insertAt->glIndex != -1) {
2111 insertAt = insertAt->next;
2114 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2115 This->stateBlock->lights = object;
2116 } else if (insertAt == NULL) { /* End of list */
2117 prevPos->next = object;
2118 object->prev = prevPos;
2119 } else { /* Middle of chain */
2120 if (prevPos == NULL) {
2121 This->stateBlock->lights = object;
2123 prevPos->next = object;
2125 object->prev = prevPos;
2126 object->next = insertAt;
2127 insertAt->prev = object;
2131 /* Initialize the object */
2132 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,
2133 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2134 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2135 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2136 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2137 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2138 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2140 /* Save away the information */
2141 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2143 switch (pLight->Type) {
2144 case D3DLIGHT_POINT:
2146 object->lightPosn[0] = pLight->Position.x;
2147 object->lightPosn[1] = pLight->Position.y;
2148 object->lightPosn[2] = pLight->Position.z;
2149 object->lightPosn[3] = 1.0f;
2150 object->cutoff = 180.0f;
2154 case D3DLIGHT_DIRECTIONAL:
2156 object->lightPosn[0] = -pLight->Direction.x;
2157 object->lightPosn[1] = -pLight->Direction.y;
2158 object->lightPosn[2] = -pLight->Direction.z;
2159 object->lightPosn[3] = 0.0;
2160 object->exponent = 0.0f;
2161 object->cutoff = 180.0f;
2166 object->lightPosn[0] = pLight->Position.x;
2167 object->lightPosn[1] = pLight->Position.y;
2168 object->lightPosn[2] = pLight->Position.z;
2169 object->lightPosn[3] = 1.0;
2172 object->lightDirn[0] = pLight->Direction.x;
2173 object->lightDirn[1] = pLight->Direction.y;
2174 object->lightDirn[2] = pLight->Direction.z;
2175 object->lightDirn[3] = 1.0;
2178 * opengl-ish and d3d-ish spot lights use too different models for the
2179 * light "intensity" as a function of the angle towards the main light direction,
2180 * so we only can approximate very roughly.
2181 * however spot lights are rather rarely used in games (if ever used at all).
2182 * furthermore if still used, probably nobody pays attention to such details.
2184 if (pLight->Falloff == 0) {
2187 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2189 if (rho < 0.0001) rho = 0.0001f;
2190 object->exponent = -0.3/log(cos(rho/2));
2191 object->cutoff = pLight->Phi*90/M_PI;
2197 FIXME("Unrecognized light type %d\n", pLight->Type);
2200 /* Update the live definitions if the light is currently assigned a glIndex */
2201 if (object->glIndex != -1) {
2202 setup_light(iface, object->glIndex, object);
2207 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2208 PLIGHTINFOEL *lightInfo = NULL;
2209 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2210 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2212 /* Locate the light in the live lights */
2213 lightInfo = This->stateBlock->lights;
2214 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2216 if (lightInfo == NULL) {
2217 TRACE("Light information requested but light not defined\n");
2218 return D3DERR_INVALIDCALL;
2221 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
2226 * Get / Set Light Enable
2227 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2229 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2230 PLIGHTINFOEL *lightInfo = NULL;
2231 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2232 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2234 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2235 if (This->isRecordingState) {
2236 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2237 if (NULL == lightInfo) {
2238 return D3DERR_OUTOFVIDEOMEMORY;
2240 lightInfo->OriginalIndex = Index;
2241 lightInfo->glIndex = -1;
2242 lightInfo->enabledChanged = TRUE;
2244 /* Add to the END of the chain of lights changes to be replayed */
2245 if (This->updateStateBlock->lights == NULL) {
2246 This->updateStateBlock->lights = lightInfo;
2248 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2249 while (temp->next != NULL) temp=temp->next;
2250 temp->next = lightInfo;
2252 TRACE("Recording... not performing anything more\n");
2256 /* Not recording... So, locate the light in the live lights */
2257 lightInfo = This->stateBlock->lights;
2258 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2260 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2261 if (lightInfo == NULL) {
2262 D3DLIGHT9 lightParms;
2263 /* Warning - untested code :-) Prob safe to change fixme to a trace but
2264 wait until someone confirms it seems to work! */
2265 TRACE("Light enabled requested but light not defined, so defining one!\n");
2266 lightParms.Type = D3DLIGHT_DIRECTIONAL;
2267 lightParms.Diffuse.r = 1.0;
2268 lightParms.Diffuse.g = 1.0;
2269 lightParms.Diffuse.b = 1.0;
2270 lightParms.Diffuse.a = 0.0;
2271 lightParms.Specular.r = 0.0;
2272 lightParms.Specular.g = 0.0;
2273 lightParms.Specular.b = 0.0;
2274 lightParms.Specular.a = 0.0;
2275 lightParms.Ambient.r = 0.0;
2276 lightParms.Ambient.g = 0.0;
2277 lightParms.Ambient.b = 0.0;
2278 lightParms.Ambient.a = 0.0;
2279 lightParms.Position.x = 0.0;
2280 lightParms.Position.y = 0.0;
2281 lightParms.Position.z = 0.0;
2282 lightParms.Direction.x = 0.0;
2283 lightParms.Direction.y = 0.0;
2284 lightParms.Direction.z = 1.0;
2285 lightParms.Range = 0.0;
2286 lightParms.Falloff = 0.0;
2287 lightParms.Attenuation0 = 0.0;
2288 lightParms.Attenuation1 = 0.0;
2289 lightParms.Attenuation2 = 0.0;
2290 lightParms.Theta = 0.0;
2291 lightParms.Phi = 0.0;
2292 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
2294 /* Search for it again! Should be fairly quick as near head of list */
2295 lightInfo = This->stateBlock->lights;
2296 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2297 if (lightInfo == NULL) {
2298 FIXME("Adding default lights has failed dismally\n");
2299 return D3DERR_INVALIDCALL;
2303 /* OK, we now have a light... */
2304 if (Enable == FALSE) {
2306 /* If we are disabling it, check it was enabled, and
2307 still only do something if it has assigned a glIndex (which it should have!) */
2308 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2309 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2311 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2312 checkGLcall("glDisable GL_LIGHT0+Index");
2315 TRACE("Nothing to do as light was not enabled\n");
2317 lightInfo->lightEnabled = FALSE;
2320 /* We are enabling it. If it is enabled, it's really simple */
2321 if (lightInfo->lightEnabled) {
2323 TRACE("Nothing to do as light was enabled\n");
2325 /* If it already has a glIndex, it's still simple */
2326 } else if (lightInfo->glIndex != -1) {
2327 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2328 lightInfo->lightEnabled = TRUE;
2330 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2331 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2334 /* Otherwise got to find space - lights are ordered gl indexes first */
2336 PLIGHTINFOEL *bsf = NULL;
2337 PLIGHTINFOEL *pos = This->stateBlock->lights;
2338 PLIGHTINFOEL *prev = NULL;
2342 /* Try to minimize changes as much as possible */
2343 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2345 /* Try to remember which index can be replaced if necessary */
2346 if (bsf==NULL && pos->lightEnabled == FALSE) {
2347 /* Found a light we can replace, save as best replacement */
2351 /* Step to next space */
2357 /* If we have too many active lights, fail the call */
2358 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2359 FIXME("Program requests too many concurrent lights\n");
2360 return D3DERR_INVALIDCALL;
2362 /* If we have allocated all lights, but not all are enabled,
2363 reuse one which is not enabled */
2364 } else if (Index == This->maxConcurrentLights) {
2365 /* use bsf - Simply swap the new light and the BSF one */
2366 PLIGHTINFOEL *bsfNext = bsf->next;
2367 PLIGHTINFOEL *bsfPrev = bsf->prev;
2370 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2371 if (bsf->prev != NULL) {
2372 bsf->prev->next = lightInfo;
2374 This->stateBlock->lights = lightInfo;
2377 /* If not side by side, lots of chains to update */
2378 if (bsf->next != lightInfo) {
2379 lightInfo->prev->next = bsf;
2380 bsf->next->prev = lightInfo;
2381 bsf->next = lightInfo->next;
2382 bsf->prev = lightInfo->prev;
2383 lightInfo->next = bsfNext;
2384 lightInfo->prev = bsfPrev;
2388 bsf->prev = lightInfo;
2389 bsf->next = lightInfo->next;
2390 lightInfo->next = bsf;
2391 lightInfo->prev = bsfPrev;
2396 glIndex = bsf->glIndex;
2398 lightInfo->glIndex = glIndex;
2399 lightInfo->lightEnabled = TRUE;
2401 /* Finally set up the light in gl itself */
2402 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2404 setup_light(iface, glIndex, lightInfo);
2405 glEnable(GL_LIGHT0 + glIndex);
2406 checkGLcall("glEnable GL_LIGHT0 new setup");
2409 /* If we reached the end of the allocated lights, with space in the
2410 gl lights, setup a new light */
2411 } else if (pos->glIndex == -1) {
2413 /* We reached the end of the allocated gl lights, so already
2414 know the index of the next one! */
2416 lightInfo->glIndex = glIndex;
2417 lightInfo->lightEnabled = TRUE;
2419 /* In an ideal world, it's already in the right place */
2420 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2421 /* No need to move it */
2423 /* Remove this light from the list */
2424 lightInfo->prev->next = lightInfo->next;
2425 if (lightInfo->next != NULL) {
2426 lightInfo->next->prev = lightInfo->prev;
2429 /* Add in at appropriate place (inbetween prev and pos) */
2430 lightInfo->prev = prev;
2431 lightInfo->next = pos;
2433 This->stateBlock->lights = lightInfo;
2435 prev->next = lightInfo;
2438 pos->prev = lightInfo;
2442 /* Finally set up the light in gl itself */
2443 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2445 setup_light(iface, glIndex, lightInfo);
2446 glEnable(GL_LIGHT0 + glIndex);
2447 checkGLcall("glEnable GL_LIGHT0 new setup");
2456 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2458 PLIGHTINFOEL *lightInfo = NULL;
2459 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2460 TRACE("(%p) : for idx(%ld)\n", This, Index);
2462 /* Locate the light in the live lights */
2463 lightInfo = This->stateBlock->lights;
2464 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2466 if (lightInfo == NULL) {
2467 TRACE("Light enabled state requested but light not defined\n");
2468 return D3DERR_INVALIDCALL;
2470 *pEnable = lightInfo->lightEnabled;
2475 * Get / Set Clip Planes
2477 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2478 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2479 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2481 /* Validate Index */
2482 if (Index >= GL_LIMITS(clipplanes)) {
2483 TRACE("Application has requested clipplane this device doesn't support\n");
2484 return D3DERR_INVALIDCALL;
2487 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2488 This->updateStateBlock->set.clipplane[Index] = TRUE;
2489 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2490 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2491 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2492 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2494 /* Handle recording of state blocks */
2495 if (This->isRecordingState) {
2496 TRACE("Recording... not performing anything\n");
2504 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2505 glMatrixMode(GL_MODELVIEW);
2507 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2509 TRACE("Clipplane [%f,%f,%f,%f]\n",
2510 This->updateStateBlock->clipplane[Index][0],
2511 This->updateStateBlock->clipplane[Index][1],
2512 This->updateStateBlock->clipplane[Index][2],
2513 This->updateStateBlock->clipplane[Index][3]);
2514 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2515 checkGLcall("glClipPlane");
2523 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2524 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2525 TRACE("(%p) : for idx %ld\n", This, Index);
2527 /* Validate Index */
2528 if (Index >= GL_LIMITS(clipplanes)) {
2529 TRACE("Application has requested clipplane this device doesn't support\n");
2530 return D3DERR_INVALIDCALL;
2533 pPlane[0] = This->stateBlock->clipplane[Index][0];
2534 pPlane[1] = This->stateBlock->clipplane[Index][1];
2535 pPlane[2] = This->stateBlock->clipplane[Index][2];
2536 pPlane[3] = This->stateBlock->clipplane[Index][3];
2541 * Get / Set Clip Plane Status
2542 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2544 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2545 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2546 FIXME("(%p) : stub\n", This);
2547 if (NULL == pClipStatus) {
2548 return D3DERR_INVALIDCALL;
2550 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2551 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2555 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2556 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2557 FIXME("(%p) : stub\n", This);
2558 if (NULL == pClipStatus) {
2559 return D3DERR_INVALIDCALL;
2561 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2562 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2567 * Get / Set Material
2568 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2570 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2571 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2573 This->updateStateBlock->changed.material = TRUE;
2574 This->updateStateBlock->set.material = TRUE;
2575 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2577 /* Handle recording of state blocks */
2578 if (This->isRecordingState) {
2579 TRACE("Recording... not performing anything\n");
2584 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2585 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2586 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2587 pMaterial->Ambient.b, pMaterial->Ambient.a);
2588 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2589 pMaterial->Specular.b, pMaterial->Specular.a);
2590 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2591 pMaterial->Emissive.b, pMaterial->Emissive.a);
2592 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2594 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2595 checkGLcall("glMaterialfv(GL_AMBIENT)");
2596 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2597 checkGLcall("glMaterialfv(GL_DIFFUSE)");
2599 /* Only change material color if specular is enabled, otherwise it is set to black */
2600 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2601 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2602 checkGLcall("glMaterialfv(GL_SPECULAR");
2604 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2605 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2606 checkGLcall("glMaterialfv(GL_SPECULAR");
2608 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2609 checkGLcall("glMaterialfv(GL_EMISSION)");
2610 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2611 checkGLcall("glMaterialf(GL_SHININESS");
2617 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2618 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2619 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2620 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2621 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2622 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2623 pMaterial->Ambient.b, pMaterial->Ambient.a);
2624 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2625 pMaterial->Specular.b, pMaterial->Specular.a);
2626 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2627 pMaterial->Emissive.b, pMaterial->Emissive.a);
2628 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2636 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2637 UINT BaseVertexIndex) {
2638 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2639 IWineD3DIndexBuffer *oldIdxs;
2641 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2642 oldIdxs = This->updateStateBlock->pIndexData;
2644 This->updateStateBlock->changed.indices = TRUE;
2645 This->updateStateBlock->set.indices = TRUE;
2646 This->updateStateBlock->pIndexData = pIndexData;
2647 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2649 /* Handle recording of state blocks */
2650 if (This->isRecordingState) {
2651 TRACE("Recording... not performing anything\n");
2655 if (NULL != pIndexData) {
2656 IWineD3DIndexBuffer_AddRef(pIndexData);
2658 if (NULL != oldIdxs) {
2659 IWineD3DIndexBuffer_Release(oldIdxs);
2664 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2665 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2667 *ppIndexData = This->stateBlock->pIndexData;
2669 /* up ref count on ppindexdata */
2671 IWineD3DIndexBuffer_AddRef(*ppIndexData);
2672 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2673 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
2675 TRACE("(%p) No index data set\n", This);
2677 TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
2683 * Get / Set Viewports
2685 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2686 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2688 TRACE("(%p)\n", This);
2689 This->updateStateBlock->changed.viewport = TRUE;
2690 This->updateStateBlock->set.viewport = TRUE;
2691 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2693 /* Handle recording of state blocks */
2694 if (This->isRecordingState) {
2695 TRACE("Recording... not performing anything\n");
2698 This->viewport_changed = TRUE;
2702 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2703 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2705 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2706 checkGLcall("glDepthRange");
2707 /* Note: GL requires lower left, DirectX supplies upper left */
2708 /* TODO: replace usage of renderTarget with context management */
2709 glViewport(pViewport->X,
2710 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2711 pViewport->Width, pViewport->Height);
2713 checkGLcall("glViewport");
2721 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2722 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2723 TRACE("(%p)\n", This);
2724 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2729 * Get / Set Render States
2730 * TODO: Verify against dx9 definitions
2732 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2734 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2735 DWORD OldValue = This->stateBlock->renderState[State];
2737 /* Simple way of referring to either a DWORD or a 4 byte float */
2743 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2744 This->updateStateBlock->changed.renderState[State] = TRUE;
2745 This->updateStateBlock->set.renderState[State] = TRUE;
2746 This->updateStateBlock->renderState[State] = Value;
2748 /* Handle recording of state blocks */
2749 if (This->isRecordingState) {
2750 TRACE("Recording... not performing anything\n");
2757 case WINED3DRS_FILLMODE :
2758 switch ((D3DFILLMODE) Value) {
2759 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2760 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2761 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2763 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
2765 checkGLcall("glPolygonMode (fillmode)");
2768 case WINED3DRS_LIGHTING :
2770 glEnable(GL_LIGHTING);
2771 checkGLcall("glEnable GL_LIGHTING");
2773 glDisable(GL_LIGHTING);
2774 checkGLcall("glDisable GL_LIGHTING");
2778 case WINED3DRS_ZENABLE :
2779 switch ((D3DZBUFFERTYPE) Value) {
2781 glDisable(GL_DEPTH_TEST);
2782 checkGLcall("glDisable GL_DEPTH_TEST");
2785 glEnable(GL_DEPTH_TEST);
2786 checkGLcall("glEnable GL_DEPTH_TEST");
2789 glEnable(GL_DEPTH_TEST);
2790 checkGLcall("glEnable GL_DEPTH_TEST");
2791 FIXME("W buffer is not well handled\n");
2794 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2798 case WINED3DRS_CULLMODE :
2800 /* If we are culling "back faces with clockwise vertices" then
2801 set front faces to be counter clockwise and enable culling
2803 switch ((D3DCULL) Value) {
2805 glDisable(GL_CULL_FACE);
2806 checkGLcall("glDisable GL_CULL_FACE");
2809 glEnable(GL_CULL_FACE);
2810 checkGLcall("glEnable GL_CULL_FACE");
2811 if (This->renderUpsideDown) {
2813 checkGLcall("glFrontFace GL_CW");
2815 glFrontFace(GL_CCW);
2816 checkGLcall("glFrontFace GL_CCW");
2818 glCullFace(GL_BACK);
2821 glEnable(GL_CULL_FACE);
2822 checkGLcall("glEnable GL_CULL_FACE");
2823 if (This->renderUpsideDown) {
2824 glFrontFace(GL_CCW);
2825 checkGLcall("glFrontFace GL_CCW");
2828 checkGLcall("glFrontFace GL_CW");
2830 glCullFace(GL_BACK);
2833 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2837 case WINED3DRS_SHADEMODE :
2838 switch ((D3DSHADEMODE) Value) {
2840 glShadeModel(GL_FLAT);
2841 checkGLcall("glShadeModel");
2843 case D3DSHADE_GOURAUD:
2844 glShadeModel(GL_SMOOTH);
2845 checkGLcall("glShadeModel");
2847 case D3DSHADE_PHONG:
2848 FIXME("D3DSHADE_PHONG isn't supported?\n");
2851 return D3DERR_INVALIDCALL;
2853 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2857 case WINED3DRS_DITHERENABLE :
2859 glEnable(GL_DITHER);
2860 checkGLcall("glEnable GL_DITHER");
2862 glDisable(GL_DITHER);
2863 checkGLcall("glDisable GL_DITHER");
2867 case WINED3DRS_ZWRITEENABLE :
2870 checkGLcall("glDepthMask");
2873 checkGLcall("glDepthMask");
2877 case WINED3DRS_ZFUNC :
2879 int glParm = GL_LESS;
2881 switch ((D3DCMPFUNC) Value) {
2882 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2883 case D3DCMP_LESS: glParm=GL_LESS; break;
2884 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2885 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2886 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2887 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2888 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2889 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2891 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2893 glDepthFunc(glParm);
2894 checkGLcall("glDepthFunc");
2898 case WINED3DRS_AMBIENT :
2901 D3DCOLORTOGLFLOAT4(Value, col);
2902 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2903 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2904 checkGLcall("glLightModel for MODEL_AMBIENT");
2909 case WINED3DRS_ALPHABLENDENABLE :
2912 checkGLcall("glEnable GL_BLEND");
2914 glDisable(GL_BLEND);
2915 checkGLcall("glDisable GL_BLEND");
2919 case WINED3DRS_SRCBLEND :
2920 case WINED3DRS_DESTBLEND :
2922 int newVal = GL_ZERO;
2924 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2925 case D3DBLEND_ONE : newVal = GL_ONE; break;
2926 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2927 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2928 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2929 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2930 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2931 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2932 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2933 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2934 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2936 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2937 This->srcBlend = newVal;
2938 This->dstBlend = newVal;
2941 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2942 This->srcBlend = newVal;
2943 This->dstBlend = newVal;
2946 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2949 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2950 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2951 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2952 glBlendFunc(This->srcBlend, This->dstBlend);
2954 checkGLcall("glBlendFunc");
2958 case WINED3DRS_ALPHATESTENABLE :
2960 glEnable(GL_ALPHA_TEST);
2961 checkGLcall("glEnable GL_ALPHA_TEST");
2963 glDisable(GL_ALPHA_TEST);
2964 checkGLcall("glDisable GL_ALPHA_TEST");
2968 case WINED3DRS_ALPHAFUNC :
2970 int glParm = GL_LESS;
2971 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2973 switch ((D3DCMPFUNC) Value) {
2974 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2975 case D3DCMP_LESS: glParm = GL_LESS; break;
2976 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2977 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2978 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2979 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2980 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2981 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2983 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2985 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2986 glAlphaFunc(glParm, ref);
2987 This->alphafunc = glParm;
2988 checkGLcall("glAlphaFunc");
2992 case WINED3DRS_ALPHAREF :
2994 int glParm = This->alphafunc;
2997 ref = ((float) Value) / 255.0f;
2998 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2999 glAlphaFunc(glParm, ref);
3000 checkGLcall("glAlphaFunc");
3004 case WINED3DRS_CLIPPLANEENABLE :
3005 case WINED3DRS_CLIPPING :
3007 /* Ensure we only do the changed clip planes */
3008 DWORD enable = 0xFFFFFFFF;
3009 DWORD disable = 0x00000000;
3011 /* If enabling / disabling all */
3012 if (State == WINED3DRS_CLIPPING) {
3014 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3017 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3021 enable = Value & ~OldValue;
3022 disable = ~Value & OldValue;
3025 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
3026 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
3027 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
3028 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
3029 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
3030 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
3032 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
3033 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
3034 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
3035 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
3036 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
3037 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
3039 /** update clipping status */
3041 This->stateBlock->clip_status.ClipUnion = 0;
3042 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
3044 This->stateBlock->clip_status.ClipUnion = 0;
3045 This->stateBlock->clip_status.ClipIntersection = 0;
3050 case WINED3DRS_BLENDOP :
3052 int glParm = GL_FUNC_ADD;
3054 switch ((D3DBLENDOP) Value) {
3055 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
3056 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
3057 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3058 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
3059 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
3061 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
3063 TRACE("glBlendEquation(%x)\n", glParm);
3064 glBlendEquation(glParm);
3065 checkGLcall("glBlendEquation");
3069 case WINED3DRS_TEXTUREFACTOR :
3073 /* Note the texture color applies to all textures whereas
3074 GL_TEXTURE_ENV_COLOR applies to active only */
3076 D3DCOLORTOGLFLOAT4(Value, col);
3077 /* Set the default alpha blend color */
3078 glBlendColor(col[0], col[1], col[2], col[3]);
3079 checkGLcall("glBlendColor");
3081 /* And now the default texture color as well */
3082 for (i = 0; i < GL_LIMITS(textures); i++) {
3084 /* Note the D3DRS value applies to all textures, but GL has one
3085 per texture, so apply it now ready to be used! */
3086 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3089 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3092 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3093 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3098 case WINED3DRS_SPECULARENABLE :
3100 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3101 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3102 specular color. This is wrong:
3103 Separate specular color means the specular colour is maintained separately, whereas
3104 single color means it is merged in. However in both cases they are being used to
3106 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3107 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3111 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3112 checkGLcall("glMaterialfv");
3113 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3114 glEnable(GL_COLOR_SUM_EXT);
3116 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3118 checkGLcall("glEnable(GL_COLOR_SUM)");
3120 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3122 /* for the case of enabled lighting: */
3123 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3124 checkGLcall("glMaterialfv");
3126 /* for the case of disabled lighting: */
3127 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3128 glDisable(GL_COLOR_SUM_EXT);
3130 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3132 checkGLcall("glDisable(GL_COLOR_SUM)");
3137 case WINED3DRS_STENCILENABLE :
3139 glEnable(GL_STENCIL_TEST);
3140 checkGLcall("glEnable GL_STENCIL_TEST");
3142 glDisable(GL_STENCIL_TEST);
3143 checkGLcall("glDisable GL_STENCIL_TEST");
3147 case WINED3DRS_STENCILFUNC :
3150 GLint ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3151 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3154 switch ((D3DCMPFUNC)Value) {
3155 case D3DCMP_NEVER: func = GL_NEVER; break;
3156 case D3DCMP_LESS: func = GL_LESS; break;
3157 case D3DCMP_EQUAL: func = GL_EQUAL; break;
3158 case D3DCMP_LESSEQUAL: func = GL_LEQUAL; break;
3159 case D3DCMP_GREATER: func = GL_GREATER; break;
3160 case D3DCMP_NOTEQUAL: func = GL_NOTEQUAL; break;
3161 case D3DCMP_GREATEREQUAL: func = GL_GEQUAL; break;
3162 case D3DCMP_ALWAYS: func = GL_ALWAYS; break;
3164 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3166 This->stencilfunc = func;
3167 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3168 if(GL_EXTCALL(glStencilFuncSeparate)) {
3169 GL_EXTCALL(glStencilFuncSeparate(GL_FRONT, func, ref, mask));
3170 checkGLcall("glStencilFuncSeparate(GL_FRONT,...)");
3172 else if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3173 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3174 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3175 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
3176 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
3177 glStencilFunc(func, ref, mask);
3178 checkGLcall("glStencilFunc(...)");
3180 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3181 GL_EXTCALL(glStencilFuncSeparateATI(GL_FRONT, func, ref, mask));
3182 checkGLcall("glStencilFuncSeparateATI(GL_FRONT,...)");
3184 TRACE("Separate stencil function not supported on this version of opengl");
3185 glStencilFunc(func, ref, mask);
3186 checkGLcall("glStencilFunc(...)");
3189 glStencilFunc(func, ref, mask);
3190 checkGLcall("glStencilFunc(...)");
3194 case WINED3DRS_STENCILREF :
3196 int glParm = This->stencilfunc;
3198 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3201 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3202 glStencilFunc(glParm, ref, mask);
3203 checkGLcall("glStencilFunc");
3207 case WINED3DRS_STENCILMASK :
3209 int glParm = This->stencilfunc;
3210 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3211 GLuint mask = Value;
3213 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3214 glStencilFunc(glParm, ref, mask);
3215 checkGLcall("glStencilFunc");
3219 case WINED3DRS_STENCILFAIL :
3220 case WINED3DRS_STENCILZFAIL :
3221 case WINED3DRS_STENCILPASS :
3227 GLint action = StencilOp(Value);
3229 glGetIntegerv(GL_STENCIL_FAIL, &stencilFail);
3230 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &depthFail);
3231 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &stencilPass);
3233 if(WINED3DRS_STENCILFAIL == State) {
3234 stencilFail = action;
3236 else if(WINED3DRS_STENCILZFAIL == State) {
3239 else if(WINED3DRS_STENCILPASS == State) {
3240 stencilPass = action;
3243 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3244 if(GL_EXTCALL(glStencilOpSeparate)) {
3245 GL_EXTCALL(glStencilOpSeparate(GL_FRONT, stencilFail, depthFail, stencilPass));
3246 checkGLcall("glStencilOpSeparate(GL_FRONT,...)");
3248 else if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3249 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3250 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3251 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
3252 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
3253 glStencilOp(stencilFail, depthFail, stencilPass);
3254 checkGLcall("glStencilOp(...)");
3256 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3257 GL_EXTCALL(glStencilOpSeparateATI(GL_FRONT, stencilFail, depthFail, stencilPass));
3258 checkGLcall("glStencilOpSeparateATI(GL_FRONT,...)");
3260 TRACE("Separate stencil operation not supported on this version of opengl");
3261 glStencilOp(stencilFail, depthFail, stencilPass);
3262 checkGLcall("glStencilOp(...)");
3265 glStencilOp(stencilFail, depthFail, stencilPass);
3266 checkGLcall("glStencilOp(...)");
3270 case WINED3DRS_STENCILWRITEMASK :
3272 glStencilMask(Value);
3273 TRACE("glStencilMask(%lu)\n", Value);
3274 checkGLcall("glStencilMask");
3278 case WINED3DRS_FOGENABLE :
3280 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
3282 checkGLcall("glEnable GL_FOG");
3285 checkGLcall("glDisable GL_FOG");
3290 case WINED3DRS_RANGEFOGENABLE :
3293 TRACE("Enabled RANGEFOG");
3295 TRACE("Disabled RANGEFOG");
3300 case WINED3DRS_FOGCOLOR :
3303 D3DCOLORTOGLFLOAT4(Value, col);
3304 /* Set the default alpha blend color */
3305 glFogfv(GL_FOG_COLOR, &col[0]);
3306 checkGLcall("glFog GL_FOG_COLOR");
3310 case WINED3DRS_FOGTABLEMODE :
3312 glHint(GL_FOG_HINT, GL_NICEST);
3314 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3315 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3316 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3317 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3319 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3321 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3322 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3327 case WINED3DRS_FOGVERTEXMODE :
3329 glHint(GL_FOG_HINT, GL_FASTEST);
3331 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3332 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3333 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3334 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3336 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3338 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3339 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
3344 case WINED3DRS_FOGSTART :
3347 glFogfv(GL_FOG_START, &tmpvalue.f);
3348 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3349 TRACE("Fog Start == %f\n", tmpvalue.f);
3353 case WINED3DRS_FOGEND :
3356 glFogfv(GL_FOG_END, &tmpvalue.f);
3357 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3358 TRACE("Fog End == %f\n", tmpvalue.f);
3362 case WINED3DRS_FOGDENSITY :
3365 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3366 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3370 case WINED3DRS_VERTEXBLEND :
3372 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3373 TRACE("Vertex Blending state to %ld\n", Value);
3377 case WINED3DRS_TWEENFACTOR :
3380 This->updateStateBlock->tween_factor = tmpvalue.f;
3381 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3385 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
3387 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3391 case WINED3DRS_COLORVERTEX :
3392 case WINED3DRS_DIFFUSEMATERIALSOURCE :
3393 case WINED3DRS_SPECULARMATERIALSOURCE :
3394 case WINED3DRS_AMBIENTMATERIALSOURCE :
3395 case WINED3DRS_EMISSIVEMATERIALSOURCE :
3397 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3399 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3400 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3401 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3402 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3403 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3404 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3406 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3407 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3408 Parm = GL_AMBIENT_AND_DIFFUSE;
3412 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3414 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3416 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3423 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3425 This->tracking_color = NEEDS_TRACKING;
3426 This->tracking_parm = Parm;
3430 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3435 case WINED3DRS_LINEPATTERN :
3441 tmppattern.d = Value;
3443 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3445 if (tmppattern.lp.wRepeatFactor) {
3446 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3447 checkGLcall("glLineStipple(repeat, linepattern)");
3448 glEnable(GL_LINE_STIPPLE);
3449 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3451 glDisable(GL_LINE_STIPPLE);
3452 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3457 case WINED3DRS_ZBIAS : /* D3D8 only */
3461 TRACE("ZBias value %f\n", tmpvalue.f);
3462 glPolygonOffset(0, -tmpvalue.f);
3463 checkGLcall("glPolygonOffset(0, -Value)");
3464 glEnable(GL_POLYGON_OFFSET_FILL);
3465 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3466 glEnable(GL_POLYGON_OFFSET_LINE);
3467 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3468 glEnable(GL_POLYGON_OFFSET_POINT);
3469 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3471 glDisable(GL_POLYGON_OFFSET_FILL);
3472 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3473 glDisable(GL_POLYGON_OFFSET_LINE);
3474 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3475 glDisable(GL_POLYGON_OFFSET_POINT);
3476 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3481 case WINED3DRS_NORMALIZENORMALS :
3483 glEnable(GL_NORMALIZE);
3484 checkGLcall("glEnable(GL_NORMALIZE);");
3486 glDisable(GL_NORMALIZE);
3487 checkGLcall("glDisable(GL_NORMALIZE);");
3491 case WINED3DRS_POINTSIZE :
3492 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
3494 TRACE("Set point size to %f\n", tmpvalue.f);
3495 glPointSize(tmpvalue.f);
3496 checkGLcall("glPointSize(...);");
3499 case WINED3DRS_POINTSIZE_MIN :
3500 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3502 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3503 checkGLcall("glPointParameterfEXT(...);");
3505 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3509 case WINED3DRS_POINTSIZE_MAX :
3510 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3512 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3513 checkGLcall("glPointParameterfEXT(...);");
3515 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3519 case WINED3DRS_POINTSCALE_A :
3520 case WINED3DRS_POINTSCALE_B :
3521 case WINED3DRS_POINTSCALE_C :
3522 case WINED3DRS_POINTSCALEENABLE :
3525 * POINTSCALEENABLE controls how point size value is treated. If set to
3526 * true, the point size is scaled with respect to height of viewport.
3527 * When set to false point size is in pixels.
3529 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
3532 /* Default values */
3533 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3536 * Minimum valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
3537 * This means that OpenGL will clamp really small point sizes to 1.0f.
3538 * To correct for this we need to multiply by the scale factor when sizes
3539 * are less than 1.0f. scale_factor = 1.0f / point_size.
3541 GLfloat pointSize = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSIZE]);
3542 if(pointSize > 0.0f) {
3543 GLfloat scaleFactor;
3545 if(pointSize < 1.0f) {
3546 scaleFactor = pointSize * pointSize;
3551 if(This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3552 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]) /
3553 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3554 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]) /
3555 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3556 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) /
3557 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3561 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
3562 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
3563 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
3565 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3566 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3567 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
3569 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
3573 case WINED3DRS_COLORWRITEENABLE :
3575 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3576 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3577 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3578 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3579 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3580 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3581 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3582 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3583 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3584 checkGLcall("glColorMask(...)");
3588 case WINED3DRS_LOCALVIEWER :
3590 GLint state = (Value) ? 1 : 0;
3591 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3592 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3596 case WINED3DRS_LASTPIXEL :
3599 TRACE("Last Pixel Drawing Enabled\n");
3601 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3606 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3609 TRACE("Software Processing Enabled\n");
3611 TRACE("Software Processing Disabled\n");
3616 /** not supported */
3617 case WINED3DRS_ZVISIBLE :
3620 return D3DERR_INVALIDCALL;
3622 case WINED3DRS_POINTSPRITEENABLE :
3624 /* TODO: NV_POINT_SPRITE */
3625 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
3626 TRACE("Point sprites not supported\n");
3631 * Point sprites are always enabled. Value controls texture coordinate
3632 * replacement mode. Must be set true for point sprites to use
3635 glEnable(GL_POINT_SPRITE_ARB);
3636 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
3639 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
3640 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, TRUE)");
3642 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, FALSE);
3643 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, FALSE)");
3647 case WINED3DRS_EDGEANTIALIAS :
3650 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3652 checkGLcall("glEnable(GL_BLEND)");
3653 glEnable(GL_LINE_SMOOTH);
3654 checkGLcall("glEnable(GL_LINE_SMOOTH)");
3656 glDisable(GL_BLEND);
3657 checkGLcall("glDisable(GL_BLEND)");
3658 glDisable(GL_LINE_SMOOTH);
3659 checkGLcall("glDisable(GL_LINE_SMOOTH)");
3663 case WINED3DRS_WRAP0 :
3664 case WINED3DRS_WRAP1 :
3665 case WINED3DRS_WRAP2 :
3666 case WINED3DRS_WRAP3 :
3667 case WINED3DRS_WRAP4 :
3668 case WINED3DRS_WRAP5 :
3669 case WINED3DRS_WRAP6 :
3670 case WINED3DRS_WRAP7 :
3672 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
3673 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
3674 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
3675 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
3676 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
3678 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
3680 TRACE("(%p)->(%d,%ld) Texture wraping not yet supported\n",This, State, Value);
3682 case WINED3DRS_MULTISAMPLEANTIALIAS :
3684 if (!GL_SUPPORT(ARB_MULTISAMPLE)) {
3685 TRACE("Multisample antialiasing not supported\n");
3690 glEnable(GL_MULTISAMPLE_ARB);
3691 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
3693 glDisable(GL_MULTISAMPLE_ARB);
3694 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
3698 case WINED3DRS_SCISSORTESTENABLE :
3701 glEnable(GL_SCISSOR_TEST);
3702 checkGLcall("glEnable(GL_SCISSOR_TEST)");
3704 glDisable(GL_SCISSOR_TEST);
3705 checkGLcall("glDisable(GL_SCISSOR_TEST)");
3709 case WINED3DRS_SLOPESCALEDEPTHBIAS :
3713 glEnable(GL_POLYGON_OFFSET_FILL);
3714 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
3715 glPolygonOffset(tmpvalue.f, *((float*)&This->stateBlock->renderState[WINED3DRS_DEPTHBIAS]));
3716 checkGLcall("glPolygonOffset(...)");
3718 glDisable(GL_POLYGON_OFFSET_FILL);
3719 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
3723 case WINED3DRS_ANTIALIASEDLINEENABLE :
3726 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3728 checkGLcall("glEnable(GL_BLEND)");
3729 glEnable(GL_LINE_SMOOTH);
3730 checkGLcall("glEnable(GL_LINE_SMOOTH)");
3732 glDisable(GL_BLEND);
3733 checkGLcall("glDisable(GL_BLEND)");
3734 glDisable(GL_LINE_SMOOTH);
3735 checkGLcall("glDisable(GL_LINE_SMOOTH)");
3739 case WINED3DRS_MULTISAMPLEMASK :
3740 case WINED3DRS_PATCHEDGESTYLE :
3741 case WINED3DRS_PATCHSEGMENTS :
3742 case WINED3DRS_DEBUGMONITORTOKEN :
3743 case WINED3DRS_POSITIONORDER :
3744 case WINED3DRS_NORMALORDER :
3745 /* Direct3D9 render states */
3746 case WINED3DRS_MINTESSELLATIONLEVEL :
3747 case WINED3DRS_MAXTESSELLATIONLEVEL :
3748 case WINED3DRS_ADAPTIVETESS_X :
3749 case WINED3DRS_ADAPTIVETESS_Y :
3750 case WINED3DRS_ADAPTIVETESS_Z :
3751 case WINED3DRS_ADAPTIVETESS_W :
3752 case WINED3DRS_ENABLEADAPTIVETESSELLATION :
3754 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3757 case WINED3DRS_TWOSIDEDSTENCILMODE :
3760 TRACE("Two-sided stencil mode enabled\n");
3762 TRACE("Two-sided stencil mode disabled\n");
3766 case WINED3DRS_CCW_STENCILFAIL :
3767 case WINED3DRS_CCW_STENCILZFAIL :
3768 case WINED3DRS_CCW_STENCILPASS :
3774 GLint action = StencilOp(Value);
3776 glGetIntegerv(GL_STENCIL_BACK_FAIL, &stencilFail);
3777 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &depthFail);
3778 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS, &stencilPass);
3780 if(WINED3DRS_CCW_STENCILFAIL == State) {
3781 stencilFail = action;
3783 else if(WINED3DRS_CCW_STENCILZFAIL == State) {
3786 else if(WINED3DRS_CCW_STENCILPASS == State) {
3787 stencilPass = action;
3790 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3791 if(GL_EXTCALL(glStencilOpSeparate)) {
3792 GL_EXTCALL(glStencilOpSeparate(GL_BACK, stencilFail, depthFail, stencilPass));
3793 checkGLcall("glStencilOpSeparate(GL_BACK,...)");
3795 else if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3796 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3797 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3798 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
3799 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
3800 glStencilOp(stencilFail, depthFail, stencilPass);
3801 checkGLcall("glStencilOp(...)");
3803 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3804 GL_EXTCALL(glStencilOpSeparateATI(GL_BACK, stencilFail, depthFail, stencilPass));
3805 checkGLcall("glStencilOpSeparateATI(GL_BACK,...)");
3807 TRACE("Separate stencil operation not supported on this version of opengl");
3808 glStencilOp(stencilFail, depthFail, stencilPass);
3809 checkGLcall("glStencilOp(...)");
3812 glStencilOp(stencilFail, depthFail, stencilPass);
3813 checkGLcall("glStencilOp(...)");
3817 case WINED3DRS_CCW_STENCILFUNC :
3820 GLint ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3821 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3824 switch ((D3DCMPFUNC)Value) {
3825 case D3DCMP_NEVER: func = GL_NEVER; break;
3826 case D3DCMP_LESS: func = GL_LESS; break;
3827 case D3DCMP_EQUAL: func = GL_EQUAL; break;
3828 case D3DCMP_LESSEQUAL: func = GL_LEQUAL; break;
3829 case D3DCMP_GREATER: func = GL_GREATER; break;
3830 case D3DCMP_NOTEQUAL: func = GL_NOTEQUAL; break;
3831 case D3DCMP_GREATEREQUAL: func = GL_GEQUAL; break;
3832 case D3DCMP_ALWAYS: func = GL_ALWAYS; break;
3834 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3836 This->stencilfunc = func;
3837 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3838 if(GL_EXTCALL(glStencilFuncSeparate)) {
3839 GL_EXTCALL(glStencilFuncSeparate(GL_BACK, func, ref, mask));
3840 checkGLcall("glStencilFuncSeparate(GL_BACK,...)");
3842 else if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3843 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3844 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3845 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
3846 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
3847 glStencilFunc(func, ref, mask);
3848 checkGLcall("glStencilFunc(...)");
3850 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3851 GL_EXTCALL(glStencilFuncSeparateATI(GL_BACK, func, ref, mask));
3852 checkGLcall("glStencilFuncSeparateATI(GL_BACK,...)");
3854 TRACE("Separate stencil function not supported on this version of opengl");
3855 glStencilFunc(func, ref, mask);
3856 checkGLcall("glStencilFunc(...)");
3859 glStencilFunc(func, ref, mask);
3860 checkGLcall("glStencilFunc(...)");
3864 case WINED3DRS_COLORWRITEENABLE1 :
3865 case WINED3DRS_COLORWRITEENABLE2 :
3866 case WINED3DRS_COLORWRITEENABLE3 :
3867 case WINED3DRS_BLENDFACTOR :
3868 case WINED3DRS_SRGBWRITEENABLE :
3870 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3873 case WINED3DRS_DEPTHBIAS :
3877 glEnable(GL_POLYGON_OFFSET_FILL);
3878 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
3879 glPolygonOffset(*((float*)&This->stateBlock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS]), tmpvalue.f);
3880 checkGLcall("glPolygonOffset(...)");
3882 glDisable(GL_POLYGON_OFFSET_FILL);
3883 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
3887 case WINED3DRS_WRAP8 :
3888 case WINED3DRS_WRAP9 :
3889 case WINED3DRS_WRAP10 :
3890 case WINED3DRS_WRAP11 :
3891 case WINED3DRS_WRAP12 :
3892 case WINED3DRS_WRAP13 :
3893 case WINED3DRS_WRAP14 :
3894 case WINED3DRS_WRAP15 :
3895 case WINED3DRS_SEPARATEALPHABLENDENABLE :
3896 case WINED3DRS_SRCBLENDALPHA :
3897 case WINED3DRS_DESTBLENDALPHA :
3898 case WINED3DRS_BLENDOPALPHA :
3899 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3900 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3903 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3911 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3912 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3913 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3914 *pValue = This->stateBlock->renderState[State];
3919 * Get / Set Sampler States
3920 * TODO: Verify against dx9 definitions
3923 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3924 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3926 * SetSampler is designed to allow for more than the standard up to 8 textures
3927 * and Geforce has stopped supporting more than 6 standard textures in openGL.
3928 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3930 * http://developer.nvidia.com/object/General_FAQ.html#t6
3932 * There are two new settings for GForce
3934 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3935 * and the texture one:
3936 * GL_MAX_TEXTURE_COORDS_ARB.
3937 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3939 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
3940 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
3942 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
3943 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE, Sampler, Type);
3944 return D3DERR_INVALIDCALL;
3946 TRACE("Setting sampler %ld %d to %ld\n", Sampler, Type, Value);
3947 This->updateStateBlock->samplerState[Sampler][Type] = Value;
3948 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
3949 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
3951 /* Handle recording of state blocks */
3952 if (This->isRecordingState) {
3953 TRACE("Recording... not performing anything\n");
3960 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3961 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3962 /** TODO: check that sampler is in range **/
3963 *Value = This->updateStateBlock->samplerState[Sampler][Type];
3964 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
3969 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3970 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3973 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3974 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3975 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3981 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3982 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3983 GLint scissorBox[4];
3986 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3987 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
3988 pRect->left = scissorBox[1];
3989 pRect->top = scissorBox[2];
3990 pRect->right = scissorBox[1] + scissorBox[3];
3991 pRect->bottom = scissorBox[2] + scissorBox[4];
3992 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3997 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3998 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3999 IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
4001 TRACE("(%p) : pDecl=%p\n", This, pDecl);
4003 This->updateStateBlock->vertexDecl = pDecl;
4004 This->updateStateBlock->changed.vertexDecl = TRUE;
4005 This->updateStateBlock->set.vertexDecl = TRUE;
4007 if (This->isRecordingState) {
4008 TRACE("Recording... not performing anything\n");
4011 if (NULL != pDecl) {
4012 IWineD3DVertexDeclaration_AddRef(pDecl);
4014 if (NULL != oldDecl) {
4015 IWineD3DVertexDeclaration_Release(oldDecl);
4020 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
4021 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4023 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
4025 *ppDecl = This->stateBlock->vertexDecl;
4026 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
4030 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
4031 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4032 IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
4034 This->updateStateBlock->vertexShader = pShader;
4035 This->updateStateBlock->changed.vertexShader = TRUE;
4036 This->updateStateBlock->set.vertexShader = TRUE;
4038 if (This->isRecordingState) {
4039 TRACE("Recording... not performing anything\n");
4042 if (NULL != pShader) {
4043 IWineD3DVertexShader_AddRef(pShader);
4045 if (NULL != oldShader) {
4046 IWineD3DVertexShader_Release(oldShader);
4049 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4051 * TODO: merge HAL shaders context switching from prototype
4056 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
4057 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4059 if (NULL == ppShader) {
4060 return D3DERR_INVALIDCALL;
4062 *ppShader = This->stateBlock->vertexShader;
4063 if( NULL != *ppShader)
4064 IWineD3DVertexShader_AddRef(*ppShader);
4066 TRACE("(%p) : returning %p\n", This, *ppShader);
4070 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4071 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4074 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4076 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4077 iface, dstData, srcData, type, start, count, registersize);
4079 if (type != WINESHADERCNST_NONE) {
4080 if (srcData == NULL || cnt < 0) {
4081 return D3DERR_INVALIDCALL;
4084 CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
4087 for (i = start; i < cnt + start; ++i) {
4088 This->updateStateBlock->changed.vertexShaderConstants[i] = TRUE;
4089 This->updateStateBlock->set.vertexShaderConstants[i] = TRUE;
4090 This->updateStateBlock->vertexShaderConstantT[i] = type;
4096 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4097 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4100 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4102 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4103 iface, dstData, srcData, type, start, count, registersize);
4105 /* Verify that the requested shader constant was populated with the correct type */
4106 for (i = start; i < cnt + start; ++i) {
4107 if (This->updateStateBlock->vertexShaderConstantT[i] != type) {
4108 TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning D3DERR_INVALIDCALL\n",
4109 This, type, This->updateStateBlock->vertexShaderConstantT[i]);
4110 return D3DERR_INVALIDCALL;
4114 if (dstData == NULL || cnt < 0) {
4115 return D3DERR_INVALIDCALL;
4118 CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
4123 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
4124 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4126 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4127 This->updateStateBlock->vertexShaderConstantB,
4129 WINESHADERCNST_BOOL,
4132 sizeof(*pConstantData));
4135 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
4136 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4138 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4140 This->updateStateBlock->vertexShaderConstantB,
4141 WINESHADERCNST_BOOL,
4144 sizeof(*pConstantData));
4147 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
4148 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4150 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4151 This->updateStateBlock->vertexShaderConstantI,
4153 WINESHADERCNST_INTEGER,
4156 4 * sizeof(*pConstantData));
4159 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
4160 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4162 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4164 This->updateStateBlock->vertexShaderConstantI,
4165 WINESHADERCNST_INTEGER,
4168 4 * sizeof(*pConstantData));
4172 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
4173 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4175 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4176 This->updateStateBlock->vertexShaderConstantF,
4178 WINESHADERCNST_FLOAT,
4181 4 * sizeof(*pConstantData));
4184 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
4185 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4187 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4189 This->updateStateBlock->vertexShaderConstantF,
4190 WINESHADERCNST_FLOAT,
4193 4 * sizeof(*pConstantData));
4196 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
4197 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4200 WINESHADERCNST_NONE,
4206 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
4207 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4208 IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader;
4209 This->updateStateBlock->pixelShader = pShader;
4210 This->updateStateBlock->changed.pixelShader = TRUE;
4211 This->updateStateBlock->set.pixelShader = TRUE;
4213 /* Handle recording of state blocks */
4214 if (This->isRecordingState) {
4215 TRACE("Recording... not performing anything\n");
4218 if (NULL != pShader) {
4219 IWineD3DPixelShader_AddRef(pShader);
4221 if (NULL != oldShader) {
4222 IWineD3DPixelShader_Release(oldShader);
4225 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4227 * TODO: merge HAL shaders context switching from prototype
4232 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
4233 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4235 if (NULL == ppShader) {
4236 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
4237 return D3DERR_INVALIDCALL;
4240 *ppShader = This->stateBlock->pixelShader;
4241 if (NULL != ppShader) {
4242 IWineD3DPixelShader_AddRef(*ppShader);
4244 TRACE("(%p) : returning %p\n", This, *ppShader);
4248 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4249 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4252 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4254 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4255 iface, dstData, srcData, type, start, count, registersize);
4257 if (type != WINESHADERCNST_NONE) {
4258 if (srcData == NULL || cnt < 0) {
4259 return D3DERR_INVALIDCALL;
4262 CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
4265 for (i = start; i < cnt + start; ++i) {
4266 This->updateStateBlock->changed.pixelShaderConstants[i] = TRUE;
4267 This->updateStateBlock->set.pixelShaderConstants[i] = TRUE;
4268 This->updateStateBlock->pixelShaderConstantT[i] = type;
4274 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4275 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4278 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4280 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4281 iface, dstData, srcData, type, start, count, registersize);
4283 /* Verify that the requested shader constant was populated with the correct type */
4284 for (i = start; i < cnt + start; ++i) {
4285 if (This->updateStateBlock->pixelShaderConstantT[i] != type) {
4286 TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning D3DERR_INVALIDCALL\n",
4287 This, type, This->updateStateBlock->pixelShaderConstantT[i]);
4288 return D3DERR_INVALIDCALL;
4292 if (dstData == NULL || cnt < 0) {
4293 return D3DERR_INVALIDCALL;
4296 CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
4301 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
4302 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4304 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4305 This->updateStateBlock->pixelShaderConstantB,
4307 WINESHADERCNST_BOOL,
4310 sizeof(*pConstantData));
4313 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
4314 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4316 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4318 This->updateStateBlock->pixelShaderConstantB,
4319 WINESHADERCNST_BOOL,
4322 sizeof(*pConstantData));
4325 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
4326 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4328 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4329 This->updateStateBlock->pixelShaderConstantI,
4331 WINESHADERCNST_INTEGER,
4334 4 * sizeof(*pConstantData));
4337 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
4338 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4340 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4342 This->updateStateBlock->pixelShaderConstantI,
4343 WINESHADERCNST_INTEGER,
4346 4 * sizeof(*pConstantData));
4349 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
4350 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4352 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4353 This->updateStateBlock->pixelShaderConstantF,
4355 WINESHADERCNST_FLOAT,
4358 4 * sizeof(*pConstantData));
4361 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
4362 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4364 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4366 This->updateStateBlock->pixelShaderConstantF,
4367 WINESHADERCNST_FLOAT,
4370 4 * sizeof(*pConstantData));
4373 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
4374 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4377 WINESHADERCNST_NONE,
4383 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
4384 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4385 FIXME("(%p) : stub\n", This);
4390 * Apply / Get / Set Texture Stage States
4391 * TODO: Verify against dx9 definitions
4394 /* 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 */
4395 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
4396 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4397 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
4398 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4400 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4402 /* Check that the stage is within limits */
4403 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4404 TRACE("Attempt to access invalid texture rejected\n");
4411 case WINED3DTSS_ALPHAOP :
4412 case WINED3DTSS_COLOROP :
4413 /* nothing to do as moved to drawprim for now */
4415 case WINED3DTSS_ADDRESSW :
4416 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
4417 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
4418 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
4421 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
4422 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
4423 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
4424 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
4427 case WINED3DTSS_TEXCOORDINDEX :
4429 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
4431 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
4432 one flag, you can still specify an index value, which the system uses to
4433 determine the texture wrapping mode.
4434 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
4435 means use the vertex position (camera-space) as the input texture coordinates
4436 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
4437 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
4438 to the TEXCOORDINDEX value */
4441 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
4443 switch (Value & 0xFFFF0000) {
4444 case D3DTSS_TCI_PASSTHRU:
4445 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
4446 glDisable(GL_TEXTURE_GEN_S);
4447 glDisable(GL_TEXTURE_GEN_T);
4448 glDisable(GL_TEXTURE_GEN_R);
4449 glDisable(GL_TEXTURE_GEN_Q);
4450 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
4453 case D3DTSS_TCI_CAMERASPACEPOSITION:
4454 /* CameraSpacePosition means use the vertex position, transformed to camera space,
4455 as the input texture coordinates for this stage's texture transformation. This
4456 equates roughly to EYE_LINEAR */
4458 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4459 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4460 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4461 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4462 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4464 glMatrixMode(GL_MODELVIEW);
4467 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4468 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4469 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4470 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4473 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
4474 glEnable(GL_TEXTURE_GEN_S);
4475 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4476 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4477 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4478 glEnable(GL_TEXTURE_GEN_T);
4479 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4480 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4481 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4482 glEnable(GL_TEXTURE_GEN_R);
4483 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4484 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4485 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4489 case D3DTSS_TCI_CAMERASPACENORMAL:
4491 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4492 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4493 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4494 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4495 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4496 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
4498 glMatrixMode(GL_MODELVIEW);
4501 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4502 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4503 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4504 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4507 glEnable(GL_TEXTURE_GEN_S);
4508 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4509 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4510 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4511 glEnable(GL_TEXTURE_GEN_T);
4512 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4513 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4514 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4515 glEnable(GL_TEXTURE_GEN_R);
4516 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4517 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4518 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4523 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
4525 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4526 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4527 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4528 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4529 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4530 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
4532 glMatrixMode(GL_MODELVIEW);
4535 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4536 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4537 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4538 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4541 glEnable(GL_TEXTURE_GEN_S);
4542 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4543 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4544 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4545 glEnable(GL_TEXTURE_GEN_T);
4546 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4547 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4548 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4549 glEnable(GL_TEXTURE_GEN_R);
4550 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4551 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4552 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4557 /* Unhandled types: */
4560 /* ? disable GL_TEXTURE_GEN_n ? */
4561 glDisable(GL_TEXTURE_GEN_S);
4562 glDisable(GL_TEXTURE_GEN_T);
4563 glDisable(GL_TEXTURE_GEN_R);
4564 glDisable(GL_TEXTURE_GEN_Q);
4565 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
4572 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
4573 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);
4576 case WINED3DTSS_BUMPENVMAT00 :
4577 case WINED3DTSS_BUMPENVMAT01 :
4578 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
4580 case WINED3DTSS_BUMPENVMAT10 :
4581 case WINED3DTSS_BUMPENVMAT11 :
4582 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
4585 case WINED3DTSS_BUMPENVLSCALE :
4586 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4589 case WINED3DTSS_BUMPENVLOFFSET :
4590 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4593 case WINED3DTSS_RESULTARG :
4594 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4598 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
4599 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4608 * Get / Set Texture Stage States
4609 * TODO: Verify against dx9 definitions
4611 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
4612 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4614 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4616 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4618 /* Reject invalid texture units */
4619 if (Stage >= GL_LIMITS(textures)) {
4620 TRACE("Attempt to access invalid texture rejected\n");
4621 return D3DERR_INVALIDCALL;
4624 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
4625 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
4626 This->updateStateBlock->textureState[Stage][Type] = Value;
4631 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4632 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4633 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4634 *pValue = This->updateStateBlock->textureState[Stage][Type];
4641 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4643 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4644 IWineD3DBaseTexture *oldTexture;
4646 oldTexture = This->updateStateBlock->textures[Stage];
4647 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
4649 #if 0 /* TODO: check so vertex textures */
4650 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
4651 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
4656 /* Reject invalid texture units */
4657 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4658 WARN("Attempt to access invalid texture rejected\n");
4659 return D3DERR_INVALIDCALL;
4662 if(pTexture != NULL) {
4663 /* SetTexture isn't allowed on textures in D3DPOOL_SCRATCH; The same is
4664 * the case for D3DPOOL_SYSTEMMEM textures unless D3DDEVCAPS_TEXTURESYSTEMMORY is set.
4665 * We don't check the caps as GetDeviceCaps is inefficient and we don't set the cap anyway.
4667 if(((IWineD3DTextureImpl*)pTexture)->resource.pool == D3DPOOL_SCRATCH || ((IWineD3DTextureImpl*)pTexture)->resource.pool == D3DPOOL_SYSTEMMEM) {
4668 WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
4669 return D3DERR_INVALIDCALL;
4673 oldTexture = This->updateStateBlock->textures[Stage];
4674 TRACE("GL_LIMITS %d\n",GL_LIMITS(textures));
4675 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
4677 This->updateStateBlock->set.textures[Stage] = TRUE;
4678 This->updateStateBlock->changed.textures[Stage] = TRUE;
4679 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
4680 This->updateStateBlock->textures[Stage] = pTexture;
4682 /* Handle recording of state blocks */
4683 if (This->isRecordingState) {
4684 TRACE("Recording... not performing anything\n");
4688 /** NOTE: MSDN says that setTexture increases the reference count,
4689 * and the the application nust set the texture back to null (or have a leaky application),
4690 * This means we should pass the refcount up to the parent
4691 *******************************/
4692 if (NULL != This->updateStateBlock->textures[Stage]) {
4693 IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
4696 if (NULL != oldTexture) {
4697 IWineD3DBaseTexture_Release(oldTexture);
4703 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4704 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4705 TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
4707 /* Reject invalid texture units */
4708 if (Stage >= GL_LIMITS(textures)) {
4709 TRACE("Attempt to access invalid texture rejected\n");
4710 return D3DERR_INVALIDCALL;
4712 *ppTexture=This->updateStateBlock->textures[Stage];
4714 IWineD3DBaseTexture_AddRef(*ppTexture);
4716 return D3DERR_INVALIDCALL;
4723 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type,
4724 IWineD3DSurface **ppBackBuffer) {
4725 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4726 IWineD3DSwapChain *swapChain;
4729 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4731 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4733 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4734 IWineD3DSwapChain_Release(swapChain);
4736 *ppBackBuffer = NULL;
4741 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4742 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4743 WARN("(%p) : stub, calling idirect3d for now\n", This);
4744 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4747 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
4748 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4749 IWineD3DSwapChain *swapChain;
4752 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4754 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4755 IWineD3DSwapChain_Release(swapChain);
4757 FIXME("(%p) Error getting display mode\n", This);
4762 * Stateblock related functions
4765 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4766 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4767 IWineD3DStateBlockImpl *object;
4768 TRACE("(%p)", This);
4770 if (This->isRecordingState) {
4771 return D3DERR_INVALIDCALL;
4774 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4775 if (NULL == object ) {
4776 FIXME("(%p)Error allocating memory for stateblock\n", This);
4777 return E_OUTOFMEMORY;
4779 TRACE("(%p) creted object %p\n", This, object);
4780 object->wineD3DDevice= This;
4781 /** FIXME: object->parent = parent; **/
4782 object->parent = NULL;
4783 object->blockType = WINED3DSBT_ALL;
4785 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
4787 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4788 This->updateStateBlock = object;
4789 This->isRecordingState = TRUE;
4791 TRACE("(%p) recording stateblock %p\n",This , object);
4795 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4796 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4798 if (!This->isRecordingState) {
4799 FIXME("(%p) not recording! returning error\n", This);
4800 *ppStateBlock = NULL;
4801 return D3DERR_INVALIDCALL;
4804 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4805 This->isRecordingState = FALSE;
4806 This->updateStateBlock = This->stateBlock;
4807 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4808 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4809 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4814 * Scene related functions
4816 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4817 /* At the moment we have no need for any functionality at the beginning
4819 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4820 TRACE("(%p) : stub\n", This);
4824 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4825 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4826 TRACE("(%p)\n", This);
4828 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4830 checkGLcall("glFlush");
4832 TRACE("End Scene\n");
4833 if(This->renderTarget != NULL) {
4835 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4836 IUnknown *targetContainer = NULL;
4837 if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
4838 || D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
4839 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
4840 /** always dirtify for now. we must find a better way to see that surface have been modified
4841 (Modifications should will only occur via draw-primitive, but we do need better locking
4842 switching to render-to-texture should remove the overhead though.
4844 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4845 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
4846 IWineD3DSurface_PreLoad(This->renderTarget);
4847 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4848 IUnknown_Release(targetContainer);
4851 This->sceneEnded = TRUE;
4856 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4857 CONST RECT* pSourceRect, CONST RECT* pDestRect,
4858 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4859 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4860 IWineD3DSwapChain *swapChain = NULL;
4862 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4864 TRACE("(%p) Presenting the frame\n", This);
4866 for(i = 0 ; i < swapchains ; i ++) {
4868 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4869 TRACE("presentinng chain %d, %p\n", i, swapChain);
4870 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4871 IWineD3DSwapChain_Release(swapChain);
4877 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4878 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4879 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4881 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4882 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4883 when the depth-buffer format does not contain stencil buffer information, this method fails. */
4884 GLbitfield glMask = 0;
4885 GLboolean old_ztest;
4886 GLfloat old_z_clear_value;
4887 GLint old_stencil_clear_value;
4888 GLfloat old_color_clear_value[4];
4890 CONST D3DRECT* curRect;
4892 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4893 Count, pRects, Flags, Z, Stencil);
4897 glEnable(GL_SCISSOR_TEST);
4898 checkGLcall("glEnable GL_SCISSOR_TEST");
4900 if (Count > 0 && pRects) {
4906 /* Only set the values up once, as they are not changing */
4907 if (Flags & D3DCLEAR_STENCIL) {
4908 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4909 glClearStencil(Stencil);
4910 checkGLcall("glClearStencil");
4911 glMask = glMask | GL_STENCIL_BUFFER_BIT;
4912 glStencilMask(0xFFFFFFFF);
4915 if (Flags & D3DCLEAR_ZBUFFER) {
4916 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4917 glDepthMask(GL_TRUE);
4918 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4920 checkGLcall("glClearDepth");
4921 glMask = glMask | GL_DEPTH_BUFFER_BIT;
4924 if (Flags & D3DCLEAR_TARGET) {
4925 TRACE("Clearing screen with glClear to color %lx\n", Color);
4926 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4927 glClearColor(D3DCOLOR_R(Color),
4931 checkGLcall("glClearColor");
4933 /* Clear ALL colors! */
4934 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4935 glMask = glMask | GL_COLOR_BUFFER_BIT;
4938 /* Now process each rect in turn */
4939 for (i = 0; i < Count || i == 0; i++) {
4942 /* Note gl uses lower left, width/height */
4943 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4944 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4945 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4946 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4947 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4948 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4949 checkGLcall("glScissor");
4951 glScissor(This->stateBlock->viewport.X,
4952 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
4953 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4954 This->stateBlock->viewport.Width,
4955 This->stateBlock->viewport.Height);
4956 checkGLcall("glScissor");
4959 /* Clear the selected rectangle (or full screen) */
4961 checkGLcall("glClear");
4963 /* Step to the next rectangle */
4964 if (curRect) curRect = curRect + sizeof(D3DRECT);
4967 /* Restore the old values (why..?) */
4968 if (Flags & D3DCLEAR_STENCIL) {
4969 glClearStencil(old_stencil_clear_value);
4970 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4972 if (Flags & D3DCLEAR_ZBUFFER) {
4973 glDepthMask(old_ztest);
4974 glClearDepth(old_z_clear_value);
4976 if (Flags & D3DCLEAR_TARGET) {
4977 glClearColor(old_color_clear_value[0],
4978 old_color_clear_value[1],
4979 old_color_clear_value[2],
4980 old_color_clear_value[3]);
4981 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4982 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4983 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4984 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4987 glDisable(GL_SCISSOR_TEST);
4988 checkGLcall("glDisable");
4997 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4998 UINT PrimitiveCount) {
5000 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5001 This->stateBlock->streamIsUP = FALSE;
5003 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
5004 debug_d3dprimitivetype(PrimitiveType),
5005 StartVertex, PrimitiveCount);
5006 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
5007 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
5013 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
5014 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
5015 D3DPRIMITIVETYPE PrimitiveType,
5016 INT baseVIndex, UINT minIndex,
5017 UINT NumVertices, UINT startIndex, UINT primCount) {
5019 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5021 IWineD3DIndexBuffer *pIB;
5022 D3DINDEXBUFFER_DESC IdxBufDsc;
5024 pIB = This->stateBlock->pIndexData;
5025 This->stateBlock->streamIsUP = FALSE;
5027 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
5028 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5029 minIndex, NumVertices, startIndex, baseVIndex, primCount);
5031 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
5032 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
5038 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
5039 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
5044 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
5045 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
5046 UINT VertexStreamZeroStride) {
5047 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5049 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
5050 debug_d3dprimitivetype(PrimitiveType),
5051 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
5053 /* release the stream source */
5054 if (This->stateBlock->streamSource[0] != NULL) {
5055 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5058 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5059 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5060 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5061 This->stateBlock->streamIsUP = TRUE;
5063 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
5064 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
5065 /* stream zero settings set to null at end, as per the msdn
5066 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
5068 This->stateBlock->streamStride[0] = 0;
5069 This->stateBlock->streamSource[0] = NULL;
5071 /*stream zero settings set to null at end, as per the msdn */
5075 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
5076 UINT MinVertexIndex, UINT NumVertices,
5077 UINT PrimitiveCount, CONST void* pIndexData,
5078 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
5079 UINT VertexStreamZeroStride) {
5081 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5083 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
5084 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5085 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
5086 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
5088 if (IndexDataFormat == WINED3DFMT_INDEX16) {
5094 /* release the stream and index data */
5095 if (This->stateBlock->streamSource[0] != NULL) {
5096 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5098 if (This->stateBlock->pIndexData) {
5099 IWineD3DIndexBuffer_Release(This->stateBlock->pIndexData);
5102 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5103 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5104 This->stateBlock->streamIsUP = TRUE;
5105 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5107 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
5108 /* stream zero settings set to null at end as per the msdn
5109 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
5112 /* stream zero settings set to null at end as per the msdn */
5113 This->stateBlock->streamSource[0] = NULL;
5114 This->stateBlock->streamStride[0] = 0;
5119 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
5120 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
5121 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5122 HRESULT hr = D3D_OK;
5123 D3DRESOURCETYPE sourceType;
5124 D3DRESOURCETYPE destinationType;
5127 /* TODO: think about moving the code into IWineD3DBaseTexture */
5129 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
5131 /* verify that the source and destination textures aren't NULL */
5132 if (NULL == pSourceTexture || NULL == pDestinationTexture) {
5133 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning D3DERR_INVALIDCALL\n",
5134 This, pSourceTexture, pDestinationTexture);
5135 hr = D3DERR_INVALIDCALL;
5138 if (pSourceTexture == pDestinationTexture) {
5139 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning D3DERR_INVALIDCALL\n",
5140 This, pSourceTexture, pDestinationTexture);
5141 hr = D3DERR_INVALIDCALL;
5143 /* Verify that the source and destination textures are the same type */
5144 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
5145 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
5147 if (sourceType != destinationType) {
5148 WARN("(%p) Sorce and destination types must match, returning D3DERR_INVALIDCALL\n",
5150 hr = D3DERR_INVALIDCALL;
5153 /* check that both textures have the identical numbers of levels */
5154 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
5155 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning D3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
5156 hr = D3DERR_INVALIDCALL;
5161 /* Make sure that the destination texture is loaded */
5162 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
5164 /* Update every surface level of the texture */
5165 levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
5167 switch (sourceType) {
5168 case D3DRTYPE_TEXTURE:
5170 IWineD3DSurface *srcSurface;
5171 IWineD3DSurface *destSurface;
5173 for (i = 0 ; i < levels ; ++i) {
5174 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture, i, &srcSurface);
5175 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
5176 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5177 IWineD3DSurface_Release(srcSurface);
5178 IWineD3DSurface_Release(destSurface);
5180 WARN("(%p) : Call to update surface failed\n", This);
5186 case D3DRTYPE_CUBETEXTURE:
5188 IWineD3DSurface *srcSurface;
5189 IWineD3DSurface *destSurface;
5190 D3DCUBEMAP_FACES faceType;
5192 for (i = 0 ; i < levels ; ++i) {
5193 /* Update each cube face */
5194 for (faceType = D3DCUBEMAP_FACE_POSITIVE_X; faceType <= D3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
5195 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture, faceType, i, &srcSurface);
5197 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5199 TRACE("Got srcSurface %p\n", srcSurface);
5201 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
5203 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5205 TRACE("Got desrSurface %p\n", destSurface);
5207 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5208 IWineD3DSurface_Release(srcSurface);
5209 IWineD3DSurface_Release(destSurface);
5211 WARN("(%p) : Call to update surface failed\n", This);
5218 #if 0 /* TODO: Add support for volume textures */
5219 case D3DRTYPE_VOLUMETEXTURE:
5221 IWineD3DVolume srcVolume = NULL;
5222 IWineD3DSurface destVolume = NULL;
5224 for (i = 0 ; i < levels ; ++i) {
5225 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture, i, &srcVolume);
5226 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
5227 hr = IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
5228 IWineD3DVolume_Release(srcSurface);
5229 IWineD3DVolume_Release(destSurface);
5231 WARN("(%p) : Call to update volume failed\n", This);
5239 FIXME("(%p) : Unsupported source and destination type\n", This);
5240 hr = D3DERR_INVALIDCALL;
5247 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
5248 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
5249 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
5250 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5252 TRACE("(%p) : stub\n", This);
5255 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
5256 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5257 /** TODO: remove remove casts to IWineD3DSurfaceImpl *
5258 * NOTE It may be best to move the code into surface to occomplish this
5259 ****************************************/
5261 WINED3DSURFACE_DESC surfaceDesc;
5262 unsigned int surfaceWidth, surfaceHeight;
5263 glDescriptor *targetGlDescription = NULL;
5264 glDescriptor *surfaceGlDescription = NULL;
5265 IWineD3DSwapChainImpl *container = NULL;
5267 IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
5268 IWineD3DSurface_GetGlDesc(pSurface, &surfaceGlDescription);
5269 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5271 surfaceDesc.Width = &surfaceWidth;
5272 surfaceDesc.Height = &surfaceHeight;
5273 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5274 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
5276 /* Ok, I may need to setup some kind of active swapchain reference on the device */
5277 IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
5279 /* TODO: opengl Context switching for swapchains etc... */
5280 if (NULL != container || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
5281 if (NULL != container && (pRenderTarget == container->backBuffer)) {
5282 glReadBuffer(GL_BACK);
5283 vcheckGLcall("glReadBuffer(GL_BACK)");
5284 } else if ((NULL != container && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
5285 glReadBuffer(GL_FRONT);
5286 vcheckGLcall("glReadBuffer(GL_FRONT)");
5287 } else if (pRenderTarget == This->depthStencilBuffer) {
5288 FIXME("Reading of depthstencil not yet supported\n");
5291 glReadPixels(surfaceGlDescription->target,
5292 surfaceGlDescription->level,
5295 surfaceGlDescription->glFormat,
5296 surfaceGlDescription->glType,
5297 (void *)IWineD3DSurface_GetData(pSurface));
5298 vcheckGLcall("glReadPixels(...)");
5299 if(NULL != container ){
5300 IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
5303 IWineD3DBaseTexture *container;
5304 GLenum textureDimensions = GL_TEXTURE_2D;
5306 if (D3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
5307 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
5308 IWineD3DBaseTexture_Release(container);
5310 /* TODO: 2D -> Cube surface coppies etc.. */
5311 if (surfaceGlDescription->target != textureDimensions) {
5312 FIXME("(%p) : Texture dimension mismatch\n", This);
5314 glEnable(textureDimensions);
5315 vcheckGLcall("glEnable(GL_TEXTURE_...)");
5316 /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
5317 glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
5318 vcheckGLcall("glBindTexture");
5319 glGetTexImage(surfaceGlDescription->target,
5320 surfaceGlDescription->level,
5321 surfaceGlDescription->glFormat,
5322 surfaceGlDescription->glType,
5323 (void *)IWineD3DSurface_GetData(pSurface));
5324 glDisable(textureDimensions);
5325 vcheckGLcall("glDisable(GL_TEXTURE_...)");
5332 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
5333 IWineD3DSwapChain *swapChain;
5335 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5337 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
5338 IWineD3DSwapChain_Release(swapChain);
5343 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5344 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5345 /* return a sensible default */
5347 /* TODO: If the window is minimized then validate device should return something other than d3d_ok */
5348 FIXME("(%p) : stub\n", This);
5352 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5353 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5355 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5356 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5357 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5358 return D3DERR_INVALIDCALL;
5360 for (j = 0; j < 256; ++j) {
5361 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
5362 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5363 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
5364 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5366 TRACE("(%p) : returning\n", This);
5370 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5371 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5373 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5374 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5375 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5376 return D3DERR_INVALIDCALL;
5378 for (j = 0; j < 256; ++j) {
5379 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
5380 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5381 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
5382 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5384 TRACE("(%p) : returning\n", This);
5388 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5389 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5390 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5391 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5392 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5393 return D3DERR_INVALIDCALL;
5395 /*TODO: stateblocks */
5396 This->currentPalette = PaletteNumber;
5397 TRACE("(%p) : returning\n", This);
5401 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
5402 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5403 if (PaletteNumber == NULL) {
5404 WARN("(%p) : returning Invalid Call\n", This);
5405 return D3DERR_INVALIDCALL;
5407 /*TODO: stateblocks */
5408 *PaletteNumber = This->currentPalette;
5409 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
5413 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
5414 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5415 static BOOL showFixmes = TRUE;
5417 FIXME("(%p) : stub\n", This);
5421 This->softwareVertexProcessing = bSoftware;
5426 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
5427 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5428 static BOOL showFixmes = TRUE;
5430 FIXME("(%p) : stub\n", This);
5433 return This->softwareVertexProcessing;
5437 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
5438 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5439 IWineD3DSwapChain *swapChain;
5442 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
5444 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5446 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
5447 IWineD3DSwapChain_Release(swapChain);
5449 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
5455 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
5456 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5457 static BOOL showfixmes = TRUE;
5458 if(nSegments != 0.0f) {
5460 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
5467 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
5468 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5469 static BOOL showfixmes = TRUE;
5471 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
5477 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
5478 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5479 /** TODO: remove casts to IWineD3DSurfaceImpl
5480 * NOTE: move code to surface to accomplish this
5481 ****************************************/
5482 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
5483 int srcWidth, srcHeight;
5484 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
5485 WINED3DFORMAT destFormat, srcFormat;
5487 int destLeft, destTop;
5488 D3DPOOL srcPool, destPool;
5490 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
5491 glDescriptor *glDescription = NULL;
5492 GLenum textureDimensions = GL_TEXTURE_2D;
5493 IWineD3DBaseTexture *baseTexture;
5495 WINED3DSURFACE_DESC winedesc;
5497 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
5498 memset(&winedesc, 0, sizeof(winedesc));
5499 winedesc.Width = &srcSurfaceWidth;
5500 winedesc.Height = &srcSurfaceHeight;
5501 winedesc.Pool = &srcPool;
5502 winedesc.Format = &srcFormat;
5504 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5506 winedesc.Width = &destSurfaceWidth;
5507 winedesc.Height = &destSurfaceHeight;
5508 winedesc.Pool = &destPool;
5509 winedesc.Format = &destFormat;
5510 winedesc.Size = &destSize;
5512 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5514 if(srcPool != D3DPOOL_SYSTEMMEM || destPool != D3DPOOL_DEFAULT){
5515 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning D3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
5516 return D3DERR_INVALIDCALL;
5519 if (destFormat == WINED3DFMT_UNKNOWN) {
5520 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5521 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5523 /* Get the update surface description */
5524 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5527 /* Make sure the surface is loaded and up to date */
5528 IWineD3DSurface_PreLoad(pDestinationSurface);
5530 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
5534 /* this needs to be done in lines if the sourceRect != the sourceWidth */
5535 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
5536 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
5537 destLeft = pDestPoint ? pDestPoint->x : 0;
5538 destTop = pDestPoint ? pDestPoint->y : 0;
5541 /* This function doesn't support compressed textures
5542 the pitch is just bytesPerPixel * width */
5543 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
5544 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
5545 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
5546 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
5548 /* TODO DXT formats */
5550 if(pSourceRect != NULL && pSourceRect->top != 0){
5551 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
5553 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
5555 ,glDescription->level
5560 ,glDescription->glFormat
5561 ,glDescription->glType
5562 ,IWineD3DSurface_GetData(pSourceSurface)
5566 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
5568 /* need to lock the surface to get the data */
5569 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5572 /* TODO: Cube and volume support */
5574 /* not a whole row so we have to do it a line at a time */
5577 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
5578 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5580 for(j = destTop ; j < (srcHeight + destTop) ; j++){
5582 glTexSubImage2D(glDescription->target
5583 ,glDescription->level
5588 ,glDescription->glFormat
5589 ,glDescription->glType
5590 ,data /* could be quicker using */
5595 } else { /* Full width, so just write out the whole texture */
5597 if (WINED3DFMT_DXT1 == destFormat ||
5598 WINED3DFMT_DXT2 == destFormat ||
5599 WINED3DFMT_DXT3 == destFormat ||
5600 WINED3DFMT_DXT4 == destFormat ||
5601 WINED3DFMT_DXT5 == destFormat) {
5602 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
5603 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
5604 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
5605 FIXME("Updating part of a compressed texture is not supported at the moment\n");
5606 } if (destFormat != srcFormat) {
5607 FIXME("Updating mixed format compressed texture is not curretly support\n");
5609 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
5610 glDescription->level,
5611 glDescription->glFormatInternal,
5616 IWineD3DSurface_GetData(pSourceSurface));
5619 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
5624 if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
5626 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
5627 to repack the data from pow2Width/Height to expected Width,Height, this makes the
5628 data returned by GetData non-power2 width/height with hardware non-power2
5629 pow2Width/height are set to surface width height, repacking isn't needed so it
5630 doesn't matter which function gets called. */
5631 glTexSubImage2D(glDescription->target
5632 ,glDescription->level
5637 ,glDescription->glFormat
5638 ,glDescription->glType
5639 ,IWineD3DSurface_GetData(pSourceSurface)
5643 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
5644 glTexSubImage2D(glDescription->target
5645 ,glDescription->level
5648 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
5649 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
5650 ,glDescription->glFormat
5651 ,glDescription->glType
5652 ,IWineD3DSurface_GetData(pSourceSurface)
5658 checkGLcall("glTexSubImage2D");
5660 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
5661 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
5662 * surface bigger than it needs to be hmm.. */
5663 if (D3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
5664 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
5665 IWineD3DBaseTexture_Release(baseTexture);
5668 glDisable(textureDimensions); /* This needs to be managed better.... */
5674 /* Used by DirectX 8 */
5675 HRESULT WINAPI IWineD3DDeviceImpl_CopyRects(IWineD3DDevice *iface,
5676 IWineD3DSurface* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
5677 IWineD3DSurface* pDestinationSurface, CONST POINT* pDestPointsArray) {
5679 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5680 HRESULT hr = D3D_OK;
5681 WINED3DFORMAT srcFormat, destFormat;
5682 UINT srcWidth, destWidth;
5683 UINT srcHeight, destHeight;
5685 WINED3DSURFACE_DESC winedesc;
5687 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
5688 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
5691 /* Check that the source texture is in D3DPOOL_SYSTEMMEM and the destination texture is in D3DPOOL_DEFAULT */
5692 memset(&winedesc, 0, sizeof(winedesc));
5694 winedesc.Format = &srcFormat;
5695 winedesc.Width = &srcWidth;
5696 winedesc.Height = &srcHeight;
5697 winedesc.Size = &srcSize;
5698 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5700 winedesc.Format = &destFormat;
5701 winedesc.Width = &destWidth;
5702 winedesc.Height = &destHeight;
5703 winedesc.Size = NULL;
5704 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5706 /* Check that the source and destination formats match */
5707 if (srcFormat != destFormat && WINED3DFMT_UNKNOWN != destFormat) {
5708 WARN("(%p) source %p format must match the dest %p format, returning D3DERR_INVALIDCALL\n", This, pSourceSurface, pDestinationSurface);
5709 return D3DERR_INVALIDCALL;
5710 } else if (WINED3DFMT_UNKNOWN == destFormat) {
5711 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5712 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5713 destFormat = srcFormat;
5716 /* Quick if complete copy ... */
5717 if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
5719 if (srcWidth == destWidth && srcHeight == destHeight) {
5720 D3DLOCKED_RECT lrSrc;
5721 D3DLOCKED_RECT lrDst;
5722 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, NULL, D3DLOCK_READONLY);
5723 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, NULL, 0L);
5724 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", srcWidth, srcHeight);
5726 memcpy(lrDst.pBits, lrSrc.pBits, srcSize);
5728 IWineD3DSurface_UnlockRect(pSourceSurface);
5729 IWineD3DSurface_UnlockRect(pDestinationSurface);
5730 TRACE("Unlocked src and dst\n");
5734 FIXME("Wanted to copy all surfaces but size not compatible, returning D3DERR_INVALIDCALL\n");
5735 hr = D3DERR_INVALIDCALL;
5740 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
5742 int bytesPerPixel = ((IWineD3DSurfaceImpl *) pSourceSurface)->bytesPerPixel;
5745 /* Copy rect by rect */
5746 for (i = 0; i < cRects; ++i) {
5747 CONST RECT* r = &pSourceRectsArray[i];
5748 CONST POINT* p = &pDestPointsArray[i];
5751 D3DLOCKED_RECT lrSrc;
5752 D3DLOCKED_RECT lrDst;
5755 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
5756 if (srcFormat == WINED3DFMT_DXT1) {
5757 copyperline = ((r->right - r->left) * bytesPerPixel) / 2; /* DXT1 is half byte per pixel */
5759 copyperline = ((r->right - r->left) * bytesPerPixel);
5762 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, r, D3DLOCK_READONLY);
5763 dest_rect.left = p->x;
5764 dest_rect.top = p->y;
5765 dest_rect.right = p->x + (r->right - r->left);
5766 dest_rect.bottom= p->y + (r->bottom - r->top);
5767 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, &dest_rect, 0L);
5768 TRACE("Locked src and dst\n");
5770 /* Find where to start */
5771 for (j = 0; j < (r->bottom - r->top - 1); ++j) {
5772 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
5774 IWineD3DSurface_UnlockRect(pSourceSurface);
5775 IWineD3DSurface_UnlockRect(pDestinationSurface);
5776 TRACE("Unlocked src and dst\n");
5779 FIXME("Wanted to copy partial surfaces not implemented, returning D3DERR_INVALIDCALL\n");
5780 hr = D3DERR_INVALIDCALL;
5787 /* Implementation details at http://developer.nvidia.com/attach/6494
5789 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
5790 hmm.. no longer supported use
5791 OpenGL evaluators or tessellate surfaces within your application.
5794 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
5795 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
5796 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5797 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
5798 FIXME("(%p) : Stub\n", This);
5803 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
5804 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
5805 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5806 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
5807 FIXME("(%p) : Stub\n", This);
5811 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5812 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5813 TRACE("(%p) Handle(%d)\n", This, Handle);
5814 FIXME("(%p) : Stub\n", This);
5818 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
5819 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
5820 fill a surface with a block of color! */
5821 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5822 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
5823 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
5824 IWineD3DSwapChainImpl *container = NULL;
5825 BOOL isRenderTarget = FALSE;
5826 unsigned int width, height;
5827 unsigned int top, left;
5830 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
5832 if (surface->resource.pool != D3DPOOL_DEFAULT) {
5833 FIXME("call to colorfill with non D3DPOOL_DEFAULT surface\n");
5834 return D3DERR_INVALIDCALL;
5837 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
5838 if (D3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
5839 if (D3DUSAGE_RENDERTARGET & surface->resource.usage) {
5840 /* TODO: make sure we set everything back to the way it was, and context management!
5841 glGetIntegerv(GL_READ_BUFFER, &prev_read);
5842 vcheckGLcall("glIntegerv");
5843 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
5844 vcheckGLcall("glIntegerv");
5846 TRACE("Color fill to render targets may cause some graphics issues\n");
5847 if (pSurface == container->frontBuffer) {
5848 glDrawBuffer(GL_FRONT);
5850 glDrawBuffer(GL_BACK);
5853 if (D3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
5854 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld\n", surface, surface->resource.usage);
5856 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
5858 if (container != NULL) {
5859 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5861 /* we can use GL_STENCIL_INDEX etc...*/
5864 if (container != NULL) {
5865 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5867 isRenderTarget = TRUE;
5869 /* TODO: drawing to GL_FRONT and GL_BACK */
5870 /* TODO: see if things can be speeded up by using the correct
5871 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
5872 if (pRect == NULL) {
5875 width = surface->currentDesc.Width;
5876 height = surface->currentDesc.Height;
5880 width = pRect->x2 - left;
5881 height = pRect->y2 - top;
5884 data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
5885 /* Create a 'line' of color color, in the correct format for the surface */
5886 for (u = 0 ; u < width ; u ++) {
5891 if (isRenderTarget == FALSE) {
5892 glDescriptor *glDesc;
5893 IWineD3DSurface_PreLoad(pSurface);
5895 /* draw a block of the coloured line on the sufrace */
5896 IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
5897 for (v = 0 ; v< height;v++) {
5898 glTexSubImage2D(glDesc->target
5899 ,glDesc->level /* level */
5909 checkGLcall("glTexSubImage2D");
5911 glDisable(glDesc->target);
5913 /** FIXME: Using GLClear may be faster **/
5914 glRasterPos2i(left, top);
5915 glPixelZoom((float)width ,(float)height);
5916 glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
5917 checkGLcall("glDrawPixels");
5919 HeapFree(GetProcessHeap(), 0, data);
5925 /* rendertarget and deptth stencil functions */
5926 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
5927 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5929 /* FIXME: Implelent RenderTargetIndex >0 */
5930 if(RenderTargetIndex > 0)
5931 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
5933 *ppRenderTarget = This->renderTarget;
5934 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
5935 /* Note inc ref on returned surface */
5936 if(*ppRenderTarget != NULL)
5937 IWineD3DSurface_AddRef(*ppRenderTarget);
5941 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5942 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5943 *ppZStencilSurface = This->depthStencilBuffer;
5944 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
5946 if(*ppZStencilSurface != NULL) {
5947 /* Note inc ref on returned surface */
5948 IWineD3DSurface_AddRef(*ppZStencilSurface);
5953 /* internal static helper functions */
5954 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5955 IWineD3DSurface *RenderSurface);
5957 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5958 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5959 HRESULT hr = D3D_OK;
5960 WINED3DVIEWPORT viewport;
5962 TRACE("(%p) Swapping rendertarget\n",This);
5963 if (RenderTargetIndex > 0) {
5964 FIXME("(%p) Render targets other than the first are not supported\n",This);
5965 RenderTargetIndex = 0;
5968 /* MSDN says that null disables the render target
5969 but a device must always be associated with a render target
5970 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5972 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5975 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5976 FIXME("Trying to set render target 0 to NULL\n");
5977 return D3DERR_INVALIDCALL;
5979 /* TODO: replace Impl* usage with interface usage */
5980 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & D3DUSAGE_RENDERTARGET) {
5981 FIXME("(%p)Trying to set the render target to a surface(%p) that wasn't created with a usage of D3DUSAGE_RENDERTARGET\n",This ,pRenderTarget);
5982 return D3DERR_INVALIDCALL;
5984 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
5985 * builds, but I think wine counts as a 'debug' build for now.
5986 ******************************/
5987 /* If we are trying to set what we already have, don't bother */
5988 if (pRenderTarget == This->renderTarget) {
5989 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5991 /* Otherwise, set the render target up */
5993 if (FALSE == This->sceneEnded) {
5994 IWineD3DDevice_EndScene(iface);
5996 TRACE("clearing renderer\n");
5997 /* IWineD3DDeviceImpl_CleanRender(iface); */
5998 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5999 depending on the renter target implementation being used.
6000 A shared context implementation will share all buffers between all rendertargets (including swapchains),
6001 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6002 stencil buffer and incure an extra memory overhead */
6003 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
6006 if (SUCCEEDED(hr)) {
6007 /* Finally, reset the viewport as the MSDN states. */
6008 /* TODO: Replace impl usage */
6009 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
6010 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
6013 viewport.MaxZ = 1.0f;
6014 viewport.MinZ = 0.0f;
6015 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
6017 FIXME("Unknown error setting the render target\n");
6019 This->sceneEnded = FALSE;
6023 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
6024 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6025 HRESULT hr = D3D_OK;
6026 IWineD3DSurface *tmp;
6028 TRACE("(%p) Swapping z-buffer\n",This);
6030 if (pNewZStencil == This->stencilBufferTarget) {
6031 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6033 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6034 * depending on the renter target implementation being used.
6035 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
6036 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6037 * stencil buffer and incure an extra memory overhead
6038 ******************************************************/
6041 tmp = This->stencilBufferTarget;
6042 This->stencilBufferTarget = pNewZStencil;
6043 /* should we be calling the parent or the wined3d surface? */
6044 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
6045 if (NULL != tmp) IWineD3DSurface_Release(tmp);
6047 /** TODO: glEnable/glDisable on depth/stencil depending on
6048 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
6049 **********************************************************/
6056 #ifdef GL_VERSION_1_3
6057 /* Internal functions not in DirectX */
6058 /** TODO: move this off to the opengl context manager
6059 *(the swapchain doesn't need to know anything about offscreen rendering!)
6060 ****************************************************/
6062 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
6064 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6066 TRACE("(%p), %p\n", This, swapchain);
6068 if (swapchain->win != swapchain->drawable) {
6069 /* Set everything back the way it ws */
6070 swapchain->render_ctx = swapchain->glCtx;
6071 swapchain->drawable = swapchain->win;
6076 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
6077 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
6078 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6081 unsigned int height;
6082 WINED3DFORMAT format;
6083 WINED3DSURFACE_DESC surfaceDesc;
6084 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
6085 surfaceDesc.Width = &width;
6086 surfaceDesc.Height = &height;
6087 surfaceDesc.Format = &format;
6088 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
6090 /* I need a get width/height function (and should do something with the format) */
6091 for (i = 0; i < CONTEXT_CACHE; ++i) {
6092 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
6093 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
6094 the pSurface can be set to 0 allowing it to be reused from cache **/
6095 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
6096 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
6097 *context = &This->contextCache[i];
6100 if (This->contextCache[i].Width == 0) {
6101 This->contextCache[i].pSurface = pSurface;
6102 This->contextCache[i].Width = width;
6103 This->contextCache[i].Height = height;
6104 *context = &This->contextCache[i];
6108 if (i == CONTEXT_CACHE) {
6109 int minUsage = 0x7FFFFFFF; /* MAX_INT */
6110 glContext *dropContext = 0;
6111 for (i = 0; i < CONTEXT_CACHE; i++) {
6112 if (This->contextCache[i].usedcount < minUsage) {
6113 dropContext = &This->contextCache[i];
6114 minUsage = This->contextCache[i].usedcount;
6117 /* clean up the context (this doesn't work for ATI at the moment */
6119 glXDestroyContext(swapchain->display, dropContext->context);
6120 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
6123 dropContext->Width = 0;
6124 dropContext->pSurface = pSurface;
6125 *context = dropContext;
6127 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
6128 for (i = 0; i < CONTEXT_CACHE; i++) {
6129 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
6133 if (*context != NULL)
6136 return E_OUTOFMEMORY;
6140 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
6141 * the functionality needs splitting up so that we don't do more than we should do.
6142 * this only seems to impact performance a little.
6143 ******************************/
6144 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
6145 IWineD3DSurface *RenderSurface) {
6146 HRESULT ret = D3DERR_INVALIDCALL;
6149 * Currently only active for GLX >= 1.3
6150 * for others versions we'll have to use GLXPixmaps
6152 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
6153 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
6154 * so only check OpenGL version
6155 * ..........................
6156 * I don't believe that it is a problem with NVidia headers,
6157 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
6158 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
6160 * Your application will report GLX version 1.2 on glXQueryVersion.
6161 * However, it is safe to call the GLX 1.3 functions as described below.
6163 #if defined(GL_VERSION_1_3)
6165 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6166 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
6167 IWineD3DSurface *tmp;
6168 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
6169 GLXFBConfig* cfgs = NULL;
6173 IWineD3DSwapChain *currentSwapchain;
6174 IWineD3DSwapChainImpl *swapchain;
6175 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
6176 * but switch them off if the StencilSurface is set to NULL
6177 ** *********************************************************/
6178 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
6179 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
6182 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
6183 it StencilSurface != NULL && zBufferTarget == NULL switch it on
6186 #define PUSH1(att) attribs[nAttribs++] = (att);
6187 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
6189 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
6191 /** TODO: remove the reff to Impl (context manager should fix this!) **/
6192 IWineD3DSwapChainImpl *impSwapChain;
6193 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
6194 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
6195 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
6200 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
6201 PUSH2(GLX_X_RENDERABLE, TRUE);
6202 PUSH2(GLX_DOUBLEBUFFER, TRUE);
6203 TRACE("calling makeglcfg\n");
6204 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
6207 TRACE("calling chooseFGConfig\n");
6208 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
6211 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
6212 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
6213 why we failed and only show this message once! */
6214 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"); /**/
6216 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
6217 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
6218 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
6219 PUSH2(GLX_DOUBLEBUFFER, FALSE);
6220 TRACE("calling makeglcfg\n");
6221 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
6223 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
6230 for (i = 0; i < nCfgs; ++i) {
6231 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
6232 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
6233 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
6236 if (NULL != This->renderTarget) {
6238 vcheckGLcall("glFlush");
6239 /** This is only useful if the old render target was a swapchain,
6240 * we need to supercede this with a function that displays
6241 * the current buffer on the screen. This is easy to do in glx1.3 but
6242 * we need to do copy-write pixels in glx 1.2.
6243 ************************************************/
6244 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
6246 printf("Hit Enter to get next frame ...\n");
6252 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain) != D3D_OK) {
6253 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
6254 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
6258 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
6259 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
6260 **********************************************************************/
6261 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == D3D_OK) {
6262 /* We also need to make sure that the lights &co are also in the context of the swapchains */
6263 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
6264 TRACE("making swapchain active\n");
6265 if (RenderSurface != This->renderTarget) {
6266 if (RenderSurface == swapchain->backBuffer) {
6268 /* This could be flagged so that some operations work directly with the front buffer */
6269 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
6271 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
6273 TRACE("Error in setting current context: context %p drawable %ld !\n",
6274 impSwapChain->glCtx, impSwapChain->win);
6277 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
6279 checkGLcall("glXMakeContextCurrent");
6281 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
6283 else if (pbuffer_support == TRUE && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
6285 /** ********************************************************************
6286 * This is a quickly hacked out implementation of offscreen textures.
6287 * It will work in most cases but there may be problems if the client
6288 * modifies the texture directly, or expects the contents of the rendertarget
6291 * There are some real speed vs compatibility issues here:
6292 * we should really use a new context for every texture, but that eats ram.
6293 * we should also be restoring the texture to the pbuffer but that eats CPU
6294 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
6295 * but if this means reusing the display backbuffer then we need to make sure that
6296 * states are correctly preserved.
6297 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
6298 * and gain a good performance increase at the cost of compatibility.
6299 * I would suggest that, when this is the case, a user configurable flag be made
6300 * available, allowing the user to choose the best emulated experience for them.
6301 *********************************************************************/
6303 XVisualInfo *visinfo;
6304 glContext *newContext;
6306 /* Here were using a shared context model */
6307 if (D3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
6308 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6311 /* If the context doesn't exist then create a new one */
6312 /* TODO: This should really be part of findGlContext */
6313 if (NULL == newContext->context) {
6315 TRACE("making new buffer\n");
6317 PUSH2(GLX_PBUFFER_WIDTH, newContext->Width);
6318 PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
6321 newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
6323 /** ****************************************
6324 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
6326 * In future releases, we may provide the calls glXCreateNewContext,
6327 * glXQueryDrawable and glXMakeContextCurrent.
6328 * so until then we have to use glXGetVisualFromFBConfig &co..
6329 ********************************************/
6332 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
6334 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
6336 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
6340 if (NULL == newContext || NULL == newContext->context) {
6341 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6343 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
6344 if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
6345 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
6348 /* Clean up the old context */
6349 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
6350 /* Set the current context of the swapchain to the new context */
6351 impSwapChain->drawable = newContext->drawable;
6352 impSwapChain->render_ctx = newContext->context;
6356 #if 1 /* Apply the stateblock to the new context
6357 FIXME: This is a bit of a hack, each context should know it's own state,
6358 the directX current directX state should then be applied to the context */
6361 IWineD3DStateBlockImpl *oldUpdateStateBlock;
6362 oldUpdateStateBlock = This->updateStateBlock;
6363 oldRecording= This->isRecordingState;
6364 This->isRecordingState = FALSE;
6365 This->updateStateBlock = This->stateBlock;
6366 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
6368 This->isRecordingState = oldRecording;
6369 This->updateStateBlock = oldUpdateStateBlock;
6374 /* clean up the current rendertargets swapchain (if it belonged to one) */
6375 if (currentSwapchain != NULL) {
6376 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
6379 /* Were done with the opengl context management, setup the rendertargets */
6381 tmp = This->renderTarget;
6382 This->renderTarget = RenderSurface;
6383 IWineD3DSurface_AddRef(This->renderTarget);
6384 IWineD3DSurface_Release(tmp);
6390 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
6391 /* Check that the container is not a swapchain member */
6393 IWineD3DSwapChain *tmpSwapChain;
6394 if (D3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
6395 This->renderUpsideDown = TRUE;
6397 This->renderUpsideDown = FALSE;
6398 IWineD3DSwapChain_Release(tmpSwapChain);
6400 /* Force updating the cull mode */
6401 TRACE("setting render state\n");
6402 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
6403 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
6405 /* Force updating projection matrix */
6406 This->last_was_rhw = FALSE;
6407 This->proj_valid = FALSE;
6415 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
6416 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
6421 if ( NULL != impSwapChain) {
6422 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
6430 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
6431 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
6432 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6433 /* TODO: the use of Impl is deprecated. */
6434 /* some basic validation checks */
6435 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
6437 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
6439 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
6440 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
6441 return D3DERR_INVALIDCALL;
6443 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
6444 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
6445 return D3DERR_INVALIDCALL;
6447 /* TODO: make the cursor 'real' */
6449 This->xHotSpot = XHotSpot;
6450 This->yHotSpot = YHotSpot;
6455 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
6456 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6457 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
6459 This->xScreenSpace = XScreenSpace;
6460 This->yScreenSpace = YScreenSpace;
6466 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
6467 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6468 TRACE("(%p) : visible(%d)\n", This, bShow);
6470 This->bCursorVisible = bShow;
6475 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
6476 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6477 TRACE("(%p) : state (%lu)\n", This, This->state);
6478 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
6479 switch (This->state) {
6482 case D3DERR_DEVICELOST:
6484 ResourceList *resourceList = This->resources;
6485 while (NULL != resourceList) {
6486 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == D3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
6487 return D3DERR_DEVICENOTRESET;
6488 resourceList = resourceList->next;
6490 return D3DERR_DEVICELOST;
6492 case D3DERR_DRIVERINTERNALERROR:
6493 return D3DERR_DRIVERINTERNALERROR;
6497 return D3DERR_DRIVERINTERNALERROR;
6501 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
6502 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6503 /** FIXME: Resource tracking needs to be done,
6504 * The closes we can do to this is set the priorities of all managed textures low
6505 * and then reset them.
6506 ***********************************************************/
6507 FIXME("(%p) : stub\n", This);
6511 HRESULT WINAPI IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
6512 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6513 /** FIXME: Resource trascking needs to be done.
6514 * in effect this pulls all non only default
6515 * textures out of video memory and deletes all glTextures (glDeleteTextures)
6516 * and should clear down the context and set it up according to pPresentationParameters
6517 ***********************************************************/
6518 FIXME("(%p) : stub\n", This);
6522 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
6523 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6524 /** FIXME: always true at the moment **/
6525 if(bEnableDialogs == FALSE) {
6526 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
6532 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
6533 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6535 FIXME("(%p) : stub\n", This);
6536 /* Setup some reasonable defaults */
6537 pParameters->AdapterOrdinal = 0; /* always for now */
6538 pParameters->DeviceType = D3DDEVTYPE_HAL; /* always for now */
6539 pParameters->hFocusWindow = 0;
6540 pParameters->BehaviorFlags =0;
6544 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
6545 IWineD3DSwapChain *swapchain;
6546 HRESULT hrc = D3D_OK;
6548 TRACE("Relaying to swapchain\n");
6550 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
6551 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (D3DGAMMARAMP *)pRamp);
6552 IWineD3DSwapChain_Release(swapchain);
6557 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
6558 IWineD3DSwapChain *swapchain;
6559 HRESULT hrc = D3D_OK;
6561 TRACE("Relaying to swapchain\n");
6563 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
6564 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
6565 IWineD3DSwapChain_Release(swapchain);
6571 /** ********************************************************
6572 * Notification functions
6573 ** ********************************************************/
6574 /** This function must be called in the release of a resource when ref == 0,
6575 * the contents of resource must still be correct,
6576 * any handels to other resource held by the caller must be closed
6577 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
6578 *****************************************************/
6579 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6580 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6581 ResourceList* resourceList;
6583 TRACE("(%p) : resource %p\n", This, resource);
6585 EnterCriticalSection(&resourceStoreCriticalSection);
6587 /* add a new texture to the frot of the linked list */
6588 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
6589 resourceList->resource = resource;
6591 /* Get the old head */
6592 resourceList->next = This->resources;
6594 This->resources = resourceList;
6595 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
6598 LeaveCriticalSection(&resourceStoreCriticalSection);
6603 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6604 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6605 ResourceList* resourceList = NULL;
6606 ResourceList* previousResourceList = NULL;
6608 TRACE("(%p) : resource %p\n", This, resource);
6611 EnterCriticalSection(&resourceStoreCriticalSection);
6613 resourceList = This->resources;
6615 while (resourceList != NULL) {
6616 if(resourceList->resource == resource) break;
6617 previousResourceList = resourceList;
6618 resourceList = resourceList->next;
6621 if (resourceList == NULL) {
6622 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
6624 LeaveCriticalSection(&resourceStoreCriticalSection);
6628 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
6630 /* make sure we don't leave a hole in the list */
6631 if (previousResourceList != NULL) {
6632 previousResourceList->next = resourceList->next;
6634 This->resources = resourceList->next;
6638 LeaveCriticalSection(&resourceStoreCriticalSection);
6644 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
6645 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6648 TRACE("(%p) : resource %p\n", This, resource);
6649 switch(IWineD3DResource_GetType(resource)){
6650 case D3DRTYPE_SURFACE:
6651 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
6653 case D3DRTYPE_TEXTURE:
6654 case D3DRTYPE_CUBETEXTURE:
6655 case D3DRTYPE_VOLUMETEXTURE:
6656 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
6657 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6658 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6659 This->stateBlock->textures[counter] = NULL;
6661 if (This->updateStateBlock != This->stateBlock ){
6662 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6663 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6664 This->updateStateBlock->textures[counter] = NULL;
6669 case D3DRTYPE_VOLUME:
6670 /* TODO: nothing really? */
6672 case D3DRTYPE_VERTEXBUFFER:
6673 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
6676 TRACE("Cleaning up stream pointers\n");
6678 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
6679 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
6680 FINDOUT: should changes.streamSource[StreamNumber] be set ?
6682 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6683 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
6684 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
6685 This->updateStateBlock->streamSource[streamNumber] = 0;
6686 /* Set changed flag? */
6689 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) */
6690 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
6691 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
6692 This->stateBlock->streamSource[streamNumber] = 0;
6695 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
6696 else { /* This shouldn't happen */
6697 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
6704 case D3DRTYPE_INDEXBUFFER:
6705 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
6706 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6707 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6708 This->updateStateBlock->pIndexData = NULL;
6711 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
6712 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6713 This->stateBlock->pIndexData = NULL;
6719 FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
6724 /* Remove the resoruce from the resourceStore */
6725 IWineD3DDeviceImpl_RemoveResource(iface, resource);
6727 TRACE("Resource released\n");
6732 /** This function is to be called by the swapchain when it is released and it's ref = 0
6733 *****************************************************/
6734 void WINAPI IWineD3DDeviceImpl_SwapChainReleased(IWineD3DDevice *iface, IWineD3DSwapChain *swapChain){
6735 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6736 SwapChainList **nextSwapchain;
6737 nextSwapchain = &This->swapchains;
6739 /* Check to see if the swapchian is being used as the render target */
6740 if (This->renderTarget != NULL) {
6741 IWineD3DSurface *swapchainBackBuffer;
6743 IWineD3DSwapChain_GetBackBuffer(swapChain, 0 ,( D3DBACKBUFFER_TYPE) 0, &swapchainBackBuffer);
6744 if (This->renderTarget == swapchainBackBuffer) {
6745 /* Don't know what to do, so warn and carry on as usual (which in this case leaves the renderterget in limbo) */
6746 FIXME("Atempting to release a swapchain that is currently beuing used as a render target, behaviour is undefined\n");
6750 /* Go through the swapchain list and try to find the swapchain being released */
6751 while(*nextSwapchain != NULL && (*nextSwapchain)->swapchain != swapChain) {
6752 nextSwapchain = &(*nextSwapchain)->next;
6755 /* Check to see if we found the swapchain */
6756 if (NULL != *nextSwapchain) {
6757 /* We found the swapchain so remove it from the list */
6758 TRACE("(%p) releasing swapchain(%p)\n", iface, swapChain);
6759 HeapFree(GetProcessHeap(), 0 , *nextSwapchain);
6760 *nextSwapchain = (*nextSwapchain)->next;
6762 /* We didn't find the swapchain on the list, this can only heppen because of a programming error in wined3d */
6763 FIXME("(%p) Attempting to release a swapchain (%p) that hasn't been stored\n", iface, swapChain);
6766 TRACE("swapchain (%p) released\n", swapChain);
6770 /**********************************************************
6771 * IWineD3DDevice VTbl follows
6772 **********************************************************/
6774 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
6776 /*** IUnknown methods ***/
6777 IWineD3DDeviceImpl_QueryInterface,
6778 IWineD3DDeviceImpl_AddRef,
6779 IWineD3DDeviceImpl_Release,
6780 /*** IWineD3DDevice methods ***/
6781 IWineD3DDeviceImpl_GetParent,
6782 /*** Creation methods**/
6783 IWineD3DDeviceImpl_CreateVertexBuffer,
6784 IWineD3DDeviceImpl_CreateIndexBuffer,
6785 IWineD3DDeviceImpl_CreateStateBlock,
6786 IWineD3DDeviceImpl_CreateSurface,
6787 IWineD3DDeviceImpl_CreateTexture,
6788 IWineD3DDeviceImpl_CreateVolumeTexture,
6789 IWineD3DDeviceImpl_CreateVolume,
6790 IWineD3DDeviceImpl_CreateCubeTexture,
6791 IWineD3DDeviceImpl_CreateQuery,
6792 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
6793 IWineD3DDeviceImpl_CreateVertexDeclaration,
6794 IWineD3DDeviceImpl_CreateVertexShader,
6795 IWineD3DDeviceImpl_CreatePixelShader,
6796 /*** Odd functions **/
6797 IWineD3DDeviceImpl_EvictManagedResources,
6798 IWineD3DDeviceImpl_GetAvailableTextureMem,
6799 IWineD3DDeviceImpl_GetBackBuffer,
6800 IWineD3DDeviceImpl_GetCreationParameters,
6801 IWineD3DDeviceImpl_GetDeviceCaps,
6802 IWineD3DDeviceImpl_GetDirect3D,
6803 IWineD3DDeviceImpl_GetDisplayMode,
6804 IWineD3DDeviceImpl_GetNumberOfSwapChains,
6805 IWineD3DDeviceImpl_GetRasterStatus,
6806 IWineD3DDeviceImpl_GetSwapChain,
6807 IWineD3DDeviceImpl_Reset,
6808 IWineD3DDeviceImpl_SetDialogBoxMode,
6809 IWineD3DDeviceImpl_SetCursorProperties,
6810 IWineD3DDeviceImpl_SetCursorPosition,
6811 IWineD3DDeviceImpl_ShowCursor,
6812 IWineD3DDeviceImpl_TestCooperativeLevel,
6813 /*** Getters and setters **/
6814 IWineD3DDeviceImpl_SetClipPlane,
6815 IWineD3DDeviceImpl_GetClipPlane,
6816 IWineD3DDeviceImpl_SetClipStatus,
6817 IWineD3DDeviceImpl_GetClipStatus,
6818 IWineD3DDeviceImpl_SetCurrentTexturePalette,
6819 IWineD3DDeviceImpl_GetCurrentTexturePalette,
6820 IWineD3DDeviceImpl_SetDepthStencilSurface,
6821 IWineD3DDeviceImpl_GetDepthStencilSurface,
6822 IWineD3DDeviceImpl_SetFVF,
6823 IWineD3DDeviceImpl_GetFVF,
6824 IWineD3DDeviceImpl_SetGammaRamp,
6825 IWineD3DDeviceImpl_GetGammaRamp,
6826 IWineD3DDeviceImpl_SetIndices,
6827 IWineD3DDeviceImpl_GetIndices,
6828 IWineD3DDeviceImpl_SetLight,
6829 IWineD3DDeviceImpl_GetLight,
6830 IWineD3DDeviceImpl_SetLightEnable,
6831 IWineD3DDeviceImpl_GetLightEnable,
6832 IWineD3DDeviceImpl_SetMaterial,
6833 IWineD3DDeviceImpl_GetMaterial,
6834 IWineD3DDeviceImpl_SetNPatchMode,
6835 IWineD3DDeviceImpl_GetNPatchMode,
6836 IWineD3DDeviceImpl_SetPaletteEntries,
6837 IWineD3DDeviceImpl_GetPaletteEntries,
6838 IWineD3DDeviceImpl_SetPixelShader,
6839 IWineD3DDeviceImpl_GetPixelShader,
6840 IWineD3DDeviceImpl_SetPixelShaderConstant,
6841 IWineD3DDeviceImpl_GetPixelShaderConstant,
6842 IWineD3DDeviceImpl_SetPixelShaderConstantB,
6843 IWineD3DDeviceImpl_GetPixelShaderConstantB,
6844 IWineD3DDeviceImpl_SetPixelShaderConstantI,
6845 IWineD3DDeviceImpl_GetPixelShaderConstantI,
6846 IWineD3DDeviceImpl_SetPixelShaderConstantF,
6847 IWineD3DDeviceImpl_GetPixelShaderConstantF,
6848 IWineD3DDeviceImpl_SetPixelShaderConstantN,
6849 IWineD3DDeviceImpl_SetRenderState,
6850 IWineD3DDeviceImpl_GetRenderState,
6851 IWineD3DDeviceImpl_SetRenderTarget,
6852 IWineD3DDeviceImpl_GetRenderTarget,
6853 IWineD3DDeviceImpl_SetSamplerState,
6854 IWineD3DDeviceImpl_GetSamplerState,
6855 IWineD3DDeviceImpl_SetScissorRect,
6856 IWineD3DDeviceImpl_GetScissorRect,
6857 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
6858 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
6859 IWineD3DDeviceImpl_SetStreamSource,
6860 IWineD3DDeviceImpl_GetStreamSource,
6861 IWineD3DDeviceImpl_SetStreamSourceFreq,
6862 IWineD3DDeviceImpl_GetStreamSourceFreq,
6863 IWineD3DDeviceImpl_SetTexture,
6864 IWineD3DDeviceImpl_GetTexture,
6865 IWineD3DDeviceImpl_SetTextureStageState,
6866 IWineD3DDeviceImpl_GetTextureStageState,
6867 IWineD3DDeviceImpl_SetTransform,
6868 IWineD3DDeviceImpl_GetTransform,
6869 IWineD3DDeviceImpl_SetVertexDeclaration,
6870 IWineD3DDeviceImpl_GetVertexDeclaration,
6871 IWineD3DDeviceImpl_SetVertexShader,
6872 IWineD3DDeviceImpl_GetVertexShader,
6873 IWineD3DDeviceImpl_SetVertexShaderConstant,
6874 IWineD3DDeviceImpl_GetVertexShaderConstant,
6875 IWineD3DDeviceImpl_SetVertexShaderConstantB,
6876 IWineD3DDeviceImpl_GetVertexShaderConstantB,
6877 IWineD3DDeviceImpl_SetVertexShaderConstantI,
6878 IWineD3DDeviceImpl_GetVertexShaderConstantI,
6879 IWineD3DDeviceImpl_SetVertexShaderConstantF,
6880 IWineD3DDeviceImpl_GetVertexShaderConstantF,
6881 IWineD3DDeviceImpl_SetVertexShaderConstantN,
6882 IWineD3DDeviceImpl_SetViewport,
6883 IWineD3DDeviceImpl_GetViewport,
6884 IWineD3DDeviceImpl_MultiplyTransform,
6885 IWineD3DDeviceImpl_ValidateDevice,
6886 IWineD3DDeviceImpl_ProcessVertices,
6887 /*** State block ***/
6888 IWineD3DDeviceImpl_BeginStateBlock,
6889 IWineD3DDeviceImpl_EndStateBlock,
6890 /*** Scene management ***/
6891 IWineD3DDeviceImpl_BeginScene,
6892 IWineD3DDeviceImpl_EndScene,
6893 IWineD3DDeviceImpl_Present,
6894 IWineD3DDeviceImpl_Clear,
6896 IWineD3DDeviceImpl_DrawPrimitive,
6897 IWineD3DDeviceImpl_DrawIndexedPrimitive,
6898 IWineD3DDeviceImpl_DrawPrimitiveUP,
6899 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
6900 IWineD3DDeviceImpl_DrawRectPatch,
6901 IWineD3DDeviceImpl_DrawTriPatch,
6902 IWineD3DDeviceImpl_DeletePatch,
6903 IWineD3DDeviceImpl_ColorFill,
6904 IWineD3DDeviceImpl_UpdateTexture,
6905 IWineD3DDeviceImpl_UpdateSurface,
6906 IWineD3DDeviceImpl_CopyRects,
6907 IWineD3DDeviceImpl_StretchRect,
6908 IWineD3DDeviceImpl_GetRenderTargetData,
6909 IWineD3DDeviceImpl_GetFrontBufferData,
6910 /*** Internal use IWineD3DDevice methods ***/
6911 IWineD3DDeviceImpl_SetupTextureStates,
6912 /*** object tracking ***/
6913 IWineD3DDeviceImpl_SwapChainReleased,
6914 IWineD3DDeviceImpl_ResourceReleased
6918 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
6919 WINED3DRS_ALPHABLENDENABLE ,
6920 WINED3DRS_ALPHAFUNC ,
6921 WINED3DRS_ALPHAREF ,
6922 WINED3DRS_ALPHATESTENABLE ,
6924 WINED3DRS_COLORWRITEENABLE ,
6925 WINED3DRS_DESTBLEND ,
6926 WINED3DRS_DITHERENABLE ,
6927 WINED3DRS_FILLMODE ,
6928 WINED3DRS_FOGDENSITY ,
6930 WINED3DRS_FOGSTART ,
6931 WINED3DRS_LASTPIXEL ,
6932 WINED3DRS_SHADEMODE ,
6933 WINED3DRS_SRCBLEND ,
6934 WINED3DRS_STENCILENABLE ,
6935 WINED3DRS_STENCILFAIL ,
6936 WINED3DRS_STENCILFUNC ,
6937 WINED3DRS_STENCILMASK ,
6938 WINED3DRS_STENCILPASS ,
6939 WINED3DRS_STENCILREF ,
6940 WINED3DRS_STENCILWRITEMASK ,
6941 WINED3DRS_STENCILZFAIL ,
6942 WINED3DRS_TEXTUREFACTOR ,
6953 WINED3DRS_ZWRITEENABLE
6956 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
6957 WINED3DTSS_ADDRESSW ,
6958 WINED3DTSS_ALPHAARG0 ,
6959 WINED3DTSS_ALPHAARG1 ,
6960 WINED3DTSS_ALPHAARG2 ,
6961 WINED3DTSS_ALPHAOP ,
6962 WINED3DTSS_BUMPENVLOFFSET ,
6963 WINED3DTSS_BUMPENVLSCALE ,
6964 WINED3DTSS_BUMPENVMAT00 ,
6965 WINED3DTSS_BUMPENVMAT01 ,
6966 WINED3DTSS_BUMPENVMAT10 ,
6967 WINED3DTSS_BUMPENVMAT11 ,
6968 WINED3DTSS_COLORARG0 ,
6969 WINED3DTSS_COLORARG1 ,
6970 WINED3DTSS_COLORARG2 ,
6971 WINED3DTSS_COLOROP ,
6972 WINED3DTSS_RESULTARG ,
6973 WINED3DTSS_TEXCOORDINDEX ,
6974 WINED3DTSS_TEXTURETRANSFORMFLAGS
6977 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
6978 WINED3DSAMP_ADDRESSU ,
6979 WINED3DSAMP_ADDRESSV ,
6980 WINED3DSAMP_ADDRESSW ,
6981 WINED3DSAMP_BORDERCOLOR ,
6982 WINED3DSAMP_MAGFILTER ,
6983 WINED3DSAMP_MINFILTER ,
6984 WINED3DSAMP_MIPFILTER ,
6985 WINED3DSAMP_MIPMAPLODBIAS ,
6986 WINED3DSAMP_MAXMIPLEVEL ,
6987 WINED3DSAMP_MAXANISOTROPY ,
6988 WINED3DSAMP_SRGBTEXTURE ,
6989 WINED3DSAMP_ELEMENTINDEX
6992 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
6994 WINED3DRS_AMBIENTMATERIALSOURCE ,
6995 WINED3DRS_CLIPPING ,
6996 WINED3DRS_CLIPPLANEENABLE ,
6997 WINED3DRS_COLORVERTEX ,
6998 WINED3DRS_DIFFUSEMATERIALSOURCE ,
6999 WINED3DRS_EMISSIVEMATERIALSOURCE ,
7000 WINED3DRS_FOGDENSITY ,
7002 WINED3DRS_FOGSTART ,
7003 WINED3DRS_FOGTABLEMODE ,
7004 WINED3DRS_FOGVERTEXMODE ,
7005 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
7006 WINED3DRS_LIGHTING ,
7007 WINED3DRS_LOCALVIEWER ,
7008 WINED3DRS_MULTISAMPLEANTIALIAS ,
7009 WINED3DRS_MULTISAMPLEMASK ,
7010 WINED3DRS_NORMALIZENORMALS ,
7011 WINED3DRS_PATCHEDGESTYLE ,
7012 WINED3DRS_POINTSCALE_A ,
7013 WINED3DRS_POINTSCALE_B ,
7014 WINED3DRS_POINTSCALE_C ,
7015 WINED3DRS_POINTSCALEENABLE ,
7016 WINED3DRS_POINTSIZE ,
7017 WINED3DRS_POINTSIZE_MAX ,
7018 WINED3DRS_POINTSIZE_MIN ,
7019 WINED3DRS_POINTSPRITEENABLE ,
7020 WINED3DRS_RANGEFOGENABLE ,
7021 WINED3DRS_SPECULARMATERIALSOURCE ,
7022 WINED3DRS_TWEENFACTOR ,
7023 WINED3DRS_VERTEXBLEND
7026 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
7027 WINED3DTSS_TEXCOORDINDEX ,
7028 WINED3DTSS_TEXTURETRANSFORMFLAGS
7031 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
7032 WINED3DSAMP_DMAPOFFSET