2 * IWineD3DDevice implementation
4 * Copyright 2002-2005 Jason Edmeades
5 * Copyright 2003-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include "wined3d_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
31 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
33 /* x11drv GDI escapes */
34 #define X11DRV_ESCAPE 6789
35 enum x11drv_escape_codes
37 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
38 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
39 X11DRV_GET_FONT, /* get current X font for a DC */
42 /* retrieve the X display to use on a given DC */
43 inline static Display *get_display( HDC hdc )
46 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
48 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
49 sizeof(display), (LPSTR)&display )) display = NULL;
53 /* Memory tracking and object counting */
54 static unsigned int emulated_textureram = 64*1024*1024;
56 /* TODO: setup some flags in the regestry to enable, disable pbuffer support */
57 /* enable pbuffer support for offscreen textures */
58 BOOL pbuffer_support = FALSE;
59 /* allocate one pbuffer per surface */
60 BOOL pbuffer_per_surface = FALSE;
62 /* static function declarations */
63 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
65 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type);
68 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return WINED3DERR_OUTOFVIDEOMEMORY;}
70 #define D3DCREATEOBJECTINSTANCE(object, type) { \
71 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
72 D3DMEMCHECK(object, pp##type); \
73 object->lpVtbl = &IWineD3D##type##_Vtbl; \
74 object->wineD3DDevice = This; \
75 object->parent = parent; \
77 *pp##type = (IWineD3D##type *) object; \
80 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
81 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
82 D3DMEMCHECK(object, pp##type); \
83 object->lpVtbl = &IWineD3D##type##_Vtbl; \
84 object->resource.wineD3DDevice = This; \
85 object->resource.parent = parent; \
86 object->resource.resourceType = d3dtype; \
87 object->resource.ref = 1; \
88 object->resource.pool = Pool; \
89 object->resource.format = Format; \
90 object->resource.usage = Usage; \
91 object->resource.size = _size; \
92 /* Check that we have enough video ram left */ \
93 if (Pool == WINED3DPOOL_DEFAULT) { \
94 if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
95 WARN("Out of 'bogus' video memory\n"); \
96 HeapFree(GetProcessHeap(), 0, object); \
98 return WINED3DERR_OUTOFVIDEOMEMORY; \
100 globalChangeGlRam(_size); \
102 object->resource.allocatedMemory = (0 == _size ? NULL : Pool == WINED3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
103 if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != WINED3DPOOL_DEFAULT) { \
104 FIXME("Out of memory!\n"); \
105 HeapFree(GetProcessHeap(), 0, object); \
107 return WINED3DERR_OUTOFVIDEOMEMORY; \
109 *pp##type = (IWineD3D##type *) object; \
110 IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
111 TRACE("(%p) : Created resource %p\n", This, object); \
114 #define D3DINITIALIZEBASETEXTURE(_basetexture) { \
115 _basetexture.levels = Levels; \
116 _basetexture.filterType = (Usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE; \
117 _basetexture.LOD = 0; \
118 _basetexture.dirty = TRUE; \
121 /**********************************************************
122 * Global variable / Constants follow
123 **********************************************************/
124 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
126 /**********************************************************
127 * Utility functions follow
128 **********************************************************/
129 /* Convert the D3DLIGHT properties into equivalent gl lights */
130 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
133 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
134 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
136 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
137 glMatrixMode(GL_MODELVIEW);
139 glLoadMatrixf((float *)&This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
142 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
143 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
144 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
145 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
146 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
147 checkGLcall("glLightfv");
150 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
151 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
152 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
153 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
154 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
155 checkGLcall("glLightfv");
158 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
159 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
160 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
161 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
162 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
163 checkGLcall("glLightfv");
165 /* Attenuation - Are these right? guessing... */
166 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
167 checkGLcall("glLightf");
168 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
169 checkGLcall("glLightf");
171 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
172 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
174 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
177 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
178 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
179 checkGLcall("glLightf");
181 switch (lightInfo->OriginalParms.Type) {
184 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
185 checkGLcall("glLightfv");
186 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
187 checkGLcall("glLightf");
193 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
194 checkGLcall("glLightfv");
196 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
197 checkGLcall("glLightfv");
198 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
199 checkGLcall("glLightf");
200 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
201 checkGLcall("glLightf");
205 case D3DLIGHT_DIRECTIONAL:
207 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
208 checkGLcall("glLightfv");
209 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
210 checkGLcall("glLightf");
211 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
212 checkGLcall("glLightf");
216 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
219 /* Restore the modelview matrix */
223 /* Apply the current values to the specified texture stage */
224 void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Sampler, DWORD Flags) {
225 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
233 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
234 clamping, MIPLOD, etc. This will work for up to 16 samplers.
237 if (Sampler >= GL_LIMITS(samplers)) {
238 FIXME("Trying to set the state of more samplers %ld than are supported %d by this openGL implementation\n", Sampler, GL_LIMITS(samplers));
241 VTRACE(("Activating appropriate texture state %ld\n", Sampler));
242 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
244 GLACTIVETEXTURE(Sampler);
246 /* Could we use bindTexture and then apply the states instead of GLACTIVETEXTURE */
247 } else if (Sampler > 0) {
248 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
252 /* TODO: change this to a lookup table
253 LOOKUP_TEXTURE_STATES lists all texture states that should be applied.
254 LOOKUP_CONTEXT_SATES list all context applicable states that can be applied
255 etc.... it's a lot cleaner, quicker and possibly easier to maintain than running a switch and setting a skip flag...
256 especially when there are a number of groups of states. */
258 TRACE("-----------------------> Updating the texture at Sampler %ld to have new texture state information\n", Sampler);
260 /* The list of states not to apply is a big as the list of states to apply, so it makes sense to produce an inclusive list */
261 #define APPLY_STATE(_state) IWineD3DDeviceImpl_ApplyTextureUnitState(iface, Sampler, _state)
262 /* these are the only two supported states that need to be applied */
263 APPLY_STATE(WINED3DTSS_TEXCOORDINDEX);
264 APPLY_STATE(WINED3DTSS_TEXTURETRANSFORMFLAGS);
265 #if 0 /* not supported at the moment */
266 APPLY_STATE(WINED3DTSS_BUMPENVMAT00);
267 APPLY_STATE(WINED3DTSS_BUMPENVMAT01);
268 APPLY_STATE(WINED3DTSS_BUMPENVMAT10);
269 APPLY_STATE(WINED3DTSS_BUMPENVMAT11);
270 APPLY_STATE(WINED3DTSS_BUMPENVLSCALE);
271 APPLY_STATE(WINED3DTSS_BUMPENVLOFFSET);
272 APPLY_STATE(WINED3DTSS_RESULTARG);
273 APPLY_STATE(WINED3DTSS_CONSTANT);
275 /* a quick sanity check in case someone forgot to update this function */
276 if (WINED3D_HIGHEST_TEXTURE_STATE > WINED3DTSS_CONSTANT) {
277 FIXME("(%p) : There are more texture states than expected, update device.c to match\n", This);
281 /* apply any sampler states that always need applying */
282 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
283 tmpvalue.d = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPMAPLODBIAS];
284 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
285 GL_TEXTURE_LOD_BIAS_EXT,
287 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
290 /* Note the D3DRS value applies to all textures, but GL has one
291 * per texture, so apply it now ready to be used!
293 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
294 /* Set the default alpha blend color */
295 glBlendColor(col[0], col[1], col[2], col[3]);
296 checkGLcall("glBlendColor");
298 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
299 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
300 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
302 /* TODO: NV_POINT_SPRITE */
303 if (GL_SUPPORT(ARB_POINT_SPRITE)) {
304 if (This->stateBlock->renderState[WINED3DRS_POINTSPRITEENABLE] != FALSE) {
305 /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
306 glDisable(GL_POINT_SMOOTH);
308 /* Centre the texture on the vertex */
309 VTRACE("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
310 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
312 VTRACE("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
313 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
314 checkGLcall("glTexEnvf(...)");
315 VTRACE("glEnable( GL_POINT_SPRITE_ARB )\n");
316 glEnable( GL_POINT_SPRITE_ARB );
317 checkGLcall("glEnable(...)");
319 VTRACE("glDisable( GL_POINT_SPRITE_ARB )\n");
320 glDisable( GL_POINT_SPRITE_ARB );
321 checkGLcall("glEnable(...)");
325 TRACE("-----------------------> Updated the texture at Sampler %ld to have new texture state information\n", Sampler);
328 /**********************************************************
329 * IUnknown parts follows
330 **********************************************************/
332 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
334 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
336 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
337 if (IsEqualGUID(riid, &IID_IUnknown)
338 || IsEqualGUID(riid, &IID_IWineD3DBase)
339 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
340 IUnknown_AddRef(iface);
345 return E_NOINTERFACE;
348 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
349 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
350 ULONG refCount = InterlockedIncrement(&This->ref);
352 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
356 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
357 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
358 ULONG refCount = InterlockedDecrement(&This->ref);
360 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
363 /* TODO: Clean up all the surfaces and textures! */
364 /* FIXME: Create targets and state blocks in d3d8 */
365 if (((IWineD3DImpl *)This->wineD3D)->dxVersion >= 8) { /*We don't create state blocks for d3d7 yet*/
366 /* NOTE: You must release the parent if the object was created via a callback
367 ** ***************************/
368 /* TODO: this is exactly the same as required by _Reset.., so at some point we need to move the code so that is can be called by reset add release... */
369 /* Release all of the swapchains, except the implicit swapchain */
370 IUnknown* stencilBufferParent;
371 IUnknown* swapChainParent;
373 /* NOTE: Don't release swapchain 0 here, it's 'special' */
374 SwapChainList *nextSwapchain = This->swapchains;
375 if (nextSwapchain != NULL) {
376 nextSwapchain = nextSwapchain->next;
378 WARN("Expected to find the implicit swapchain\n");
381 /* release all the other swapchains */
382 while (nextSwapchain != NULL) {
383 SwapChainList *prevSwapchain = nextSwapchain;
384 nextSwapchain = nextSwapchain->next;
385 IWineD3DSwapChain_Release(prevSwapchain->swapchain);
386 /* NOTE: no need to free the list element, it will be done by the release callback
387 HeapFree(GetProcessHeap(), 0, prevSwapchain); */
389 /* Release the buffers (with sanity checks)*/
390 if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
391 if(This->depthStencilBuffer != This->stencilBufferTarget)
392 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
394 This->stencilBufferTarget = NULL;
396 if(IWineD3DSurface_Release(This->renderTarget) >0){
397 /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
399 This->renderTarget = NULL;
401 IWineD3DSurface_GetParent(This->depthStencilBuffer, &stencilBufferParent);
402 IUnknown_Release(stencilBufferParent); /* once for the get parent */
403 if(IUnknown_Release(stencilBufferParent) >0){ /* the second time for when it was created */
404 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
406 This->depthStencilBuffer = NULL;
408 /* Release the update stateblock */
409 if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){
410 if(This->updateStateBlock != This->stateBlock)
411 FIXME("(%p) Something's still holding the Update stateblock\n",This);
413 This->updateStateBlock = NULL;
414 { /* because were not doing proper internal refcounts releasing the primary state block
415 causes recursion with the extra checks in ResourceReleased, to avoid this we have
416 to set this->stateBlock = NULL; first */
417 IWineD3DStateBlock *stateBlock = (IWineD3DStateBlock *)This->stateBlock;
418 This->stateBlock = NULL;
420 /* Release the stateblock */
421 if(IWineD3DStateBlock_Release(stateBlock) > 0){
422 FIXME("(%p) Something's still holding the Update stateblock\n",This);
426 if (This->swapchains != NULL) {
427 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
428 IWineD3DSwapChain_GetParent(This->swapchains->swapchain, &swapChainParent);
429 IUnknown_Release(swapChainParent); /* once for the get parent */
430 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
431 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
435 if (This->resources != NULL ) {
436 FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This);
437 dumpResources(This->resources);
441 IWineD3D_Release(This->wineD3D);
442 This->wineD3D = NULL;
443 HeapFree(GetProcessHeap(), 0, This);
444 TRACE("Freed device %p\n", This);
450 /**********************************************************
451 * IWineD3DDevice implementation follows
452 **********************************************************/
453 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
454 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
455 *pParent = This->parent;
456 IUnknown_AddRef(This->parent);
460 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
461 DWORD FVF, WINED3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
463 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
464 IWineD3DVertexBufferImpl *object;
465 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
466 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, WINED3DRTYPE_VERTEXBUFFER, Size)
469 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
470 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
474 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
475 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
480 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
481 WINED3DFORMAT Format, WINED3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
482 HANDLE *sharedHandle, IUnknown *parent) {
483 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
484 IWineD3DIndexBufferImpl *object;
485 TRACE("(%p) Creating index buffer\n", This);
487 /* Allocate the storage for the device */
488 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,WINED3DRTYPE_INDEXBUFFER, Length)
491 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
492 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
495 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
496 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
497 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
502 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
504 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
505 IWineD3DStateBlockImpl *object;
508 D3DCREATEOBJECTINSTANCE(object, StateBlock)
509 object->blockType = Type;
511 /* Special case - Used during initialization to produce a placeholder stateblock
512 so other functions called can update a state block */
513 if (Type == WINED3DSBT_INIT) {
514 /* Don't bother increasing the reference count otherwise a device will never
515 be freed due to circular dependencies */
519 /* Otherwise, might as well set the whole state block to the appropriate values */
520 if ( This->stateBlock != NULL) {
521 memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
523 memset(object->streamFreq, 1, sizeof(object->streamFreq));
526 /* Reset the ref and type after kludging it */
527 object->wineD3DDevice = This;
529 object->blockType = Type;
531 TRACE("Updating changed flags appropriate for type %d\n", Type);
533 if (Type == WINED3DSBT_ALL) {
535 TRACE("ALL => Pretend everything has changed\n");
536 memset(&object->changed, TRUE, sizeof(This->stateBlock->changed));
537 } else if (Type == WINED3DSBT_PIXELSTATE) {
539 TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
540 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
542 object->changed.pixelShader = TRUE;
544 /* Pixel Shader Constants */
545 for (i = 0; i < MAX_PSHADER_CONSTANTS; ++i) {
546 object->changed.pixelShaderConstants[i] = TRUE;
548 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
549 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
551 for (j = 0; j < GL_LIMITS(textures); j++) {
552 for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
553 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
556 for (j = 0 ; j < 16; j++) {
557 for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
559 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
563 } else if (Type == WINED3DSBT_VERTEXSTATE) {
565 TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
566 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
568 object->changed.vertexShader = TRUE;
570 /* Vertex Shader Constants */
571 for (i = 0; i < MAX_VSHADER_CONSTANTS; ++i) {
572 object->changed.vertexShaderConstants[i] = TRUE;
574 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
575 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
577 for (j = 0; j < GL_LIMITS(textures); j++) {
578 for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
579 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
582 for (j = 0 ; j < 16; j++){
583 for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
584 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
588 /* Duplicate light chain */
590 PLIGHTINFOEL *src = NULL;
591 PLIGHTINFOEL *dst = NULL;
592 PLIGHTINFOEL *newEl = NULL;
593 src = This->stateBlock->lights;
594 object->lights = NULL;
598 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
599 if (newEl == NULL) return WINED3DERR_OUTOFVIDEOMEMORY;
600 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
602 newEl->changed = TRUE;
603 newEl->enabledChanged = TRUE;
605 object->lights = newEl;
616 FIXME("Unrecognized state block type %d\n", Type);
619 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
624 /* ************************************
626 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
629 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
631 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.
633 ******************************** */
635 HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height, WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **ppSurface,WINED3DRESOURCETYPE Type, DWORD Usage, WINED3DPOOL Pool, WINED3DMULTISAMPLE_TYPE MultiSample ,DWORD MultisampleQuality, HANDLE* pSharedHandle, WINED3DSURFTYPE Impl, IUnknown *parent) {
636 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
637 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
638 unsigned int pow2Width, pow2Height;
639 unsigned int Size = 1;
640 TRACE("(%p) Create surface\n",This);
642 /** FIXME: Check ranges on the inputs are valid
645 * [in] Quality level. The valid range is between zero and one less than the level
646 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
647 * Passing a larger value returns the error WINED3DERR_INVALIDCALL. The MultisampleQuality
648 * values of paired render targets, depth stencil surfaces, and the MultiSample type
650 *******************************/
655 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
657 * If this flag is set, the contents of the depth stencil buffer will be
658 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
659 * with a different depth surface.
661 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
662 ***************************/
664 if(MultisampleQuality < 0) {
665 FIXME("Invalid multisample level %ld\n", MultisampleQuality);
666 return WINED3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
669 if(MultisampleQuality > 0) {
670 FIXME("MultisampleQuality set to %ld, substituting 0\n", MultisampleQuality);
671 MultisampleQuality=0;
674 /** FIXME: Check that the format is supported
676 *******************************/
678 /* Non-power2 support */
680 /* Find the nearest pow2 match */
681 pow2Width = pow2Height = 1;
682 while (pow2Width < Width) pow2Width <<= 1;
683 while (pow2Height < Height) pow2Height <<= 1;
685 if (pow2Width > Width || pow2Height > Height) {
686 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
687 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
688 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
689 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
690 This, Width, Height);
691 return WINED3DERR_NOTAVAILABLE;
695 /** Check against the maximum texture sizes supported by the video card **/
696 if (pow2Width > GL_LIMITS(texture_size) || pow2Height > GL_LIMITS(texture_size)) {
697 /* one of three options
698 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)
699 2: Set the texture to the maxium size (bad idea)
700 3: WARN and return WINED3DERR_NOTAVAILABLE;
702 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));
703 return WINED3DERR_NOTAVAILABLE;
708 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
709 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
711 *********************************/
712 if (WINED3DFMT_UNKNOWN == Format) {
714 } else if (Format == WINED3DFMT_DXT1) {
715 /* DXT1 is half byte per pixel */
716 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4)) >> 1;
718 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
719 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
720 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4));
722 Size = (pow2Width * D3DFmtGetBpp(This, Format)) * pow2Height;
725 /** Create and initialise the surface resource **/
726 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,WINED3DRTYPE_SURFACE, Size)
727 /* "Standalone" surface */
728 IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL);
730 object->currentDesc.Width = Width;
731 object->currentDesc.Height = Height;
732 object->currentDesc.MultiSampleType = MultiSample;
733 object->currentDesc.MultiSampleQuality = MultisampleQuality;
735 /* Setup some glformat defaults */
736 if (WINED3DFMT_UNKNOWN != Format) {
737 object->glDescription.glFormat = D3DFmt2GLFmt(This, object->resource.format);
738 object->glDescription.glFormatInternal = D3DFmt2GLIntFmt(This, object->resource.format);
739 object->glDescription.glType = D3DFmt2GLType(This, object->resource.format);
741 object->glDescription.glFormat = 0;
742 object->glDescription.glFormatInternal = 0;
743 object->glDescription.glType = 0;
746 object->glDescription.textureName = 0;
747 object->glDescription.level = Level;
748 object->glDescription.target = GL_TEXTURE_2D;
751 object->pow2Width = pow2Width;
752 object->pow2Height = pow2Height;
753 object->nonpow2 = (pow2Width != Width || pow2Height != Height) ? TRUE : FALSE;
754 object->discard = Discard;
755 object->activeLock = FALSE;
757 if (WINED3DFMT_UNKNOWN != Format) {
758 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
759 object->pow2Size = (pow2Width * object->bytesPerPixel) * pow2Height;
761 object->bytesPerPixel = 0;
762 object->pow2Size = 0;
765 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
767 TRACE("Pool %d %d %d %d",Pool, WINED3DPOOL_DEFAULT, WINED3DPOOL_MANAGED, WINED3DPOOL_SYSTEMMEM);
769 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
770 * this function is too deap to need to care about things like this.
771 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
772 * ****************************************/
774 case WINED3DPOOL_SCRATCH:
775 if(Lockable == FALSE)
776 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
777 which are mutually exclusive, setting lockable to true\n");
780 case WINED3DPOOL_SYSTEMMEM:
781 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
782 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
783 case WINED3DPOOL_MANAGED:
784 if(Usage == WINED3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
785 Usage of DYNAMIC which are mutually exclusive, not doing \
786 anything just telling you.\n");
788 case WINED3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
789 if(!(Usage & WINED3DUSAGE_DYNAMIC) && !(Usage & WINED3DUSAGE_RENDERTARGET)
790 && !(Usage && WINED3DUSAGE_DEPTHSTENCIL ) && Lockable == TRUE)
791 FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
794 FIXME("(%p) Unknown pool %d\n", This, Pool);
798 if (Usage & WINED3DUSAGE_RENDERTARGET && Pool != WINED3DPOOL_DEFAULT) {
799 FIXME("Trying to create a render target that isn't in the default pool\n");
803 object->locked = FALSE;
804 object->lockable = (WINED3DFMT_D16_LOCKABLE == Format) ? TRUE : Lockable;
806 /* mark the texture as dirty so that it get's loaded first time around*/
807 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
808 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
809 This, Width, Height, Format, debug_d3dformat(Format),
810 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
815 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
816 DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
817 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
818 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
820 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
821 IWineD3DTextureImpl *object;
826 unsigned int pow2Width = Width;
827 unsigned int pow2Height = Height;
830 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) ....\n", This, Width, Height, Levels, Usage);
832 /* TODO: It should only be possible to create textures for formats
833 that are reported as supported */
834 if (WINED3DFMT_UNKNOWN >= Format) {
835 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
836 return WINED3DERR_INVALIDCALL;
839 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, WINED3DRTYPE_TEXTURE, 0);
840 D3DINITIALIZEBASETEXTURE(object->baseTexture);
841 object->width = Width;
842 object->height = Height;
844 /** Non-power2 support **/
845 /* Find the nearest pow2 match */
846 pow2Width = pow2Height = 1;
847 while (pow2Width < Width) pow2Width <<= 1;
848 while (pow2Height < Height) pow2Height <<= 1;
850 /** FIXME: add support for real non-power-two if it's provided by the video card **/
851 /* Precalculated scaling for 'faked' non power of two texture coords */
852 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
853 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
854 TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
856 /* Calculate levels for mip mapping */
858 TRACE("calculating levels %d\n", object->baseTexture.levels);
859 object->baseTexture.levels++;
862 while (tmpW > 1 && tmpH > 1) {
863 tmpW = max(1, tmpW >> 1);
864 tmpH = max(1, tmpH >> 1);
865 object->baseTexture.levels++;
867 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
870 /* Generate all the surfaces */
873 for (i = 0; i < object->baseTexture.levels; i++)
875 /* use the callback to create the texture surface */
876 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
877 if (hr!= WINED3D_OK) {
879 FIXME("Failed to create surface %p\n", object);
881 for (j = 0 ; j < i ; j++) {
882 IWineD3DSurface_Release(object->surfaces[j]);
884 /* heap free object */
885 HeapFree(GetProcessHeap(), 0, object);
891 IWineD3DSurface_SetContainer(object->surfaces[i], (IWineD3DBase *)object);
892 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
893 /* calculate the next mipmap level */
894 tmpW = max(1, tmpW >> 1);
895 tmpH = max(1, tmpH >> 1);
898 TRACE("(%p) : Created texture %p\n", This, object);
902 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
903 UINT Width, UINT Height, UINT Depth,
904 UINT Levels, DWORD Usage,
905 WINED3DFORMAT Format, WINED3DPOOL Pool,
906 IWineD3DVolumeTexture **ppVolumeTexture,
907 HANDLE *pSharedHandle, IUnknown *parent,
908 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
910 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
911 IWineD3DVolumeTextureImpl *object;
917 /* TODO: It should only be possible to create textures for formats
918 that are reported as supported */
919 if (WINED3DFMT_UNKNOWN >= Format) {
920 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
921 return WINED3DERR_INVALIDCALL;
924 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, WINED3DRTYPE_VOLUMETEXTURE, 0);
925 D3DINITIALIZEBASETEXTURE(object->baseTexture);
927 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
928 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
930 object->width = Width;
931 object->height = Height;
932 object->depth = Depth;
934 /* Calculate levels for mip mapping */
936 object->baseTexture.levels++;
940 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
941 tmpW = max(1, tmpW >> 1);
942 tmpH = max(1, tmpH >> 1);
943 tmpD = max(1, tmpD >> 1);
944 object->baseTexture.levels++;
946 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
949 /* Generate all the surfaces */
954 for (i = 0; i < object->baseTexture.levels; i++)
956 /* Create the volume */
957 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
958 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
960 /* Set it's container to this object */
961 IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)object);
963 /* calcualte the next mipmap level */
964 tmpW = max(1, tmpW >> 1);
965 tmpH = max(1, tmpH >> 1);
966 tmpD = max(1, tmpD >> 1);
969 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
970 TRACE("(%p) : Created volume texture %p\n", This, object);
974 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
975 UINT Width, UINT Height, UINT Depth,
977 WINED3DFORMAT Format, WINED3DPOOL Pool,
978 IWineD3DVolume** ppVolume,
979 HANDLE* pSharedHandle, IUnknown *parent) {
981 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
982 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
984 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, WINED3DRTYPE_VOLUME, ((Width * D3DFmtGetBpp(This, Format)) * Height * Depth))
986 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
987 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
989 object->currentDesc.Width = Width;
990 object->currentDesc.Height = Height;
991 object->currentDesc.Depth = Depth;
992 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
994 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
995 object->lockable = TRUE;
996 object->locked = FALSE;
997 memset(&object->lockedBox, 0, sizeof(WINED3DBOX));
998 object->dirty = TRUE;
1000 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
1003 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
1004 UINT Levels, DWORD Usage,
1005 WINED3DFORMAT Format, WINED3DPOOL Pool,
1006 IWineD3DCubeTexture **ppCubeTexture,
1007 HANDLE *pSharedHandle, IUnknown *parent,
1008 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1010 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1011 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1015 unsigned int pow2EdgeLength = EdgeLength;
1017 /* TODO: It should only be possible to create textures for formats
1018 that are reported as supported */
1019 if (WINED3DFMT_UNKNOWN >= Format) {
1020 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
1021 return WINED3DERR_INVALIDCALL;
1024 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, WINED3DRTYPE_CUBETEXTURE, 0);
1025 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1027 TRACE("(%p) Create Cube Texture\n", This);
1029 /** Non-power2 support **/
1031 /* Find the nearest pow2 match */
1033 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
1035 object->edgeLength = EdgeLength;
1036 /* TODO: support for native non-power 2 */
1037 /* Precalculated scaling for 'faked' non power of two texture coords */
1038 object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
1040 /* Calculate levels for mip mapping */
1042 object->baseTexture.levels++;
1045 tmpW = max(1, tmpW >> 1);
1046 object->baseTexture.levels++;
1048 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1051 /* Generate all the surfaces */
1053 for (i = 0; i < object->baseTexture.levels; i++) {
1055 /* Create the 6 faces */
1056 for (j = 0; j < 6; j++) {
1058 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
1059 i /* Level */, &object->surfaces[j][i],pSharedHandle);
1061 if(hr!= WINED3D_OK) {
1065 for (l = 0; l < j; l++) {
1066 IWineD3DSurface_Release(object->surfaces[j][i]);
1068 for (k = 0; k < i; k++) {
1069 for (l = 0; l < 6; l++) {
1070 IWineD3DSurface_Release(object->surfaces[l][j]);
1074 FIXME("(%p) Failed to create surface\n",object);
1075 HeapFree(GetProcessHeap(),0,object);
1076 *ppCubeTexture = NULL;
1079 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IWineD3DBase *)object);
1080 TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1082 tmpW = max(1, tmpW >> 1);
1085 TRACE("(%p) : Created Cube Texture %p\n", This, object);
1086 *ppCubeTexture = (IWineD3DCubeTexture *) object;
1090 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1091 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1092 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1094 if (NULL == ppQuery) {
1095 /* Just a check to see if we support this type of query */
1096 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1098 case WINED3DQUERYTYPE_OCCLUSION:
1099 TRACE("(%p) occlusion query\n", This);
1100 if (GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY))
1103 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1105 case WINED3DQUERYTYPE_VCACHE:
1106 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1107 case WINED3DQUERYTYPE_VERTEXSTATS:
1108 case WINED3DQUERYTYPE_EVENT:
1109 case WINED3DQUERYTYPE_TIMESTAMP:
1110 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1111 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1112 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1113 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1114 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1115 case WINED3DQUERYTYPE_PIXELTIMINGS:
1116 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1117 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1119 FIXME("(%p) Unhandled query type %d\n", This, Type);
1124 D3DCREATEOBJECTINSTANCE(object, Query)
1125 object->type = Type;
1126 /* allocated the 'extended' data based on the type of query requested */
1128 case D3DQUERYTYPE_OCCLUSION:
1129 if(GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY)) {
1130 TRACE("(%p) Allocating data for an occlusion query\n", This);
1131 object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1134 case D3DQUERYTYPE_VCACHE:
1135 case D3DQUERYTYPE_RESOURCEMANAGER:
1136 case D3DQUERYTYPE_VERTEXSTATS:
1137 case D3DQUERYTYPE_EVENT:
1138 case D3DQUERYTYPE_TIMESTAMP:
1139 case D3DQUERYTYPE_TIMESTAMPDISJOINT:
1140 case D3DQUERYTYPE_TIMESTAMPFREQ:
1141 case D3DQUERYTYPE_PIPELINETIMINGS:
1142 case D3DQUERYTYPE_INTERFACETIMINGS:
1143 case D3DQUERYTYPE_VERTEXTIMINGS:
1144 case D3DQUERYTYPE_PIXELTIMINGS:
1145 case D3DQUERYTYPE_BANDWIDTHTIMINGS:
1146 case D3DQUERYTYPE_CACHEUTILIZATION:
1148 object->extendedData = 0;
1149 FIXME("(%p) Unhandled query type %d\n",This , Type);
1151 TRACE("(%p) : Created Query %p\n", This, object);
1155 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1156 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1158 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1159 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1160 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1163 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1165 XVisualInfo template;
1166 GLXContext oldContext;
1167 Drawable oldDrawable;
1168 HRESULT hr = WINED3D_OK;
1170 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1172 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1173 * does a device hold a reference to a swap chain giving them a lifetime of the device
1174 * or does the swap chain notify the device of its destruction.
1175 *******************************/
1177 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1179 /* Initialize other useful values */
1180 object->presentParms.BackBufferCount = 1; /* TODO:? support for gl_aux buffers */
1182 /*********************
1183 * Lookup the window Handle and the relating X window handle
1184 ********************/
1186 /* Setup hwnd we are using, plus which display this equates to */
1187 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1188 if (!object->win_handle) {
1189 object->win_handle = This->createParms.hFocusWindow;
1192 object->win_handle = GetAncestor(object->win_handle, GA_ROOT);
1193 if ( !( object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window") ) ) {
1194 ERR("Can't get drawable (window), HWND:%p doesn't have the property __wine_x11_whole_window\n", object->win_handle);
1195 return WINED3DERR_NOTAVAILABLE;
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 WINED3DERR_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 WINED3DERR_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 WINED3DERR_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 (WINED3D_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 WINED3DERR_NOTAVAILABLE;
1302 if (object->glCtx == NULL) {
1303 ERR("Error in context creation !\n");
1304 return WINED3DERR_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, 0);
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;
1456 if (hr == WINED3D_OK) {
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 = WINED3DERR_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);
1594 * Vertex Declaration
1596 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1597 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1598 IWineD3DVertexDeclarationImpl *object = NULL;
1599 HRESULT hr = WINED3D_OK;
1600 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1601 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1604 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1609 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1610 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pDeclaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1611 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1612 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1613 HRESULT hr = WINED3D_OK;
1614 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1615 object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins;
1617 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1619 /* If a vertex declaration has been passed, save it to the vertex shader, this affects d3d8 only. */
1620 /* Further it needs to be set before calling SetFunction as SetFunction needs the declaration. */
1621 if (pDeclaration != NULL) {
1622 IWineD3DVertexDeclaration *vertexDeclaration;
1623 hr = IWineD3DDevice_CreateVertexDeclaration(iface, pDeclaration, &vertexDeclaration ,NULL);
1624 if (WINED3D_OK == hr) {
1625 TRACE("(%p) : Setting vertex declaration to %p\n", This, vertexDeclaration);
1626 object->vertexDeclaration = vertexDeclaration;
1628 FIXME("(%p) : Failed to set the declaration, returning WINED3DERR_INVALIDCALL\n", iface);
1629 IWineD3DVertexShader_Release(*ppVertexShader);
1630 return WINED3DERR_INVALIDCALL;
1634 hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1636 if (WINED3D_OK != hr) {
1637 FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface);
1638 IWineD3DVertexShader_Release(*ppVertexShader);
1639 return WINED3DERR_INVALIDCALL;
1642 #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. */
1643 if(Usage == WINED3DUSAGE_SOFTWAREVERTEXPROCESSING) {
1654 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
1655 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1656 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1657 HRESULT hr = WINED3D_OK;
1659 D3DCREATEOBJECTINSTANCE(object, PixelShader)
1660 object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins;
1661 hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
1662 if (WINED3D_OK == hr) {
1663 TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
1665 WARN("(%p) : Failed to create pixel shader\n", This);
1671 HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) {
1672 FIXME("This call is a d3d7 merge stub. It will be implemented later\n");
1673 return WINED3DERR_INVALIDCALL;
1676 HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface) {
1677 FIXME("This call is a d3d7 merge stub. It will be implemented later\n");
1678 return WINED3DERR_INVALIDCALL;
1681 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
1682 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1683 *ppD3D= This->wineD3D;
1684 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1685 IWineD3D_AddRef(*ppD3D);
1689 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1690 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1691 * Into the video ram as possible and seeing how many fit
1692 * you can also get the correct initial value from via X and ATI's driver
1693 *******************/
1694 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1695 static BOOL showfixmes = TRUE;
1697 FIXME("(%p) : stub, emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1698 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1701 TRACE("(%p) : emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1702 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1703 /* videomemory is simulated videomemory + AGP memory left */
1704 return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1712 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1713 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1714 HRESULT hr = WINED3D_OK;
1716 /* Update the current state block */
1717 This->updateStateBlock->fvf = fvf;
1718 This->updateStateBlock->changed.fvf = TRUE;
1719 This->updateStateBlock->set.fvf = TRUE;
1721 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1724 /* clear down the vertex declaration
1725 NOTE: Axis and Allies doesn't work properly otherwise
1726 (may be a stateblock problem though!)
1728 hr = IWineD3DDevice_SetVertexDeclaration(iface, NULL);
1735 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1736 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1737 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1738 *pfvf = This->stateBlock->fvf;
1743 * Get / Set Stream Source
1745 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1746 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1747 IWineD3DVertexBuffer *oldSrc;
1749 /**TODO: instance and index data, see
1750 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1752 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
1755 /* D3d9 only, but shouldn't hurt d3d8 */
1758 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1760 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1761 FIXME("stream index data not supported\n");
1763 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1764 FIXME("stream instance data not supported\n");
1768 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1770 if (StreamNumber >= MAX_STREAMS) {
1771 WARN("Stream out of range %d\n", StreamNumber);
1772 return WINED3DERR_INVALIDCALL;
1775 oldSrc = This->stateBlock->streamSource[StreamNumber];
1776 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1778 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
1779 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
1780 This->updateStateBlock->streamStride[StreamNumber] = Stride;
1781 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
1782 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
1783 This->updateStateBlock->streamFlags[StreamNumber] = streamFlags;
1785 /* Handle recording of state blocks */
1786 if (This->isRecordingState) {
1787 TRACE("Recording... not performing anything\n");
1791 /* Not recording... */
1792 /* Need to do a getParent and pass the reffs up */
1793 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
1794 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
1795 so for now, just count internally */
1796 if (pStreamData != NULL) {
1797 IWineD3DVertexBuffer_AddRef(pStreamData);
1799 if (oldSrc != NULL) {
1800 IWineD3DVertexBuffer_Release(oldSrc);
1806 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
1807 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1810 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
1811 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
1814 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1816 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1817 FIXME("stream index data not supported\n");
1819 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1820 FIXME("stream instance data not supported\n");
1824 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1826 if (StreamNumber >= MAX_STREAMS) {
1827 WARN("Stream out of range %d\n", StreamNumber);
1828 return WINED3DERR_INVALIDCALL;
1830 *pStream = This->stateBlock->streamSource[StreamNumber];
1831 *pStride = This->stateBlock->streamStride[StreamNumber];
1832 *pOffset = This->stateBlock->streamOffset[StreamNumber];
1834 if (*pStream == NULL) {
1835 FIXME("Attempting to get an empty stream %d, returning WINED3DERR_INVALIDCALL\n", StreamNumber);
1836 return WINED3DERR_INVALIDCALL;
1839 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
1843 /*Should be quite easy, just an extension of vertexdata
1845 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1847 The divider is a bit odd though
1849 VertexOffset = StartVertex / Divider * StreamStride +
1850 VertexIndex / Divider * StreamStride + StreamOffset
1853 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
1854 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1856 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
1857 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (D3DSTREAMSOURCE_INSTANCEDATA | D3DSTREAMSOURCE_INDEXEDDATA );
1859 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
1860 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
1861 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
1863 if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
1864 FIXME("Stream indexing not fully supported\n");
1870 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
1871 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1873 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
1874 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
1876 TRACE("(%p) : returning %d\n", This, *Divider);
1882 * Get / Set & Multiply Transform
1884 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1885 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1887 /* Most of this routine, comments included copied from ddraw tree initially: */
1888 TRACE("(%p) : Transform State=%d\n", This, d3dts);
1890 /* Handle recording of state blocks */
1891 if (This->isRecordingState) {
1892 TRACE("Recording... not performing anything\n");
1893 This->updateStateBlock->changed.transform[d3dts] = TRUE;
1894 This->updateStateBlock->set.transform[d3dts] = TRUE;
1895 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1900 * If the new matrix is the same as the current one,
1901 * we cut off any further processing. this seems to be a reasonable
1902 * optimization because as was noticed, some apps (warcraft3 for example)
1903 * tend towards setting the same matrix repeatedly for some reason.
1905 * From here on we assume that the new matrix is different, wherever it matters.
1907 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1908 TRACE("The app is setting the same matrix over again\n");
1911 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1915 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1916 where ViewMat = Camera space, WorldMat = world space.
1918 In OpenGL, camera and world space is combined into GL_MODELVIEW
1919 matrix. The Projection matrix stay projection matrix.
1922 /* Capture the times we can just ignore the change for now */
1923 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1924 This->modelview_valid = FALSE;
1927 } else if (d3dts == D3DTS_PROJECTION) {
1928 This->proj_valid = FALSE;
1931 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1932 /* Indexed Vertex Blending Matrices 256 -> 511 */
1933 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1934 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1938 /* Now we really are going to have to change a matrix */
1941 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1942 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
1943 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1946 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1947 * NOTE: We have to reset the positions even if the light/plane is not currently
1948 * enabled, since the call to enable it will not reset the position.
1949 * NOTE2: Apparently texture transforms do NOT need reapplying
1952 PLIGHTINFOEL *lightChain = NULL;
1953 This->modelview_valid = FALSE;
1954 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
1956 glMatrixMode(GL_MODELVIEW);
1957 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1959 glLoadMatrixf((float *)lpmatrix);
1960 checkGLcall("glLoadMatrixf(...)");
1963 lightChain = This->stateBlock->lights;
1964 while (lightChain && lightChain->glIndex != -1) {
1965 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1966 checkGLcall("glLightfv posn");
1967 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1968 checkGLcall("glLightfv dirn");
1969 lightChain = lightChain->next;
1972 /* Reset Clipping Planes if clipping is enabled */
1973 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1974 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1975 checkGLcall("glClipPlane");
1979 } else { /* What was requested!?? */
1980 WARN("invalid matrix specified: %i\n", d3dts);
1983 /* Release lock, all done */
1988 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1989 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1990 TRACE("(%p) : for Transform State %d\n", This, State);
1991 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1995 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1996 D3DMATRIX *mat = NULL;
1999 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2000 * below means it will be recorded in a state block change, but it
2001 * works regardless where it is recorded.
2002 * If this is found to be wrong, change to StateBlock.
2004 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2005 TRACE("(%p) : For state %u\n", This, State);
2007 if (State < HIGHEST_TRANSFORMSTATE)
2009 mat = &This->updateStateBlock->transforms[State];
2011 FIXME("Unhandled transform state!!\n");
2014 /* Copied from ddraw code: */
2015 temp.u.s._11 = (mat->u.s._11 * pMatrix->u.s._11) + (mat->u.s._21 * pMatrix->u.s._12) +
2016 (mat->u.s._31 * pMatrix->u.s._13) + (mat->u.s._41 * pMatrix->u.s._14);
2017 temp.u.s._21 = (mat->u.s._11 * pMatrix->u.s._21) + (mat->u.s._21 * pMatrix->u.s._22) +
2018 (mat->u.s._31 * pMatrix->u.s._23) + (mat->u.s._41 * pMatrix->u.s._24);
2019 temp.u.s._31 = (mat->u.s._11 * pMatrix->u.s._31) + (mat->u.s._21 * pMatrix->u.s._32) +
2020 (mat->u.s._31 * pMatrix->u.s._33) + (mat->u.s._41 * pMatrix->u.s._34);
2021 temp.u.s._41 = (mat->u.s._11 * pMatrix->u.s._41) + (mat->u.s._21 * pMatrix->u.s._42) +
2022 (mat->u.s._31 * pMatrix->u.s._43) + (mat->u.s._41 * pMatrix->u.s._44);
2024 temp.u.s._12 = (mat->u.s._12 * pMatrix->u.s._11) + (mat->u.s._22 * pMatrix->u.s._12) +
2025 (mat->u.s._32 * pMatrix->u.s._13) + (mat->u.s._42 * pMatrix->u.s._14);
2026 temp.u.s._22 = (mat->u.s._12 * pMatrix->u.s._21) + (mat->u.s._22 * pMatrix->u.s._22) +
2027 (mat->u.s._32 * pMatrix->u.s._23) + (mat->u.s._42 * pMatrix->u.s._24);
2028 temp.u.s._32 = (mat->u.s._12 * pMatrix->u.s._31) + (mat->u.s._22 * pMatrix->u.s._32) +
2029 (mat->u.s._32 * pMatrix->u.s._33) + (mat->u.s._42 * pMatrix->u.s._34);
2030 temp.u.s._42 = (mat->u.s._12 * pMatrix->u.s._41) + (mat->u.s._22 * pMatrix->u.s._42) +
2031 (mat->u.s._32 * pMatrix->u.s._43) + (mat->u.s._42 * pMatrix->u.s._44);
2033 temp.u.s._13 = (mat->u.s._13 * pMatrix->u.s._11) + (mat->u.s._23 * pMatrix->u.s._12) +
2034 (mat->u.s._33 * pMatrix->u.s._13) + (mat->u.s._43 * pMatrix->u.s._14);
2035 temp.u.s._23 = (mat->u.s._13 * pMatrix->u.s._21) + (mat->u.s._23 * pMatrix->u.s._22) +
2036 (mat->u.s._33 * pMatrix->u.s._23) + (mat->u.s._43 * pMatrix->u.s._24);
2037 temp.u.s._33 = (mat->u.s._13 * pMatrix->u.s._31) + (mat->u.s._23 * pMatrix->u.s._32) +
2038 (mat->u.s._33 * pMatrix->u.s._33) + (mat->u.s._43 * pMatrix->u.s._34);
2039 temp.u.s._43 = (mat->u.s._13 * pMatrix->u.s._41) + (mat->u.s._23 * pMatrix->u.s._42) +
2040 (mat->u.s._33 * pMatrix->u.s._43) + (mat->u.s._43 * pMatrix->u.s._44);
2042 temp.u.s._14 = (mat->u.s._14 * pMatrix->u.s._11) + (mat->u.s._24 * pMatrix->u.s._12) +
2043 (mat->u.s._34 * pMatrix->u.s._13) + (mat->u.s._44 * pMatrix->u.s._14);
2044 temp.u.s._24 = (mat->u.s._14 * pMatrix->u.s._21) + (mat->u.s._24 * pMatrix->u.s._22) +
2045 (mat->u.s._34 * pMatrix->u.s._23) + (mat->u.s._44 * pMatrix->u.s._24);
2046 temp.u.s._34 = (mat->u.s._14 * pMatrix->u.s._31) + (mat->u.s._24 * pMatrix->u.s._32) +
2047 (mat->u.s._34 * pMatrix->u.s._33) + (mat->u.s._44 * pMatrix->u.s._34);
2048 temp.u.s._44 = (mat->u.s._14 * pMatrix->u.s._41) + (mat->u.s._24 * pMatrix->u.s._42) +
2049 (mat->u.s._34 * pMatrix->u.s._43) + (mat->u.s._44 * pMatrix->u.s._44);
2051 /* Apply change via set transform - will reapply to eg. lights this way */
2052 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2057 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
2059 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2060 you can reference any indexes you want as long as that number max are enabled at any
2061 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2062 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2063 but when recording, just build a chain pretty much of commands to be replayed. */
2065 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2067 PLIGHTINFOEL *object, *temp;
2069 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2070 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2072 /* If recording state block, just add to end of lights chain */
2073 if (This->isRecordingState) {
2074 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2075 if (NULL == object) {
2076 return WINED3DERR_OUTOFVIDEOMEMORY;
2078 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2079 object->OriginalIndex = Index;
2080 object->glIndex = -1;
2081 object->changed = TRUE;
2083 /* Add to the END of the chain of lights changes to be replayed */
2084 if (This->updateStateBlock->lights == NULL) {
2085 This->updateStateBlock->lights = object;
2087 temp = This->updateStateBlock->lights;
2088 while (temp->next != NULL) temp=temp->next;
2089 temp->next = object;
2091 TRACE("Recording... not performing anything more\n");
2095 /* Ok, not recording any longer so do real work */
2096 object = This->stateBlock->lights;
2097 while (object != NULL && object->OriginalIndex != Index) object = object->next;
2099 /* If we didn't find it in the list of lights, time to add it */
2100 if (object == NULL) {
2101 PLIGHTINFOEL *insertAt,*prevPos;
2103 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2104 if (NULL == object) {
2105 return WINED3DERR_OUTOFVIDEOMEMORY;
2107 object->OriginalIndex = Index;
2108 object->glIndex = -1;
2110 /* Add it to the front of list with the idea that lights will be changed as needed
2111 BUT after any lights currently assigned GL indexes */
2112 insertAt = This->stateBlock->lights;
2114 while (insertAt != NULL && insertAt->glIndex != -1) {
2116 insertAt = insertAt->next;
2119 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2120 This->stateBlock->lights = object;
2121 } else if (insertAt == NULL) { /* End of list */
2122 prevPos->next = object;
2123 object->prev = prevPos;
2124 } else { /* Middle of chain */
2125 if (prevPos == NULL) {
2126 This->stateBlock->lights = object;
2128 prevPos->next = object;
2130 object->prev = prevPos;
2131 object->next = insertAt;
2132 insertAt->prev = object;
2136 /* Initialize the object */
2137 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,
2138 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2139 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2140 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2141 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2142 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2143 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2145 /* Save away the information */
2146 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2148 switch (pLight->Type) {
2149 case D3DLIGHT_POINT:
2151 object->lightPosn[0] = pLight->Position.x;
2152 object->lightPosn[1] = pLight->Position.y;
2153 object->lightPosn[2] = pLight->Position.z;
2154 object->lightPosn[3] = 1.0f;
2155 object->cutoff = 180.0f;
2159 case D3DLIGHT_DIRECTIONAL:
2161 object->lightPosn[0] = -pLight->Direction.x;
2162 object->lightPosn[1] = -pLight->Direction.y;
2163 object->lightPosn[2] = -pLight->Direction.z;
2164 object->lightPosn[3] = 0.0;
2165 object->exponent = 0.0f;
2166 object->cutoff = 180.0f;
2171 object->lightPosn[0] = pLight->Position.x;
2172 object->lightPosn[1] = pLight->Position.y;
2173 object->lightPosn[2] = pLight->Position.z;
2174 object->lightPosn[3] = 1.0;
2177 object->lightDirn[0] = pLight->Direction.x;
2178 object->lightDirn[1] = pLight->Direction.y;
2179 object->lightDirn[2] = pLight->Direction.z;
2180 object->lightDirn[3] = 1.0;
2183 * opengl-ish and d3d-ish spot lights use too different models for the
2184 * light "intensity" as a function of the angle towards the main light direction,
2185 * so we only can approximate very roughly.
2186 * however spot lights are rather rarely used in games (if ever used at all).
2187 * furthermore if still used, probably nobody pays attention to such details.
2189 if (pLight->Falloff == 0) {
2192 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2194 if (rho < 0.0001) rho = 0.0001f;
2195 object->exponent = -0.3/log(cos(rho/2));
2196 object->cutoff = pLight->Phi*90/M_PI;
2202 FIXME("Unrecognized light type %d\n", pLight->Type);
2205 /* Update the live definitions if the light is currently assigned a glIndex */
2206 if (object->glIndex != -1) {
2207 setup_light(iface, object->glIndex, object);
2212 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2213 PLIGHTINFOEL *lightInfo = NULL;
2214 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2215 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2217 /* Locate the light in the live lights */
2218 lightInfo = This->stateBlock->lights;
2219 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2221 if (lightInfo == NULL) {
2222 TRACE("Light information requested but light not defined\n");
2223 return WINED3DERR_INVALIDCALL;
2226 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
2231 * Get / Set Light Enable
2232 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2234 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2235 PLIGHTINFOEL *lightInfo = NULL;
2236 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2237 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2239 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2240 if (This->isRecordingState) {
2241 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2242 if (NULL == lightInfo) {
2243 return WINED3DERR_OUTOFVIDEOMEMORY;
2245 lightInfo->OriginalIndex = Index;
2246 lightInfo->glIndex = -1;
2247 lightInfo->enabledChanged = TRUE;
2249 /* Add to the END of the chain of lights changes to be replayed */
2250 if (This->updateStateBlock->lights == NULL) {
2251 This->updateStateBlock->lights = lightInfo;
2253 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2254 while (temp->next != NULL) temp=temp->next;
2255 temp->next = lightInfo;
2257 TRACE("Recording... not performing anything more\n");
2261 /* Not recording... So, locate the light in the live lights */
2262 lightInfo = This->stateBlock->lights;
2263 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2265 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2266 if (lightInfo == NULL) {
2267 D3DLIGHT9 lightParms;
2268 /* Warning - untested code :-) Prob safe to change fixme to a trace but
2269 wait until someone confirms it seems to work! */
2270 TRACE("Light enabled requested but light not defined, so defining one!\n");
2271 lightParms.Type = D3DLIGHT_DIRECTIONAL;
2272 lightParms.Diffuse.r = 1.0;
2273 lightParms.Diffuse.g = 1.0;
2274 lightParms.Diffuse.b = 1.0;
2275 lightParms.Diffuse.a = 0.0;
2276 lightParms.Specular.r = 0.0;
2277 lightParms.Specular.g = 0.0;
2278 lightParms.Specular.b = 0.0;
2279 lightParms.Specular.a = 0.0;
2280 lightParms.Ambient.r = 0.0;
2281 lightParms.Ambient.g = 0.0;
2282 lightParms.Ambient.b = 0.0;
2283 lightParms.Ambient.a = 0.0;
2284 lightParms.Position.x = 0.0;
2285 lightParms.Position.y = 0.0;
2286 lightParms.Position.z = 0.0;
2287 lightParms.Direction.x = 0.0;
2288 lightParms.Direction.y = 0.0;
2289 lightParms.Direction.z = 1.0;
2290 lightParms.Range = 0.0;
2291 lightParms.Falloff = 0.0;
2292 lightParms.Attenuation0 = 0.0;
2293 lightParms.Attenuation1 = 0.0;
2294 lightParms.Attenuation2 = 0.0;
2295 lightParms.Theta = 0.0;
2296 lightParms.Phi = 0.0;
2297 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
2299 /* Search for it again! Should be fairly quick as near head of list */
2300 lightInfo = This->stateBlock->lights;
2301 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2302 if (lightInfo == NULL) {
2303 FIXME("Adding default lights has failed dismally\n");
2304 return WINED3DERR_INVALIDCALL;
2308 /* OK, we now have a light... */
2309 if (Enable == FALSE) {
2311 /* If we are disabling it, check it was enabled, and
2312 still only do something if it has assigned a glIndex (which it should have!) */
2313 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2314 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2316 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2317 checkGLcall("glDisable GL_LIGHT0+Index");
2320 TRACE("Nothing to do as light was not enabled\n");
2322 lightInfo->lightEnabled = FALSE;
2325 /* We are enabling it. If it is enabled, it's really simple */
2326 if (lightInfo->lightEnabled) {
2328 TRACE("Nothing to do as light was enabled\n");
2330 /* If it already has a glIndex, it's still simple */
2331 } else if (lightInfo->glIndex != -1) {
2332 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2333 lightInfo->lightEnabled = TRUE;
2335 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2336 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2339 /* Otherwise got to find space - lights are ordered gl indexes first */
2341 PLIGHTINFOEL *bsf = NULL;
2342 PLIGHTINFOEL *pos = This->stateBlock->lights;
2343 PLIGHTINFOEL *prev = NULL;
2347 /* Try to minimize changes as much as possible */
2348 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2350 /* Try to remember which index can be replaced if necessary */
2351 if (bsf==NULL && pos->lightEnabled == FALSE) {
2352 /* Found a light we can replace, save as best replacement */
2356 /* Step to next space */
2362 /* If we have too many active lights, fail the call */
2363 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2364 FIXME("Program requests too many concurrent lights\n");
2365 return WINED3DERR_INVALIDCALL;
2367 /* If we have allocated all lights, but not all are enabled,
2368 reuse one which is not enabled */
2369 } else if (Index == This->maxConcurrentLights) {
2370 /* use bsf - Simply swap the new light and the BSF one */
2371 PLIGHTINFOEL *bsfNext = bsf->next;
2372 PLIGHTINFOEL *bsfPrev = bsf->prev;
2375 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2376 if (bsf->prev != NULL) {
2377 bsf->prev->next = lightInfo;
2379 This->stateBlock->lights = lightInfo;
2382 /* If not side by side, lots of chains to update */
2383 if (bsf->next != lightInfo) {
2384 lightInfo->prev->next = bsf;
2385 bsf->next->prev = lightInfo;
2386 bsf->next = lightInfo->next;
2387 bsf->prev = lightInfo->prev;
2388 lightInfo->next = bsfNext;
2389 lightInfo->prev = bsfPrev;
2393 bsf->prev = lightInfo;
2394 bsf->next = lightInfo->next;
2395 lightInfo->next = bsf;
2396 lightInfo->prev = bsfPrev;
2401 glIndex = bsf->glIndex;
2403 lightInfo->glIndex = glIndex;
2404 lightInfo->lightEnabled = TRUE;
2406 /* Finally set up the light in gl itself */
2407 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2409 setup_light(iface, glIndex, lightInfo);
2410 glEnable(GL_LIGHT0 + glIndex);
2411 checkGLcall("glEnable GL_LIGHT0 new setup");
2414 /* If we reached the end of the allocated lights, with space in the
2415 gl lights, setup a new light */
2416 } else if (pos->glIndex == -1) {
2418 /* We reached the end of the allocated gl lights, so already
2419 know the index of the next one! */
2421 lightInfo->glIndex = glIndex;
2422 lightInfo->lightEnabled = TRUE;
2424 /* In an ideal world, it's already in the right place */
2425 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2426 /* No need to move it */
2428 /* Remove this light from the list */
2429 lightInfo->prev->next = lightInfo->next;
2430 if (lightInfo->next != NULL) {
2431 lightInfo->next->prev = lightInfo->prev;
2434 /* Add in at appropriate place (inbetween prev and pos) */
2435 lightInfo->prev = prev;
2436 lightInfo->next = pos;
2438 This->stateBlock->lights = lightInfo;
2440 prev->next = lightInfo;
2443 pos->prev = lightInfo;
2447 /* Finally set up the light in gl itself */
2448 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2450 setup_light(iface, glIndex, lightInfo);
2451 glEnable(GL_LIGHT0 + glIndex);
2452 checkGLcall("glEnable GL_LIGHT0 new setup");
2461 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2463 PLIGHTINFOEL *lightInfo = NULL;
2464 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2465 TRACE("(%p) : for idx(%ld)\n", This, Index);
2467 /* Locate the light in the live lights */
2468 lightInfo = This->stateBlock->lights;
2469 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2471 if (lightInfo == NULL) {
2472 TRACE("Light enabled state requested but light not defined\n");
2473 return WINED3DERR_INVALIDCALL;
2475 *pEnable = lightInfo->lightEnabled;
2480 * Get / Set Clip Planes
2482 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2483 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2484 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2486 /* Validate Index */
2487 if (Index >= GL_LIMITS(clipplanes)) {
2488 TRACE("Application has requested clipplane this device doesn't support\n");
2489 return WINED3DERR_INVALIDCALL;
2492 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2493 This->updateStateBlock->set.clipplane[Index] = TRUE;
2494 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2495 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2496 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2497 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2499 /* Handle recording of state blocks */
2500 if (This->isRecordingState) {
2501 TRACE("Recording... not performing anything\n");
2509 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2510 glMatrixMode(GL_MODELVIEW);
2512 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2514 TRACE("Clipplane [%f,%f,%f,%f]\n",
2515 This->updateStateBlock->clipplane[Index][0],
2516 This->updateStateBlock->clipplane[Index][1],
2517 This->updateStateBlock->clipplane[Index][2],
2518 This->updateStateBlock->clipplane[Index][3]);
2519 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2520 checkGLcall("glClipPlane");
2528 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2529 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2530 TRACE("(%p) : for idx %ld\n", This, Index);
2532 /* Validate Index */
2533 if (Index >= GL_LIMITS(clipplanes)) {
2534 TRACE("Application has requested clipplane this device doesn't support\n");
2535 return WINED3DERR_INVALIDCALL;
2538 pPlane[0] = This->stateBlock->clipplane[Index][0];
2539 pPlane[1] = This->stateBlock->clipplane[Index][1];
2540 pPlane[2] = This->stateBlock->clipplane[Index][2];
2541 pPlane[3] = This->stateBlock->clipplane[Index][3];
2546 * Get / Set Clip Plane Status
2547 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2549 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2550 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2551 FIXME("(%p) : stub\n", This);
2552 if (NULL == pClipStatus) {
2553 return WINED3DERR_INVALIDCALL;
2555 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2556 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2560 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2561 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2562 FIXME("(%p) : stub\n", This);
2563 if (NULL == pClipStatus) {
2564 return WINED3DERR_INVALIDCALL;
2566 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2567 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2572 * Get / Set Material
2573 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2575 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2576 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2578 This->updateStateBlock->changed.material = TRUE;
2579 This->updateStateBlock->set.material = TRUE;
2580 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2582 /* Handle recording of state blocks */
2583 if (This->isRecordingState) {
2584 TRACE("Recording... not performing anything\n");
2589 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2590 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2591 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2592 pMaterial->Ambient.b, pMaterial->Ambient.a);
2593 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2594 pMaterial->Specular.b, pMaterial->Specular.a);
2595 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2596 pMaterial->Emissive.b, pMaterial->Emissive.a);
2597 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2599 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2600 checkGLcall("glMaterialfv(GL_AMBIENT)");
2601 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2602 checkGLcall("glMaterialfv(GL_DIFFUSE)");
2604 /* Only change material color if specular is enabled, otherwise it is set to black */
2605 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2606 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2607 checkGLcall("glMaterialfv(GL_SPECULAR");
2609 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2610 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2611 checkGLcall("glMaterialfv(GL_SPECULAR");
2613 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2614 checkGLcall("glMaterialfv(GL_EMISSION)");
2615 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2616 checkGLcall("glMaterialf(GL_SHININESS");
2622 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2623 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2624 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2625 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2626 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2627 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2628 pMaterial->Ambient.b, pMaterial->Ambient.a);
2629 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2630 pMaterial->Specular.b, pMaterial->Specular.a);
2631 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2632 pMaterial->Emissive.b, pMaterial->Emissive.a);
2633 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2641 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2642 UINT BaseVertexIndex) {
2643 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2644 IWineD3DIndexBuffer *oldIdxs;
2646 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2647 oldIdxs = This->updateStateBlock->pIndexData;
2649 This->updateStateBlock->changed.indices = TRUE;
2650 This->updateStateBlock->set.indices = TRUE;
2651 This->updateStateBlock->pIndexData = pIndexData;
2652 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2654 /* Handle recording of state blocks */
2655 if (This->isRecordingState) {
2656 TRACE("Recording... not performing anything\n");
2660 if (NULL != pIndexData) {
2661 IWineD3DIndexBuffer_AddRef(pIndexData);
2663 if (NULL != oldIdxs) {
2664 IWineD3DIndexBuffer_Release(oldIdxs);
2669 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2670 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2672 *ppIndexData = This->stateBlock->pIndexData;
2674 /* up ref count on ppindexdata */
2676 IWineD3DIndexBuffer_AddRef(*ppIndexData);
2677 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2678 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
2680 TRACE("(%p) No index data set\n", This);
2682 TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
2688 * Get / Set Viewports
2690 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2691 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2693 TRACE("(%p)\n", This);
2694 This->updateStateBlock->changed.viewport = TRUE;
2695 This->updateStateBlock->set.viewport = TRUE;
2696 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2698 /* Handle recording of state blocks */
2699 if (This->isRecordingState) {
2700 TRACE("Recording... not performing anything\n");
2703 This->viewport_changed = TRUE;
2707 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2708 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2710 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2711 checkGLcall("glDepthRange");
2712 /* Note: GL requires lower left, DirectX supplies upper left */
2713 /* TODO: replace usage of renderTarget with context management */
2714 glViewport(pViewport->X,
2715 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2716 pViewport->Width, pViewport->Height);
2718 checkGLcall("glViewport");
2726 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2727 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2728 TRACE("(%p)\n", This);
2729 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2734 * Get / Set Render States
2735 * TODO: Verify against dx9 definitions
2737 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2739 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2740 DWORD OldValue = This->stateBlock->renderState[State];
2742 /* Simple way of referring to either a DWORD or a 4 byte float */
2748 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2749 This->updateStateBlock->changed.renderState[State] = TRUE;
2750 This->updateStateBlock->set.renderState[State] = TRUE;
2751 This->updateStateBlock->renderState[State] = Value;
2753 /* Handle recording of state blocks */
2754 if (This->isRecordingState) {
2755 TRACE("Recording... not performing anything\n");
2762 case WINED3DRS_FILLMODE :
2763 switch ((D3DFILLMODE) Value) {
2764 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2765 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2766 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2768 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
2770 checkGLcall("glPolygonMode (fillmode)");
2773 case WINED3DRS_LIGHTING :
2775 glEnable(GL_LIGHTING);
2776 checkGLcall("glEnable GL_LIGHTING");
2778 glDisable(GL_LIGHTING);
2779 checkGLcall("glDisable GL_LIGHTING");
2783 case WINED3DRS_ZENABLE :
2784 switch ((D3DZBUFFERTYPE) Value) {
2786 glDisable(GL_DEPTH_TEST);
2787 checkGLcall("glDisable GL_DEPTH_TEST");
2790 glEnable(GL_DEPTH_TEST);
2791 checkGLcall("glEnable GL_DEPTH_TEST");
2794 glEnable(GL_DEPTH_TEST);
2795 checkGLcall("glEnable GL_DEPTH_TEST");
2796 FIXME("W buffer is not well handled\n");
2799 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2803 case WINED3DRS_CULLMODE :
2805 /* If we are culling "back faces with clockwise vertices" then
2806 set front faces to be counter clockwise and enable culling
2808 switch ((D3DCULL) Value) {
2810 glDisable(GL_CULL_FACE);
2811 checkGLcall("glDisable GL_CULL_FACE");
2814 glEnable(GL_CULL_FACE);
2815 checkGLcall("glEnable GL_CULL_FACE");
2816 if (This->renderUpsideDown) {
2818 checkGLcall("glFrontFace GL_CW");
2820 glFrontFace(GL_CCW);
2821 checkGLcall("glFrontFace GL_CCW");
2823 glCullFace(GL_BACK);
2826 glEnable(GL_CULL_FACE);
2827 checkGLcall("glEnable GL_CULL_FACE");
2828 if (This->renderUpsideDown) {
2829 glFrontFace(GL_CCW);
2830 checkGLcall("glFrontFace GL_CCW");
2833 checkGLcall("glFrontFace GL_CW");
2835 glCullFace(GL_BACK);
2838 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2842 case WINED3DRS_SHADEMODE :
2843 switch ((D3DSHADEMODE) Value) {
2845 glShadeModel(GL_FLAT);
2846 checkGLcall("glShadeModel");
2848 case D3DSHADE_GOURAUD:
2849 glShadeModel(GL_SMOOTH);
2850 checkGLcall("glShadeModel");
2852 case D3DSHADE_PHONG:
2853 FIXME("D3DSHADE_PHONG isn't supported?\n");
2856 return WINED3DERR_INVALIDCALL;
2858 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2862 case WINED3DRS_DITHERENABLE :
2864 glEnable(GL_DITHER);
2865 checkGLcall("glEnable GL_DITHER");
2867 glDisable(GL_DITHER);
2868 checkGLcall("glDisable GL_DITHER");
2872 case WINED3DRS_ZWRITEENABLE :
2875 checkGLcall("glDepthMask");
2878 checkGLcall("glDepthMask");
2882 case WINED3DRS_ZFUNC :
2884 int glParm = GL_LESS;
2886 switch ((D3DCMPFUNC) Value) {
2887 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2888 case D3DCMP_LESS: glParm=GL_LESS; break;
2889 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2890 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2891 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2892 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2893 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2894 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2896 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2898 glDepthFunc(glParm);
2899 checkGLcall("glDepthFunc");
2903 case WINED3DRS_AMBIENT :
2906 D3DCOLORTOGLFLOAT4(Value, col);
2907 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2908 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2909 checkGLcall("glLightModel for MODEL_AMBIENT");
2914 case WINED3DRS_ALPHABLENDENABLE :
2917 checkGLcall("glEnable GL_BLEND");
2919 glDisable(GL_BLEND);
2920 checkGLcall("glDisable GL_BLEND");
2924 case WINED3DRS_SRCBLEND :
2925 case WINED3DRS_DESTBLEND :
2927 int newVal = GL_ZERO;
2929 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2930 case D3DBLEND_ONE : newVal = GL_ONE; break;
2931 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2932 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2933 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2934 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2935 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2936 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2937 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2938 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2939 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2941 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2942 This->srcBlend = newVal;
2943 This->dstBlend = newVal;
2946 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2947 This->srcBlend = newVal;
2948 This->dstBlend = newVal;
2951 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2954 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2955 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2956 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2957 glBlendFunc(This->srcBlend, This->dstBlend);
2959 checkGLcall("glBlendFunc");
2963 case WINED3DRS_ALPHATESTENABLE :
2965 glEnable(GL_ALPHA_TEST);
2966 checkGLcall("glEnable GL_ALPHA_TEST");
2968 glDisable(GL_ALPHA_TEST);
2969 checkGLcall("glDisable GL_ALPHA_TEST");
2973 case WINED3DRS_ALPHAFUNC :
2975 int glParm = GL_LESS;
2976 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2978 switch ((D3DCMPFUNC) Value) {
2979 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2980 case D3DCMP_LESS: glParm = GL_LESS; break;
2981 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2982 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2983 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2984 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2985 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2986 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2988 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2990 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2991 glAlphaFunc(glParm, ref);
2992 This->alphafunc = glParm;
2993 checkGLcall("glAlphaFunc");
2997 case WINED3DRS_ALPHAREF :
2999 int glParm = This->alphafunc;
3002 ref = ((float) Value) / 255.0f;
3003 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
3004 glAlphaFunc(glParm, ref);
3005 checkGLcall("glAlphaFunc");
3009 case WINED3DRS_CLIPPLANEENABLE :
3010 case WINED3DRS_CLIPPING :
3012 /* Ensure we only do the changed clip planes */
3013 DWORD enable = 0xFFFFFFFF;
3014 DWORD disable = 0x00000000;
3016 /* If enabling / disabling all */
3017 if (State == WINED3DRS_CLIPPING) {
3019 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3022 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3026 enable = Value & ~OldValue;
3027 disable = ~Value & OldValue;
3030 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
3031 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
3032 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
3033 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
3034 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
3035 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
3037 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
3038 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
3039 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
3040 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
3041 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
3042 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
3044 /** update clipping status */
3046 This->stateBlock->clip_status.ClipUnion = 0;
3047 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
3049 This->stateBlock->clip_status.ClipUnion = 0;
3050 This->stateBlock->clip_status.ClipIntersection = 0;
3055 case WINED3DRS_BLENDOP :
3057 int glParm = GL_FUNC_ADD;
3059 switch ((D3DBLENDOP) Value) {
3060 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
3061 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
3062 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3063 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
3064 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
3066 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
3068 TRACE("glBlendEquation(%x)\n", glParm);
3069 glBlendEquation(glParm);
3070 checkGLcall("glBlendEquation");
3074 case WINED3DRS_TEXTUREFACTOR :
3078 /* Note the texture color applies to all textures whereas
3079 GL_TEXTURE_ENV_COLOR applies to active only */
3081 D3DCOLORTOGLFLOAT4(Value, col);
3082 /* Set the default alpha blend color */
3083 glBlendColor(col[0], col[1], col[2], col[3]);
3084 checkGLcall("glBlendColor");
3086 /* And now the default texture color as well */
3087 for (i = 0; i < GL_LIMITS(textures); i++) {
3089 /* Note the D3DRS value applies to all textures, but GL has one
3090 per texture, so apply it now ready to be used! */
3091 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3094 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3097 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3098 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3103 case WINED3DRS_SPECULARENABLE :
3105 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3106 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3107 specular color. This is wrong:
3108 Separate specular color means the specular colour is maintained separately, whereas
3109 single color means it is merged in. However in both cases they are being used to
3111 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3112 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3116 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3117 checkGLcall("glMaterialfv");
3118 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3119 glEnable(GL_COLOR_SUM_EXT);
3121 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3123 checkGLcall("glEnable(GL_COLOR_SUM)");
3125 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3127 /* for the case of enabled lighting: */
3128 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3129 checkGLcall("glMaterialfv");
3131 /* for the case of disabled lighting: */
3132 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3133 glDisable(GL_COLOR_SUM_EXT);
3135 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3137 checkGLcall("glDisable(GL_COLOR_SUM)");
3142 case WINED3DRS_STENCILENABLE :
3144 glEnable(GL_STENCIL_TEST);
3145 checkGLcall("glEnable GL_STENCIL_TEST");
3147 glDisable(GL_STENCIL_TEST);
3148 checkGLcall("glDisable GL_STENCIL_TEST");
3152 case WINED3DRS_STENCILFUNC :
3155 GLint ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3156 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3159 switch ((D3DCMPFUNC)Value) {
3160 case D3DCMP_NEVER: func = GL_NEVER; break;
3161 case D3DCMP_LESS: func = GL_LESS; break;
3162 case D3DCMP_EQUAL: func = GL_EQUAL; break;
3163 case D3DCMP_LESSEQUAL: func = GL_LEQUAL; break;
3164 case D3DCMP_GREATER: func = GL_GREATER; break;
3165 case D3DCMP_NOTEQUAL: func = GL_NOTEQUAL; break;
3166 case D3DCMP_GREATEREQUAL: func = GL_GEQUAL; break;
3167 case D3DCMP_ALWAYS: func = GL_ALWAYS; break;
3169 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3171 This->stencilfunc = func;
3172 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3173 #if 0 /* Don't use OpenGL 2.0 calls for now */
3174 if(GL_EXTCALL(glStencilFuncSeparate)) {
3175 GL_EXTCALL(glStencilFuncSeparate(GL_FRONT, func, ref, mask));
3176 checkGLcall("glStencilFuncSeparate(GL_FRONT,...)");
3180 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3181 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3182 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3183 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
3184 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
3185 glStencilFunc(func, ref, mask);
3186 checkGLcall("glStencilFunc(...)");
3188 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3189 GL_EXTCALL(glStencilFuncSeparateATI(GL_FRONT, func, ref, mask));
3190 checkGLcall("glStencilFuncSeparateATI(GL_FRONT,...)");
3192 TRACE("Separate stencil function not supported on this version of opengl");
3193 glStencilFunc(func, ref, mask);
3194 checkGLcall("glStencilFunc(...)");
3197 glStencilFunc(func, ref, mask);
3198 checkGLcall("glStencilFunc(...)");
3202 case WINED3DRS_STENCILREF :
3204 int glParm = This->stencilfunc;
3206 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3209 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3210 glStencilFunc(glParm, ref, mask);
3211 checkGLcall("glStencilFunc");
3215 case WINED3DRS_STENCILMASK :
3217 int glParm = This->stencilfunc;
3218 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3219 GLuint mask = Value;
3221 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3222 glStencilFunc(glParm, ref, mask);
3223 checkGLcall("glStencilFunc");
3227 case WINED3DRS_STENCILFAIL :
3228 case WINED3DRS_STENCILZFAIL :
3229 case WINED3DRS_STENCILPASS :
3235 GLint action = StencilOp(Value);
3237 glGetIntegerv(GL_STENCIL_FAIL, &stencilFail);
3238 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &depthFail);
3239 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &stencilPass);
3241 if(WINED3DRS_STENCILFAIL == State) {
3242 stencilFail = action;
3244 else if(WINED3DRS_STENCILZFAIL == State) {
3247 else if(WINED3DRS_STENCILPASS == State) {
3248 stencilPass = action;
3251 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3252 #if 0 /* Don't use OpenGL 2.0 calls for now */
3253 if(GL_EXTCALL(glStencilOpSeparate)) {
3254 GL_EXTCALL(glStencilOpSeparate(GL_FRONT, stencilFail, depthFail, stencilPass));
3255 checkGLcall("glStencilOpSeparate(GL_FRONT,...)");
3259 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3260 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3261 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3262 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
3263 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
3264 glStencilOp(stencilFail, depthFail, stencilPass);
3265 checkGLcall("glStencilOp(...)");
3267 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3268 GL_EXTCALL(glStencilOpSeparateATI(GL_FRONT, stencilFail, depthFail, stencilPass));
3269 checkGLcall("glStencilOpSeparateATI(GL_FRONT,...)");
3271 TRACE("Separate stencil operation not supported on this version of opengl");
3272 glStencilOp(stencilFail, depthFail, stencilPass);
3273 checkGLcall("glStencilOp(...)");
3276 glStencilOp(stencilFail, depthFail, stencilPass);
3277 checkGLcall("glStencilOp(...)");
3281 case WINED3DRS_STENCILWRITEMASK :
3283 glStencilMask(Value);
3284 TRACE("glStencilMask(%lu)\n", Value);
3285 checkGLcall("glStencilMask");
3289 case WINED3DRS_FOGENABLE :
3291 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
3293 checkGLcall("glEnable GL_FOG");
3296 checkGLcall("glDisable GL_FOG");
3301 case WINED3DRS_RANGEFOGENABLE :
3304 TRACE("Enabled RANGEFOG");
3306 TRACE("Disabled RANGEFOG");
3311 case WINED3DRS_FOGCOLOR :
3314 D3DCOLORTOGLFLOAT4(Value, col);
3315 /* Set the default alpha blend color */
3316 glFogfv(GL_FOG_COLOR, &col[0]);
3317 checkGLcall("glFog GL_FOG_COLOR");
3321 case WINED3DRS_FOGTABLEMODE :
3323 glHint(GL_FOG_HINT, GL_NICEST);
3325 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3326 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3327 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3328 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3330 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3332 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3333 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3338 case WINED3DRS_FOGVERTEXMODE :
3340 glHint(GL_FOG_HINT, GL_FASTEST);
3342 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3343 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3344 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3345 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3347 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3349 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3350 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
3355 case WINED3DRS_FOGSTART :
3358 glFogfv(GL_FOG_START, &tmpvalue.f);
3359 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3360 TRACE("Fog Start == %f\n", tmpvalue.f);
3364 case WINED3DRS_FOGEND :
3367 glFogfv(GL_FOG_END, &tmpvalue.f);
3368 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3369 TRACE("Fog End == %f\n", tmpvalue.f);
3373 case WINED3DRS_FOGDENSITY :
3376 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3377 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3381 case WINED3DRS_VERTEXBLEND :
3383 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3384 TRACE("Vertex Blending state to %ld\n", Value);
3388 case WINED3DRS_TWEENFACTOR :
3391 This->updateStateBlock->tween_factor = tmpvalue.f;
3392 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3396 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
3398 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3402 case WINED3DRS_COLORVERTEX :
3403 case WINED3DRS_DIFFUSEMATERIALSOURCE :
3404 case WINED3DRS_SPECULARMATERIALSOURCE :
3405 case WINED3DRS_AMBIENTMATERIALSOURCE :
3406 case WINED3DRS_EMISSIVEMATERIALSOURCE :
3408 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3410 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3411 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3412 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3413 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3414 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3415 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3417 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3418 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3419 Parm = GL_AMBIENT_AND_DIFFUSE;
3423 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3425 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3427 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3434 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3436 This->tracking_color = NEEDS_TRACKING;
3437 This->tracking_parm = Parm;
3441 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3446 case WINED3DRS_LINEPATTERN :
3452 tmppattern.d = Value;
3454 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3456 if (tmppattern.lp.wRepeatFactor) {
3457 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3458 checkGLcall("glLineStipple(repeat, linepattern)");
3459 glEnable(GL_LINE_STIPPLE);
3460 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3462 glDisable(GL_LINE_STIPPLE);
3463 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3468 case WINED3DRS_ZBIAS : /* D3D8 only */
3472 TRACE("ZBias value %f\n", tmpvalue.f);
3473 glPolygonOffset(0, -tmpvalue.f);
3474 checkGLcall("glPolygonOffset(0, -Value)");
3475 glEnable(GL_POLYGON_OFFSET_FILL);
3476 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3477 glEnable(GL_POLYGON_OFFSET_LINE);
3478 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3479 glEnable(GL_POLYGON_OFFSET_POINT);
3480 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3482 glDisable(GL_POLYGON_OFFSET_FILL);
3483 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3484 glDisable(GL_POLYGON_OFFSET_LINE);
3485 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3486 glDisable(GL_POLYGON_OFFSET_POINT);
3487 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3492 case WINED3DRS_NORMALIZENORMALS :
3494 glEnable(GL_NORMALIZE);
3495 checkGLcall("glEnable(GL_NORMALIZE);");
3497 glDisable(GL_NORMALIZE);
3498 checkGLcall("glDisable(GL_NORMALIZE);");
3502 case WINED3DRS_POINTSIZE :
3503 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
3505 TRACE("Set point size to %f\n", tmpvalue.f);
3506 glPointSize(tmpvalue.f);
3507 checkGLcall("glPointSize(...);");
3510 case WINED3DRS_POINTSIZE_MIN :
3511 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3513 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3514 checkGLcall("glPointParameterfEXT(...);");
3516 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3520 case WINED3DRS_POINTSIZE_MAX :
3521 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3523 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3524 checkGLcall("glPointParameterfEXT(...);");
3526 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3530 case WINED3DRS_POINTSCALE_A :
3531 case WINED3DRS_POINTSCALE_B :
3532 case WINED3DRS_POINTSCALE_C :
3533 case WINED3DRS_POINTSCALEENABLE :
3536 * POINTSCALEENABLE controls how point size value is treated. If set to
3537 * true, the point size is scaled with respect to height of viewport.
3538 * When set to false point size is in pixels.
3540 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
3543 /* Default values */
3544 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3547 * Minimum valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
3548 * This means that OpenGL will clamp really small point sizes to 1.0f.
3549 * To correct for this we need to multiply by the scale factor when sizes
3550 * are less than 1.0f. scale_factor = 1.0f / point_size.
3552 GLfloat pointSize = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSIZE]);
3553 if(pointSize > 0.0f) {
3554 GLfloat scaleFactor;
3556 if(pointSize < 1.0f) {
3557 scaleFactor = pointSize * pointSize;
3562 if(This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3563 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]) /
3564 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3565 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]) /
3566 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3567 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) /
3568 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3572 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
3573 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
3574 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
3576 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3577 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3578 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
3580 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
3584 case WINED3DRS_COLORWRITEENABLE :
3586 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3587 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3588 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3589 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3590 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3591 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3592 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3593 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3594 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3595 checkGLcall("glColorMask(...)");
3599 case WINED3DRS_LOCALVIEWER :
3601 GLint state = (Value) ? 1 : 0;
3602 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3603 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3607 case WINED3DRS_LASTPIXEL :
3610 TRACE("Last Pixel Drawing Enabled\n");
3612 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3617 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3620 TRACE("Software Processing Enabled\n");
3622 TRACE("Software Processing Disabled\n");
3627 /** not supported */
3628 case WINED3DRS_ZVISIBLE :
3631 return WINED3DERR_INVALIDCALL;
3633 case WINED3DRS_POINTSPRITEENABLE :
3635 /* TODO: NV_POINT_SPRITE */
3636 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
3637 TRACE("Point sprites not supported\n");
3642 * Point sprites are always enabled. Value controls texture coordinate
3643 * replacement mode. Must be set true for point sprites to use
3646 glEnable(GL_POINT_SPRITE_ARB);
3647 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
3650 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
3651 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, TRUE)");
3653 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, FALSE);
3654 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, FALSE)");
3658 case WINED3DRS_EDGEANTIALIAS :
3661 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3663 checkGLcall("glEnable(GL_BLEND)");
3664 glEnable(GL_LINE_SMOOTH);
3665 checkGLcall("glEnable(GL_LINE_SMOOTH)");
3667 glDisable(GL_BLEND);
3668 checkGLcall("glDisable(GL_BLEND)");
3669 glDisable(GL_LINE_SMOOTH);
3670 checkGLcall("glDisable(GL_LINE_SMOOTH)");
3674 case WINED3DRS_WRAP0 :
3675 case WINED3DRS_WRAP1 :
3676 case WINED3DRS_WRAP2 :
3677 case WINED3DRS_WRAP3 :
3678 case WINED3DRS_WRAP4 :
3679 case WINED3DRS_WRAP5 :
3680 case WINED3DRS_WRAP6 :
3681 case WINED3DRS_WRAP7 :
3682 case WINED3DRS_WRAP8 :
3683 case WINED3DRS_WRAP9 :
3684 case WINED3DRS_WRAP10 :
3685 case WINED3DRS_WRAP11 :
3686 case WINED3DRS_WRAP12 :
3687 case WINED3DRS_WRAP13 :
3688 case WINED3DRS_WRAP14 :
3689 case WINED3DRS_WRAP15 :
3691 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
3692 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
3693 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
3694 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
3695 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
3697 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
3699 TRACE("(%p)->(%s,%ld) Texture wraping not yet supported\n",This, debug_d3drenderstate(State), Value);
3701 case WINED3DRS_MULTISAMPLEANTIALIAS :
3703 if (!GL_SUPPORT(ARB_MULTISAMPLE)) {
3704 TRACE("Multisample antialiasing not supported\n");
3709 glEnable(GL_MULTISAMPLE_ARB);
3710 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
3712 glDisable(GL_MULTISAMPLE_ARB);
3713 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
3717 case WINED3DRS_SCISSORTESTENABLE :
3720 glEnable(GL_SCISSOR_TEST);
3721 checkGLcall("glEnable(GL_SCISSOR_TEST)");
3723 glDisable(GL_SCISSOR_TEST);
3724 checkGLcall("glDisable(GL_SCISSOR_TEST)");
3728 case WINED3DRS_SLOPESCALEDEPTHBIAS :
3732 glEnable(GL_POLYGON_OFFSET_FILL);
3733 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
3734 glPolygonOffset(tmpvalue.f, *((float*)&This->stateBlock->renderState[WINED3DRS_DEPTHBIAS]));
3735 checkGLcall("glPolygonOffset(...)");
3737 glDisable(GL_POLYGON_OFFSET_FILL);
3738 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
3742 case WINED3DRS_ANTIALIASEDLINEENABLE :
3745 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3747 checkGLcall("glEnable(GL_BLEND)");
3748 glEnable(GL_LINE_SMOOTH);
3749 checkGLcall("glEnable(GL_LINE_SMOOTH)");
3751 glDisable(GL_BLEND);
3752 checkGLcall("glDisable(GL_BLEND)");
3753 glDisable(GL_LINE_SMOOTH);
3754 checkGLcall("glDisable(GL_LINE_SMOOTH)");
3758 case WINED3DRS_TWOSIDEDSTENCILMODE :
3761 TRACE("Two-sided stencil mode enabled\n");
3763 TRACE("Two-sided stencil mode disabled\n");
3767 case WINED3DRS_CCW_STENCILFAIL :
3768 case WINED3DRS_CCW_STENCILZFAIL :
3769 case WINED3DRS_CCW_STENCILPASS :
3775 GLint action = StencilOp(Value);
3777 glGetIntegerv(GL_STENCIL_BACK_FAIL, &stencilFail);
3778 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &depthFail);
3779 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS, &stencilPass);
3781 if(WINED3DRS_CCW_STENCILFAIL == State) {
3782 stencilFail = action;
3784 else if(WINED3DRS_CCW_STENCILZFAIL == State) {
3787 else if(WINED3DRS_CCW_STENCILPASS == State) {
3788 stencilPass = action;
3791 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3792 #if 0 /* Don't use OpenGL 2.0 calls for now */
3793 if(GL_EXTCALL(glStencilOpSeparate)) {
3794 GL_EXTCALL(glStencilOpSeparate(GL_BACK, stencilFail, depthFail, stencilPass));
3795 checkGLcall("glStencilOpSeparate(GL_BACK,...)");
3799 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3800 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3801 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3802 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
3803 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
3804 glStencilOp(stencilFail, depthFail, stencilPass);
3805 checkGLcall("glStencilOp(...)");
3807 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3808 GL_EXTCALL(glStencilOpSeparateATI(GL_BACK, stencilFail, depthFail, stencilPass));
3809 checkGLcall("glStencilOpSeparateATI(GL_BACK,...)");
3811 TRACE("Separate stencil operation not supported on this version of opengl");
3812 glStencilOp(stencilFail, depthFail, stencilPass);
3813 checkGLcall("glStencilOp(...)");
3816 glStencilOp(stencilFail, depthFail, stencilPass);
3817 checkGLcall("glStencilOp(...)");
3821 case WINED3DRS_CCW_STENCILFUNC :
3824 GLint ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3825 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3828 switch ((D3DCMPFUNC)Value) {
3829 case D3DCMP_NEVER: func = GL_NEVER; break;
3830 case D3DCMP_LESS: func = GL_LESS; break;
3831 case D3DCMP_EQUAL: func = GL_EQUAL; break;
3832 case D3DCMP_LESSEQUAL: func = GL_LEQUAL; break;
3833 case D3DCMP_GREATER: func = GL_GREATER; break;
3834 case D3DCMP_NOTEQUAL: func = GL_NOTEQUAL; break;
3835 case D3DCMP_GREATEREQUAL: func = GL_GEQUAL; break;
3836 case D3DCMP_ALWAYS: func = GL_ALWAYS; break;
3838 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3840 This->stencilfunc = func;
3841 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3842 #if 0 /* Don't use OpenGL 2.0 calls for now */
3843 if(GL_EXTCALL(glStencilFuncSeparate)) {
3844 GL_EXTCALL(glStencilFuncSeparate(GL_BACK, func, ref, mask));
3845 checkGLcall("glStencilFuncSeparate(GL_BACK,...)");
3849 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3850 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3851 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3852 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
3853 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
3854 glStencilFunc(func, ref, mask);
3855 checkGLcall("glStencilFunc(...)");
3857 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3858 GL_EXTCALL(glStencilFuncSeparateATI(GL_BACK, func, ref, mask));
3859 checkGLcall("glStencilFuncSeparateATI(GL_BACK,...)");
3861 TRACE("Separate stencil function not supported on this version of opengl");
3862 glStencilFunc(func, ref, mask);
3863 checkGLcall("glStencilFunc(...)");
3866 glStencilFunc(func, ref, mask);
3867 checkGLcall("glStencilFunc(...)");
3871 case WINED3DRS_DEPTHBIAS :
3875 glEnable(GL_POLYGON_OFFSET_FILL);
3876 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
3877 glPolygonOffset(*((float*)&This->stateBlock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS]), tmpvalue.f);
3878 checkGLcall("glPolygonOffset(...)");
3880 glDisable(GL_POLYGON_OFFSET_FILL);
3881 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
3885 case WINED3DRS_SEPARATEALPHABLENDENABLE :
3886 case WINED3DRS_SRCBLENDALPHA :
3887 case WINED3DRS_DESTBLENDALPHA :
3888 case WINED3DRS_BLENDOPALPHA :
3889 case WINED3DRS_MULTISAMPLEMASK :
3890 case WINED3DRS_PATCHEDGESTYLE :
3891 case WINED3DRS_PATCHSEGMENTS :
3892 case WINED3DRS_DEBUGMONITORTOKEN :
3893 case WINED3DRS_POSITIONORDER :
3894 case WINED3DRS_NORMALORDER :
3895 case WINED3DRS_MINTESSELLATIONLEVEL :
3896 case WINED3DRS_MAXTESSELLATIONLEVEL :
3897 case WINED3DRS_ADAPTIVETESS_X :
3898 case WINED3DRS_ADAPTIVETESS_Y :
3899 case WINED3DRS_ADAPTIVETESS_Z :
3900 case WINED3DRS_ADAPTIVETESS_W :
3901 case WINED3DRS_ENABLEADAPTIVETESSELLATION :
3902 case WINED3DRS_COLORWRITEENABLE1 :
3903 case WINED3DRS_COLORWRITEENABLE2 :
3904 case WINED3DRS_COLORWRITEENABLE3 :
3905 case WINED3DRS_BLENDFACTOR :
3906 case WINED3DRS_SRGBWRITEENABLE :
3907 FIXME("(%p)->(%s,%ld) not handled yet\n", This, debug_d3drenderstate(State), Value);
3910 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3918 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3919 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3920 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3921 *pValue = This->stateBlock->renderState[State];
3926 * Get / Set Sampler States
3927 * TODO: Verify against dx9 definitions
3930 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3931 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3933 * SetSampler is designed to allow for more than the standard up to 8 textures
3934 * and Geforce has stopped supporting more than 6 standard textures in openGL.
3935 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3937 * http://developer.nvidia.com/object/General_FAQ.html#t6
3939 * There are two new settings for GForce
3941 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3942 * and the texture one:
3943 * GL_MAX_TEXTURE_COORDS_ARB.
3944 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3946 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
3947 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
3949 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
3950 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE, Sampler, Type);
3951 return WINED3DERR_INVALIDCALL;
3953 TRACE("Setting sampler %ld %d to %ld\n", Sampler, Type, Value);
3954 This->updateStateBlock->samplerState[Sampler][Type] = Value;
3955 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
3956 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
3958 /* Handle recording of state blocks */
3959 if (This->isRecordingState) {
3960 TRACE("Recording... not performing anything\n");
3967 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3968 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3969 /** TODO: check that sampler is in range **/
3970 *Value = This->updateStateBlock->samplerState[Sampler][Type];
3971 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
3976 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3977 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3980 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3981 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3982 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3988 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3989 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3990 GLint scissorBox[4];
3993 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3994 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
3995 pRect->left = scissorBox[1];
3996 pRect->top = scissorBox[2];
3997 pRect->right = scissorBox[1] + scissorBox[3];
3998 pRect->bottom = scissorBox[2] + scissorBox[4];
3999 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4004 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
4005 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4006 IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
4008 TRACE("(%p) : pDecl=%p\n", This, pDecl);
4010 This->updateStateBlock->vertexDecl = pDecl;
4011 This->updateStateBlock->changed.vertexDecl = TRUE;
4012 This->updateStateBlock->set.vertexDecl = TRUE;
4014 if (This->isRecordingState) {
4015 TRACE("Recording... not performing anything\n");
4018 if (NULL != pDecl) {
4019 IWineD3DVertexDeclaration_AddRef(pDecl);
4021 if (NULL != oldDecl) {
4022 IWineD3DVertexDeclaration_Release(oldDecl);
4027 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
4028 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4030 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
4032 *ppDecl = This->stateBlock->vertexDecl;
4033 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
4037 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
4038 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4039 IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
4041 This->updateStateBlock->vertexShader = pShader;
4042 This->updateStateBlock->changed.vertexShader = TRUE;
4043 This->updateStateBlock->set.vertexShader = TRUE;
4045 if (This->isRecordingState) {
4046 TRACE("Recording... not performing anything\n");
4049 if (NULL != pShader) {
4050 IWineD3DVertexShader_AddRef(pShader);
4052 if (NULL != oldShader) {
4053 IWineD3DVertexShader_Release(oldShader);
4056 if (pShader != NULL && ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration != NULL) {
4057 TRACE("(%p) : setting vertexDeclaration(%p)\n", This, ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration);
4058 IWineD3DDevice_SetVertexDeclaration(iface, ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration);
4061 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4063 * TODO: merge HAL shaders context switching from prototype
4068 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
4069 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4071 if (NULL == ppShader) {
4072 return WINED3DERR_INVALIDCALL;
4074 *ppShader = This->stateBlock->vertexShader;
4075 if( NULL != *ppShader)
4076 IWineD3DVertexShader_AddRef(*ppShader);
4078 TRACE("(%p) : returning %p\n", This, *ppShader);
4082 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4083 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4086 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4088 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4089 iface, dstData, srcData, type, start, count, registersize);
4091 if (type != WINESHADERCNST_NONE) {
4092 if (srcData == NULL || cnt < 0) {
4093 return WINED3DERR_INVALIDCALL;
4096 CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
4099 for (i = start; i < cnt + start; ++i) {
4100 This->updateStateBlock->changed.vertexShaderConstants[i] = TRUE;
4101 This->updateStateBlock->set.vertexShaderConstants[i] = TRUE;
4102 This->updateStateBlock->vertexShaderConstantT[i] = type;
4108 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4109 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4112 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4114 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4115 iface, dstData, srcData, type, start, count, registersize);
4117 /* Verify that the requested shader constant was populated with the correct type */
4118 for (i = start; i < cnt + start; ++i) {
4119 if (This->updateStateBlock->vertexShaderConstantT[i] != type) {
4120 TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning WINED3DERR_INVALIDCALL\n",
4121 This, type, This->updateStateBlock->vertexShaderConstantT[i]);
4122 return WINED3DERR_INVALIDCALL;
4126 if (dstData == NULL || cnt < 0) {
4127 return WINED3DERR_INVALIDCALL;
4130 CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
4135 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
4136 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4138 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4139 This->updateStateBlock->vertexShaderConstantB,
4141 WINESHADERCNST_BOOL,
4144 sizeof(*pConstantData));
4147 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
4148 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4150 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4152 This->updateStateBlock->vertexShaderConstantB,
4153 WINESHADERCNST_BOOL,
4156 sizeof(*pConstantData));
4159 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
4160 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4162 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4163 This->updateStateBlock->vertexShaderConstantI,
4165 WINESHADERCNST_INTEGER,
4168 4 * sizeof(*pConstantData));
4171 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
4172 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4174 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4176 This->updateStateBlock->vertexShaderConstantI,
4177 WINESHADERCNST_INTEGER,
4180 4 * sizeof(*pConstantData));
4184 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
4185 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4187 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4188 This->updateStateBlock->vertexShaderConstantF,
4190 WINESHADERCNST_FLOAT,
4193 4 * sizeof(*pConstantData));
4196 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
4197 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4199 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4201 This->updateStateBlock->vertexShaderConstantF,
4202 WINESHADERCNST_FLOAT,
4205 4 * sizeof(*pConstantData));
4208 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
4209 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4212 WINESHADERCNST_NONE,
4218 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
4219 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4220 IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader;
4221 This->updateStateBlock->pixelShader = pShader;
4222 This->updateStateBlock->changed.pixelShader = TRUE;
4223 This->updateStateBlock->set.pixelShader = TRUE;
4225 /* Handle recording of state blocks */
4226 if (This->isRecordingState) {
4227 TRACE("Recording... not performing anything\n");
4230 if (NULL != pShader) {
4231 IWineD3DPixelShader_AddRef(pShader);
4233 if (NULL != oldShader) {
4234 IWineD3DPixelShader_Release(oldShader);
4237 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4239 * TODO: merge HAL shaders context switching from prototype
4244 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
4245 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4247 if (NULL == ppShader) {
4248 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
4249 return WINED3DERR_INVALIDCALL;
4252 *ppShader = This->stateBlock->pixelShader;
4253 if (NULL != *ppShader) {
4254 IWineD3DPixelShader_AddRef(*ppShader);
4256 TRACE("(%p) : returning %p\n", This, *ppShader);
4260 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4261 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4264 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4266 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4267 iface, dstData, srcData, type, start, count, registersize);
4269 if (type != WINESHADERCNST_NONE) {
4270 if (srcData == NULL || cnt < 0) {
4271 return WINED3DERR_INVALIDCALL;
4274 CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
4277 for (i = start; i < cnt + start; ++i) {
4278 This->updateStateBlock->changed.pixelShaderConstants[i] = TRUE;
4279 This->updateStateBlock->set.pixelShaderConstants[i] = TRUE;
4280 This->updateStateBlock->pixelShaderConstantT[i] = type;
4286 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4287 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4290 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4292 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4293 iface, dstData, srcData, type, start, count, registersize);
4295 /* Verify that the requested shader constant was populated with the correct type */
4296 for (i = start; i < cnt + start; ++i) {
4297 if (This->updateStateBlock->pixelShaderConstantT[i] != type) {
4298 TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning WINED3DERR_INVALIDCALL\n",
4299 This, type, This->updateStateBlock->pixelShaderConstantT[i]);
4300 return WINED3DERR_INVALIDCALL;
4304 if (dstData == NULL || cnt < 0) {
4305 return WINED3DERR_INVALIDCALL;
4308 CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
4313 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
4314 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4316 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4317 This->updateStateBlock->pixelShaderConstantB,
4319 WINESHADERCNST_BOOL,
4322 sizeof(*pConstantData));
4325 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
4326 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4328 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4330 This->updateStateBlock->pixelShaderConstantB,
4331 WINESHADERCNST_BOOL,
4334 sizeof(*pConstantData));
4337 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
4338 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4340 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4341 This->updateStateBlock->pixelShaderConstantI,
4343 WINESHADERCNST_INTEGER,
4346 4 * sizeof(*pConstantData));
4349 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
4350 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4352 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4354 This->updateStateBlock->pixelShaderConstantI,
4355 WINESHADERCNST_INTEGER,
4358 4 * sizeof(*pConstantData));
4361 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
4362 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4364 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4365 This->updateStateBlock->pixelShaderConstantF,
4367 WINESHADERCNST_FLOAT,
4370 4 * sizeof(*pConstantData));
4373 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
4374 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4376 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4378 This->updateStateBlock->pixelShaderConstantF,
4379 WINESHADERCNST_FLOAT,
4382 4 * sizeof(*pConstantData));
4385 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
4386 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4389 WINESHADERCNST_NONE,
4395 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
4396 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4397 FIXME("(%p) : stub\n", This);
4402 * Apply / Get / Set Texture Stage States
4403 * TODO: Verify against dx9 definitions
4406 /* 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 */
4407 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
4408 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4409 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
4410 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4412 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4414 /* Check that the stage is within limits */
4415 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4416 TRACE("Attempt to access invalid texture rejected\n");
4423 case WINED3DTSS_ALPHAOP :
4424 case WINED3DTSS_COLOROP :
4425 /* nothing to do as moved to drawprim for now */
4427 case WINED3DTSS_ADDRESSW :
4428 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
4429 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
4430 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
4433 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
4434 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
4435 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
4436 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
4439 case WINED3DTSS_TEXCOORDINDEX :
4441 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
4443 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
4444 one flag, you can still specify an index value, which the system uses to
4445 determine the texture wrapping mode.
4446 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
4447 means use the vertex position (camera-space) as the input texture coordinates
4448 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
4449 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
4450 to the TEXCOORDINDEX value */
4453 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
4455 switch (Value & 0xFFFF0000) {
4456 case D3DTSS_TCI_PASSTHRU:
4457 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
4458 glDisable(GL_TEXTURE_GEN_S);
4459 glDisable(GL_TEXTURE_GEN_T);
4460 glDisable(GL_TEXTURE_GEN_R);
4461 glDisable(GL_TEXTURE_GEN_Q);
4462 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
4465 case D3DTSS_TCI_CAMERASPACEPOSITION:
4466 /* CameraSpacePosition means use the vertex position, transformed to camera space,
4467 as the input texture coordinates for this stage's texture transformation. This
4468 equates roughly to EYE_LINEAR */
4470 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4471 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4472 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4473 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4474 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4476 glMatrixMode(GL_MODELVIEW);
4479 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4480 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4481 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4482 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4485 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
4486 glEnable(GL_TEXTURE_GEN_S);
4487 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4488 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4489 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4490 glEnable(GL_TEXTURE_GEN_T);
4491 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4492 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4493 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4494 glEnable(GL_TEXTURE_GEN_R);
4495 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4496 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4497 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4501 case D3DTSS_TCI_CAMERASPACENORMAL:
4503 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4504 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4505 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4506 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4507 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4508 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
4510 glMatrixMode(GL_MODELVIEW);
4513 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4514 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4515 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4516 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4519 glEnable(GL_TEXTURE_GEN_S);
4520 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4521 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4522 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4523 glEnable(GL_TEXTURE_GEN_T);
4524 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4525 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4526 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4527 glEnable(GL_TEXTURE_GEN_R);
4528 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4529 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4530 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4535 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
4537 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4538 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4539 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4540 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4541 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4542 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
4544 glMatrixMode(GL_MODELVIEW);
4547 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4548 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4549 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4550 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4553 glEnable(GL_TEXTURE_GEN_S);
4554 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4555 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4556 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4557 glEnable(GL_TEXTURE_GEN_T);
4558 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4559 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4560 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4561 glEnable(GL_TEXTURE_GEN_R);
4562 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4563 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4564 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4569 /* Unhandled types: */
4572 /* ? disable GL_TEXTURE_GEN_n ? */
4573 glDisable(GL_TEXTURE_GEN_S);
4574 glDisable(GL_TEXTURE_GEN_T);
4575 glDisable(GL_TEXTURE_GEN_R);
4576 glDisable(GL_TEXTURE_GEN_Q);
4577 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
4584 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
4585 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);
4588 case WINED3DTSS_BUMPENVMAT00 :
4589 case WINED3DTSS_BUMPENVMAT01 :
4590 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
4592 case WINED3DTSS_BUMPENVMAT10 :
4593 case WINED3DTSS_BUMPENVMAT11 :
4594 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
4597 case WINED3DTSS_BUMPENVLSCALE :
4598 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4601 case WINED3DTSS_BUMPENVLOFFSET :
4602 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4605 case WINED3DTSS_RESULTARG :
4606 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4610 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
4611 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4620 * Get / Set Texture Stage States
4621 * TODO: Verify against dx9 definitions
4623 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
4624 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4626 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4628 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4630 /* Reject invalid texture units */
4631 if (Stage >= GL_LIMITS(textures)) {
4632 TRACE("Attempt to access invalid texture rejected\n");
4633 return WINED3DERR_INVALIDCALL;
4636 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
4637 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
4638 This->updateStateBlock->textureState[Stage][Type] = Value;
4643 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4644 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4645 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4646 *pValue = This->updateStateBlock->textureState[Stage][Type];
4653 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4655 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4656 IWineD3DBaseTexture *oldTexture;
4658 oldTexture = This->updateStateBlock->textures[Stage];
4659 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
4661 #if 0 /* TODO: check so vertex textures */
4662 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
4663 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
4668 /* Reject invalid texture units */
4669 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4670 WARN("Attempt to access invalid texture rejected\n");
4671 return WINED3DERR_INVALIDCALL;
4674 if(pTexture != NULL) {
4675 /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH; The same is
4676 * the case for WINED3DPOOL_SYSTEMMEM textures unless WINED3DDEVCAPS_TEXTURESYSTEMMORY is set.
4677 * We don't check the caps as GetDeviceCaps is inefficient and we don't set the cap anyway.
4679 if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH || ((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SYSTEMMEM) {
4680 WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
4681 return WINED3DERR_INVALIDCALL;
4685 oldTexture = This->updateStateBlock->textures[Stage];
4686 TRACE("GL_LIMITS %d\n",GL_LIMITS(textures));
4687 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
4689 This->updateStateBlock->set.textures[Stage] = TRUE;
4690 This->updateStateBlock->changed.textures[Stage] = TRUE;
4691 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
4692 This->updateStateBlock->textures[Stage] = pTexture;
4694 /* Handle recording of state blocks */
4695 if (This->isRecordingState) {
4696 TRACE("Recording... not performing anything\n");
4700 /** NOTE: MSDN says that setTexture increases the reference count,
4701 * and the the application nust set the texture back to null (or have a leaky application),
4702 * This means we should pass the refcount up to the parent
4703 *******************************/
4704 if (NULL != This->updateStateBlock->textures[Stage]) {
4705 IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
4708 if (NULL != oldTexture) {
4709 IWineD3DBaseTexture_Release(oldTexture);
4715 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4716 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4717 TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
4719 /* Reject invalid texture units */
4720 if (Stage >= GL_LIMITS(textures)) {
4721 TRACE("Attempt to access invalid texture rejected\n");
4722 return WINED3DERR_INVALIDCALL;
4724 *ppTexture=This->updateStateBlock->textures[Stage];
4726 IWineD3DBaseTexture_AddRef(*ppTexture);
4728 return WINED3DERR_INVALIDCALL;
4735 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
4736 IWineD3DSurface **ppBackBuffer) {
4737 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4738 IWineD3DSwapChain *swapChain;
4741 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4743 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4744 if (hr == WINED3D_OK) {
4745 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4746 IWineD3DSwapChain_Release(swapChain);
4748 *ppBackBuffer = NULL;
4753 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4754 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4755 WARN("(%p) : stub, calling idirect3d for now\n", This);
4756 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4759 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
4760 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4761 IWineD3DSwapChain *swapChain;
4764 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4765 if (hr == WINED3D_OK) {
4766 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4767 IWineD3DSwapChain_Release(swapChain);
4769 FIXME("(%p) Error getting display mode\n", This);
4774 HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
4775 FIXME("This is unimplemented for now(d3d7 merge)\n");
4777 return WINED3DERR_INVALIDCALL;
4780 HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
4781 FIXME("This is unimplemented for now(d3d7 merge)\n");
4783 return WINED3DERR_INVALIDCALL;
4787 * Stateblock related functions
4790 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4791 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4792 IWineD3DStateBlockImpl *object;
4793 TRACE("(%p)", This);
4795 if (This->isRecordingState) {
4796 return WINED3DERR_INVALIDCALL;
4799 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4800 if (NULL == object ) {
4801 FIXME("(%p)Error allocating memory for stateblock\n", This);
4802 return E_OUTOFMEMORY;
4804 TRACE("(%p) creted object %p\n", This, object);
4805 object->wineD3DDevice= This;
4806 /** FIXME: object->parent = parent; **/
4807 object->parent = NULL;
4808 object->blockType = WINED3DSBT_ALL;
4810 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
4812 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4813 This->updateStateBlock = object;
4814 This->isRecordingState = TRUE;
4816 TRACE("(%p) recording stateblock %p\n",This , object);
4820 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4821 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4823 if (!This->isRecordingState) {
4824 FIXME("(%p) not recording! returning error\n", This);
4825 *ppStateBlock = NULL;
4826 return WINED3DERR_INVALIDCALL;
4829 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4830 This->isRecordingState = FALSE;
4831 This->updateStateBlock = This->stateBlock;
4832 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4833 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4834 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4839 * Scene related functions
4841 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4842 /* At the moment we have no need for any functionality at the beginning
4844 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4845 TRACE("(%p) : stub\n", This);
4849 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4850 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4851 TRACE("(%p)\n", This);
4853 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4855 checkGLcall("glFlush");
4857 TRACE("End Scene\n");
4858 if(This->renderTarget != NULL) {
4860 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4861 IUnknown *targetContainer = NULL;
4862 if (WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
4863 || WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
4864 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
4865 /** always dirtify for now. we must find a better way to see that surface have been modified
4866 (Modifications should will only occur via draw-primitive, but we do need better locking
4867 switching to render-to-texture should remove the overhead though.
4869 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4870 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
4871 IWineD3DSurface_PreLoad(This->renderTarget);
4872 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4873 IUnknown_Release(targetContainer);
4876 This->sceneEnded = TRUE;
4881 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4882 CONST RECT* pSourceRect, CONST RECT* pDestRect,
4883 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4884 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4885 IWineD3DSwapChain *swapChain = NULL;
4887 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4889 TRACE("(%p) Presenting the frame\n", This);
4891 for(i = 0 ; i < swapchains ; i ++) {
4893 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4894 TRACE("presentinng chain %d, %p\n", i, swapChain);
4895 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4896 IWineD3DSwapChain_Release(swapChain);
4902 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4903 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4904 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4906 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4907 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4908 when the depth-buffer format does not contain stencil buffer information, this method fails. */
4909 GLbitfield glMask = 0;
4910 GLboolean old_ztest;
4911 GLfloat old_z_clear_value;
4912 GLint old_stencil_clear_value;
4913 GLfloat old_color_clear_value[4];
4915 CONST D3DRECT* curRect;
4917 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4918 Count, pRects, Flags, Z, Stencil);
4922 glEnable(GL_SCISSOR_TEST);
4923 checkGLcall("glEnable GL_SCISSOR_TEST");
4925 if (Count > 0 && pRects) {
4931 /* Only set the values up once, as they are not changing */
4932 if (Flags & D3DCLEAR_STENCIL) {
4933 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4934 glClearStencil(Stencil);
4935 checkGLcall("glClearStencil");
4936 glMask = glMask | GL_STENCIL_BUFFER_BIT;
4937 glStencilMask(0xFFFFFFFF);
4940 if (Flags & D3DCLEAR_ZBUFFER) {
4941 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4942 glDepthMask(GL_TRUE);
4943 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4945 checkGLcall("glClearDepth");
4946 glMask = glMask | GL_DEPTH_BUFFER_BIT;
4949 if (Flags & D3DCLEAR_TARGET) {
4950 TRACE("Clearing screen with glClear to color %lx\n", Color);
4951 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4952 glClearColor(D3DCOLOR_R(Color),
4956 checkGLcall("glClearColor");
4958 /* Clear ALL colors! */
4959 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4960 glMask = glMask | GL_COLOR_BUFFER_BIT;
4963 /* Now process each rect in turn */
4964 for (i = 0; i < Count || i == 0; i++) {
4967 /* Note gl uses lower left, width/height */
4968 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4969 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4970 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4971 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4972 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4973 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4974 checkGLcall("glScissor");
4976 glScissor(This->stateBlock->viewport.X,
4977 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
4978 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4979 This->stateBlock->viewport.Width,
4980 This->stateBlock->viewport.Height);
4981 checkGLcall("glScissor");
4984 /* Clear the selected rectangle (or full screen) */
4986 checkGLcall("glClear");
4988 /* Step to the next rectangle */
4989 if (curRect) curRect = curRect + sizeof(D3DRECT);
4992 /* Restore the old values (why..?) */
4993 if (Flags & D3DCLEAR_STENCIL) {
4994 glClearStencil(old_stencil_clear_value);
4995 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4997 if (Flags & D3DCLEAR_ZBUFFER) {
4998 glDepthMask(old_ztest);
4999 glClearDepth(old_z_clear_value);
5001 if (Flags & D3DCLEAR_TARGET) {
5002 glClearColor(old_color_clear_value[0],
5003 old_color_clear_value[1],
5004 old_color_clear_value[2],
5005 old_color_clear_value[3]);
5006 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
5007 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
5008 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
5009 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
5012 glDisable(GL_SCISSOR_TEST);
5013 checkGLcall("glDisable");
5022 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
5023 UINT PrimitiveCount) {
5025 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5026 This->stateBlock->streamIsUP = FALSE;
5028 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
5029 debug_d3dprimitivetype(PrimitiveType),
5030 StartVertex, PrimitiveCount);
5031 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
5032 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
5038 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
5039 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
5040 D3DPRIMITIVETYPE PrimitiveType,
5041 INT baseVIndex, UINT minIndex,
5042 UINT NumVertices, UINT startIndex, UINT primCount) {
5044 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5046 IWineD3DIndexBuffer *pIB;
5047 WINED3DINDEXBUFFER_DESC IdxBufDsc;
5049 pIB = This->stateBlock->pIndexData;
5050 This->stateBlock->streamIsUP = FALSE;
5052 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
5053 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5054 minIndex, NumVertices, startIndex, baseVIndex, primCount);
5056 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
5057 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
5063 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
5064 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
5069 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
5070 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
5071 UINT VertexStreamZeroStride) {
5072 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5074 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
5075 debug_d3dprimitivetype(PrimitiveType),
5076 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
5078 /* release the stream source */
5079 if (This->stateBlock->streamSource[0] != NULL) {
5080 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5083 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5084 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5085 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5086 This->stateBlock->streamIsUP = TRUE;
5088 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
5089 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
5090 /* stream zero settings set to null at end, as per the msdn
5091 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
5093 This->stateBlock->streamStride[0] = 0;
5094 This->stateBlock->streamSource[0] = NULL;
5096 /*stream zero settings set to null at end, as per the msdn */
5100 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
5101 UINT MinVertexIndex, UINT NumVertices,
5102 UINT PrimitiveCount, CONST void* pIndexData,
5103 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
5104 UINT VertexStreamZeroStride) {
5106 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5108 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
5109 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5110 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
5111 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
5113 if (IndexDataFormat == WINED3DFMT_INDEX16) {
5119 /* release the stream and index data */
5120 if (This->stateBlock->streamSource[0] != NULL) {
5121 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5123 if (This->stateBlock->pIndexData) {
5124 IWineD3DIndexBuffer_Release(This->stateBlock->pIndexData);
5127 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5128 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5129 This->stateBlock->streamIsUP = TRUE;
5130 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5132 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
5133 /* stream zero settings set to null at end as per the msdn
5134 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
5137 /* stream zero settings set to null at end as per the msdn */
5138 This->stateBlock->streamSource[0] = NULL;
5139 This->stateBlock->streamStride[0] = 0;
5144 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
5145 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
5146 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5147 HRESULT hr = WINED3D_OK;
5148 WINED3DRESOURCETYPE sourceType;
5149 WINED3DRESOURCETYPE destinationType;
5152 /* TODO: think about moving the code into IWineD3DBaseTexture */
5154 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
5156 /* verify that the source and destination textures aren't NULL */
5157 if (NULL == pSourceTexture || NULL == pDestinationTexture) {
5158 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
5159 This, pSourceTexture, pDestinationTexture);
5160 hr = WINED3DERR_INVALIDCALL;
5163 if (pSourceTexture == pDestinationTexture) {
5164 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
5165 This, pSourceTexture, pDestinationTexture);
5166 hr = WINED3DERR_INVALIDCALL;
5168 /* Verify that the source and destination textures are the same type */
5169 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
5170 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
5172 if (sourceType != destinationType) {
5173 WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
5175 hr = WINED3DERR_INVALIDCALL;
5178 /* check that both textures have the identical numbers of levels */
5179 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
5180 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
5181 hr = WINED3DERR_INVALIDCALL;
5184 if (WINED3D_OK == hr) {
5186 /* Make sure that the destination texture is loaded */
5187 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
5189 /* Update every surface level of the texture */
5190 levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
5192 switch (sourceType) {
5193 case WINED3DRTYPE_TEXTURE:
5195 IWineD3DSurface *srcSurface;
5196 IWineD3DSurface *destSurface;
5198 for (i = 0 ; i < levels ; ++i) {
5199 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture, i, &srcSurface);
5200 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
5201 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5202 IWineD3DSurface_Release(srcSurface);
5203 IWineD3DSurface_Release(destSurface);
5204 if (WINED3D_OK != hr) {
5205 WARN("(%p) : Call to update surface failed\n", This);
5211 case WINED3DRTYPE_CUBETEXTURE:
5213 IWineD3DSurface *srcSurface;
5214 IWineD3DSurface *destSurface;
5215 WINED3DCUBEMAP_FACES faceType;
5217 for (i = 0 ; i < levels ; ++i) {
5218 /* Update each cube face */
5219 for (faceType = D3DCUBEMAP_FACE_POSITIVE_X; faceType <= D3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
5220 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture, faceType, i, &srcSurface);
5221 if (WINED3D_OK != hr) {
5222 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5224 TRACE("Got srcSurface %p\n", srcSurface);
5226 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
5227 if (WINED3D_OK != hr) {
5228 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5230 TRACE("Got desrSurface %p\n", destSurface);
5232 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5233 IWineD3DSurface_Release(srcSurface);
5234 IWineD3DSurface_Release(destSurface);
5235 if (WINED3D_OK != hr) {
5236 WARN("(%p) : Call to update surface failed\n", This);
5243 #if 0 /* TODO: Add support for volume textures */
5244 case WINED3DRTYPE_VOLUMETEXTURE:
5246 IWineD3DVolume srcVolume = NULL;
5247 IWineD3DSurface destVolume = NULL;
5249 for (i = 0 ; i < levels ; ++i) {
5250 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture, i, &srcVolume);
5251 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
5252 hr = IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
5253 IWineD3DVolume_Release(srcSurface);
5254 IWineD3DVolume_Release(destSurface);
5255 if (WINED3D_OK != hr) {
5256 WARN("(%p) : Call to update volume failed\n", This);
5264 FIXME("(%p) : Unsupported source and destination type\n", This);
5265 hr = WINED3DERR_INVALIDCALL;
5272 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
5273 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
5274 CONST RECT* pDestRect, WINED3DTEXTUREFILTERTYPE Filter) {
5275 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5277 TRACE("(%p) : stub\n", This);
5280 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
5281 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5282 /** TODO: remove remove casts to IWineD3DSurfaceImpl *
5283 * NOTE It may be best to move the code into surface to occomplish this
5284 ****************************************/
5286 WINED3DSURFACE_DESC surfaceDesc;
5287 unsigned int surfaceWidth, surfaceHeight;
5288 glDescriptor *targetGlDescription = NULL;
5289 glDescriptor *surfaceGlDescription = NULL;
5290 IWineD3DSwapChainImpl *container = NULL;
5292 IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
5293 IWineD3DSurface_GetGlDesc(pSurface, &surfaceGlDescription);
5294 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5296 surfaceDesc.Width = &surfaceWidth;
5297 surfaceDesc.Height = &surfaceHeight;
5298 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5299 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
5301 /* Ok, I may need to setup some kind of active swapchain reference on the device */
5302 IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
5304 /* TODO: opengl Context switching for swapchains etc... */
5305 if (NULL != container || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
5306 if (NULL != container && (pRenderTarget == container->backBuffer)) {
5307 glReadBuffer(GL_BACK);
5308 vcheckGLcall("glReadBuffer(GL_BACK)");
5309 } else if ((NULL != container && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
5310 glReadBuffer(GL_FRONT);
5311 vcheckGLcall("glReadBuffer(GL_FRONT)");
5312 } else if (pRenderTarget == This->depthStencilBuffer) {
5313 FIXME("Reading of depthstencil not yet supported\n");
5316 glReadPixels(surfaceGlDescription->target,
5317 surfaceGlDescription->level,
5320 surfaceGlDescription->glFormat,
5321 surfaceGlDescription->glType,
5322 (void *)IWineD3DSurface_GetData(pSurface));
5323 vcheckGLcall("glReadPixels(...)");
5324 if(NULL != container ){
5325 IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
5328 IWineD3DBaseTexture *container;
5329 GLenum textureDimensions = GL_TEXTURE_2D;
5331 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
5332 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
5333 IWineD3DBaseTexture_Release(container);
5335 /* TODO: 2D -> Cube surface coppies etc.. */
5336 if (surfaceGlDescription->target != textureDimensions) {
5337 FIXME("(%p) : Texture dimension mismatch\n", This);
5339 glEnable(textureDimensions);
5340 vcheckGLcall("glEnable(GL_TEXTURE_...)");
5341 /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
5342 glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
5343 vcheckGLcall("glBindTexture");
5344 glGetTexImage(surfaceGlDescription->target,
5345 surfaceGlDescription->level,
5346 surfaceGlDescription->glFormat,
5347 surfaceGlDescription->glType,
5348 (void *)IWineD3DSurface_GetData(pSurface));
5349 glDisable(textureDimensions);
5350 vcheckGLcall("glDisable(GL_TEXTURE_...)");
5357 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
5358 IWineD3DSwapChain *swapChain;
5360 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5361 if(hr == WINED3D_OK) {
5362 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
5363 IWineD3DSwapChain_Release(swapChain);
5368 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5369 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5370 /* return a sensible default */
5372 /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
5373 FIXME("(%p) : stub\n", This);
5377 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5378 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5380 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5381 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5382 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5383 return WINED3DERR_INVALIDCALL;
5385 for (j = 0; j < 256; ++j) {
5386 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
5387 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5388 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
5389 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5391 TRACE("(%p) : returning\n", This);
5395 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5396 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5398 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5399 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5400 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5401 return WINED3DERR_INVALIDCALL;
5403 for (j = 0; j < 256; ++j) {
5404 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
5405 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5406 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
5407 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5409 TRACE("(%p) : returning\n", This);
5413 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5414 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5415 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5416 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5417 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5418 return WINED3DERR_INVALIDCALL;
5420 /*TODO: stateblocks */
5421 This->currentPalette = PaletteNumber;
5422 TRACE("(%p) : returning\n", This);
5426 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
5427 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5428 if (PaletteNumber == NULL) {
5429 WARN("(%p) : returning Invalid Call\n", This);
5430 return WINED3DERR_INVALIDCALL;
5432 /*TODO: stateblocks */
5433 *PaletteNumber = This->currentPalette;
5434 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
5438 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
5439 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5440 static BOOL showFixmes = TRUE;
5442 FIXME("(%p) : stub\n", This);
5446 This->softwareVertexProcessing = bSoftware;
5451 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
5452 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5453 static BOOL showFixmes = TRUE;
5455 FIXME("(%p) : stub\n", This);
5458 return This->softwareVertexProcessing;
5462 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
5463 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5464 IWineD3DSwapChain *swapChain;
5467 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
5469 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5470 if(hr == WINED3D_OK){
5471 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
5472 IWineD3DSwapChain_Release(swapChain);
5474 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
5480 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
5481 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5482 static BOOL showfixmes = TRUE;
5483 if(nSegments != 0.0f) {
5485 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
5492 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
5493 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5494 static BOOL showfixmes = TRUE;
5496 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
5502 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
5503 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5504 /** TODO: remove casts to IWineD3DSurfaceImpl
5505 * NOTE: move code to surface to accomplish this
5506 ****************************************/
5507 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
5508 int srcWidth, srcHeight;
5509 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
5510 WINED3DFORMAT destFormat, srcFormat;
5512 int destLeft, destTop;
5513 WINED3DPOOL srcPool, destPool;
5515 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
5516 glDescriptor *glDescription = NULL;
5517 GLenum textureDimensions = GL_TEXTURE_2D;
5518 IWineD3DBaseTexture *baseTexture;
5520 WINED3DSURFACE_DESC winedesc;
5522 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
5523 memset(&winedesc, 0, sizeof(winedesc));
5524 winedesc.Width = &srcSurfaceWidth;
5525 winedesc.Height = &srcSurfaceHeight;
5526 winedesc.Pool = &srcPool;
5527 winedesc.Format = &srcFormat;
5529 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5531 winedesc.Width = &destSurfaceWidth;
5532 winedesc.Height = &destSurfaceHeight;
5533 winedesc.Pool = &destPool;
5534 winedesc.Format = &destFormat;
5535 winedesc.Size = &destSize;
5537 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5539 if(srcPool != WINED3DPOOL_SYSTEMMEM || destPool != WINED3DPOOL_DEFAULT){
5540 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
5541 return WINED3DERR_INVALIDCALL;
5544 if (destFormat == WINED3DFMT_UNKNOWN) {
5545 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5546 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5548 /* Get the update surface description */
5549 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5552 /* Make sure the surface is loaded and up to date */
5553 IWineD3DSurface_PreLoad(pDestinationSurface);
5555 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
5559 /* this needs to be done in lines if the sourceRect != the sourceWidth */
5560 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
5561 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
5562 destLeft = pDestPoint ? pDestPoint->x : 0;
5563 destTop = pDestPoint ? pDestPoint->y : 0;
5566 /* This function doesn't support compressed textures
5567 the pitch is just bytesPerPixel * width */
5568 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
5569 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
5570 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
5571 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
5573 /* TODO DXT formats */
5575 if(pSourceRect != NULL && pSourceRect->top != 0){
5576 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
5578 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
5580 ,glDescription->level
5585 ,glDescription->glFormat
5586 ,glDescription->glType
5587 ,IWineD3DSurface_GetData(pSourceSurface)
5591 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
5593 /* need to lock the surface to get the data */
5594 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5597 /* TODO: Cube and volume support */
5599 /* not a whole row so we have to do it a line at a time */
5602 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
5603 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5605 for(j = destTop ; j < (srcHeight + destTop) ; j++){
5607 glTexSubImage2D(glDescription->target
5608 ,glDescription->level
5613 ,glDescription->glFormat
5614 ,glDescription->glType
5615 ,data /* could be quicker using */
5620 } else { /* Full width, so just write out the whole texture */
5622 if (WINED3DFMT_DXT1 == destFormat ||
5623 WINED3DFMT_DXT2 == destFormat ||
5624 WINED3DFMT_DXT3 == destFormat ||
5625 WINED3DFMT_DXT4 == destFormat ||
5626 WINED3DFMT_DXT5 == destFormat) {
5627 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
5628 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
5629 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
5630 FIXME("Updating part of a compressed texture is not supported at the moment\n");
5631 } if (destFormat != srcFormat) {
5632 FIXME("Updating mixed format compressed texture is not curretly support\n");
5634 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
5635 glDescription->level,
5636 glDescription->glFormatInternal,
5641 IWineD3DSurface_GetData(pSourceSurface));
5644 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
5649 if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
5651 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
5652 to repack the data from pow2Width/Height to expected Width,Height, this makes the
5653 data returned by GetData non-power2 width/height with hardware non-power2
5654 pow2Width/height are set to surface width height, repacking isn't needed so it
5655 doesn't matter which function gets called. */
5656 glTexSubImage2D(glDescription->target
5657 ,glDescription->level
5662 ,glDescription->glFormat
5663 ,glDescription->glType
5664 ,IWineD3DSurface_GetData(pSourceSurface)
5668 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
5669 glTexSubImage2D(glDescription->target
5670 ,glDescription->level
5673 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
5674 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
5675 ,glDescription->glFormat
5676 ,glDescription->glType
5677 ,IWineD3DSurface_GetData(pSourceSurface)
5683 checkGLcall("glTexSubImage2D");
5685 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
5686 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
5687 * surface bigger than it needs to be hmm.. */
5688 if (WINED3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
5689 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
5690 IWineD3DBaseTexture_Release(baseTexture);
5693 glDisable(textureDimensions); /* This needs to be managed better.... */
5699 /* Used by DirectX 8 */
5700 HRESULT WINAPI IWineD3DDeviceImpl_CopyRects(IWineD3DDevice *iface,
5701 IWineD3DSurface* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
5702 IWineD3DSurface* pDestinationSurface, CONST POINT* pDestPointsArray) {
5704 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5705 HRESULT hr = WINED3D_OK;
5706 WINED3DFORMAT srcFormat, destFormat;
5707 UINT srcWidth, destWidth;
5708 UINT srcHeight, destHeight;
5710 WINED3DSURFACE_DESC winedesc;
5712 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
5713 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
5716 /* Check that the source texture is in WINED3DPOOL_SYSTEMMEM and the destination texture is in WINED3DPOOL_DEFAULT */
5717 memset(&winedesc, 0, sizeof(winedesc));
5719 winedesc.Format = &srcFormat;
5720 winedesc.Width = &srcWidth;
5721 winedesc.Height = &srcHeight;
5722 winedesc.Size = &srcSize;
5723 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5725 winedesc.Format = &destFormat;
5726 winedesc.Width = &destWidth;
5727 winedesc.Height = &destHeight;
5728 winedesc.Size = NULL;
5729 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5731 /* Check that the source and destination formats match */
5732 if (srcFormat != destFormat && WINED3DFMT_UNKNOWN != destFormat) {
5733 WARN("(%p) source %p format must match the dest %p format, returning WINED3DERR_INVALIDCALL\n", This, pSourceSurface, pDestinationSurface);
5734 return WINED3DERR_INVALIDCALL;
5735 } else if (WINED3DFMT_UNKNOWN == destFormat) {
5736 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5737 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5738 destFormat = srcFormat;
5741 /* Quick if complete copy ... */
5742 if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
5744 if (srcWidth == destWidth && srcHeight == destHeight) {
5745 WINED3DLOCKED_RECT lrSrc;
5746 WINED3DLOCKED_RECT lrDst;
5747 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, NULL, WINED3DLOCK_READONLY);
5748 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, NULL, 0L);
5749 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", srcWidth, srcHeight);
5751 memcpy(lrDst.pBits, lrSrc.pBits, srcSize);
5753 IWineD3DSurface_UnlockRect(pSourceSurface);
5754 IWineD3DSurface_UnlockRect(pDestinationSurface);
5755 TRACE("Unlocked src and dst\n");
5759 FIXME("Wanted to copy all surfaces but size not compatible, returning WINED3DERR_INVALIDCALL\n");
5760 hr = WINED3DERR_INVALIDCALL;
5765 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
5767 int bytesPerPixel = ((IWineD3DSurfaceImpl *) pSourceSurface)->bytesPerPixel;
5770 /* Copy rect by rect */
5771 for (i = 0; i < cRects; ++i) {
5772 CONST RECT* r = &pSourceRectsArray[i];
5773 CONST POINT* p = &pDestPointsArray[i];
5776 WINED3DLOCKED_RECT lrSrc;
5777 WINED3DLOCKED_RECT lrDst;
5780 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
5781 if (srcFormat == WINED3DFMT_DXT1) {
5782 copyperline = ((r->right - r->left) * bytesPerPixel) / 2; /* DXT1 is half byte per pixel */
5784 copyperline = ((r->right - r->left) * bytesPerPixel);
5787 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, r, WINED3DLOCK_READONLY);
5788 dest_rect.left = p->x;
5789 dest_rect.top = p->y;
5790 dest_rect.right = p->x + (r->right - r->left);
5791 dest_rect.bottom= p->y + (r->bottom - r->top);
5792 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, &dest_rect, 0L);
5793 TRACE("Locked src and dst\n");
5795 /* Find where to start */
5796 for (j = 0; j < (r->bottom - r->top - 1); ++j) {
5797 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
5799 IWineD3DSurface_UnlockRect(pSourceSurface);
5800 IWineD3DSurface_UnlockRect(pDestinationSurface);
5801 TRACE("Unlocked src and dst\n");
5804 FIXME("Wanted to copy partial surfaces not implemented, returning WINED3DERR_INVALIDCALL\n");
5805 hr = WINED3DERR_INVALIDCALL;
5812 /* Implementation details at http://developer.nvidia.com/attach/6494
5814 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
5815 hmm.. no longer supported use
5816 OpenGL evaluators or tessellate surfaces within your application.
5819 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
5820 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
5821 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5822 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
5823 FIXME("(%p) : Stub\n", This);
5828 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
5829 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
5830 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5831 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
5832 FIXME("(%p) : Stub\n", This);
5836 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5837 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5838 TRACE("(%p) Handle(%d)\n", This, Handle);
5839 FIXME("(%p) : Stub\n", This);
5843 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
5844 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
5845 fill a surface with a block of color! */
5846 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5847 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
5848 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
5849 IWineD3DSwapChainImpl *container = NULL;
5850 BOOL isRenderTarget = FALSE;
5851 unsigned int width, height;
5852 unsigned int top, left;
5855 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
5857 if (surface->resource.pool != WINED3DPOOL_DEFAULT) {
5858 FIXME("call to colorfill with non WINED3DPOOL_DEFAULT surface\n");
5859 return WINED3DERR_INVALIDCALL;
5862 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
5863 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
5864 if (WINED3DUSAGE_RENDERTARGET & surface->resource.usage) {
5865 /* TODO: make sure we set everything back to the way it was, and context management!
5866 glGetIntegerv(GL_READ_BUFFER, &prev_read);
5867 vcheckGLcall("glIntegerv");
5868 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
5869 vcheckGLcall("glIntegerv");
5871 TRACE("Color fill to render targets may cause some graphics issues\n");
5872 if (pSurface == container->frontBuffer) {
5873 glDrawBuffer(GL_FRONT);
5875 glDrawBuffer(GL_BACK);
5878 if (WINED3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
5879 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld\n", surface, surface->resource.usage);
5881 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
5883 if (container != NULL) {
5884 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5886 /* we can use GL_STENCIL_INDEX etc...*/
5889 if (container != NULL) {
5890 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5892 isRenderTarget = TRUE;
5894 /* TODO: drawing to GL_FRONT and GL_BACK */
5895 /* TODO: see if things can be speeded up by using the correct
5896 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
5897 if (pRect == NULL) {
5900 width = surface->currentDesc.Width;
5901 height = surface->currentDesc.Height;
5905 width = pRect->x2 - left;
5906 height = pRect->y2 - top;
5909 data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
5910 /* Create a 'line' of color color, in the correct format for the surface */
5911 for (u = 0 ; u < width ; u ++) {
5916 if (isRenderTarget == FALSE) {
5917 glDescriptor *glDesc;
5918 IWineD3DSurface_PreLoad(pSurface);
5920 /* draw a block of the coloured line on the sufrace */
5921 IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
5922 for (v = 0 ; v< height;v++) {
5923 glTexSubImage2D(glDesc->target
5924 ,glDesc->level /* level */
5934 checkGLcall("glTexSubImage2D");
5936 glDisable(glDesc->target);
5938 /** FIXME: Using GLClear may be faster **/
5939 glRasterPos2i(left, top);
5940 glPixelZoom((float)width ,(float)height);
5941 glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
5942 checkGLcall("glDrawPixels");
5944 HeapFree(GetProcessHeap(), 0, data);
5950 /* rendertarget and deptth stencil functions */
5951 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
5952 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5954 /* FIXME: Implelent RenderTargetIndex >0 */
5955 if(RenderTargetIndex > 0)
5956 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
5958 *ppRenderTarget = This->renderTarget;
5959 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
5960 /* Note inc ref on returned surface */
5961 if(*ppRenderTarget != NULL)
5962 IWineD3DSurface_AddRef(*ppRenderTarget);
5966 HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
5967 FIXME("This call is a d3d7 merge stub. It will be implemented later\n");
5968 return WINED3DERR_INVALIDCALL;
5971 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5972 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5973 *ppZStencilSurface = This->depthStencilBuffer;
5974 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
5976 if(*ppZStencilSurface != NULL) {
5977 /* Note inc ref on returned surface */
5978 IWineD3DSurface_AddRef(*ppZStencilSurface);
5983 /* internal static helper functions */
5984 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5985 IWineD3DSurface *RenderSurface);
5987 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5988 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5989 HRESULT hr = WINED3D_OK;
5990 WINED3DVIEWPORT viewport;
5992 TRACE("(%p) Swapping rendertarget\n",This);
5993 if (RenderTargetIndex > 0) {
5994 FIXME("(%p) Render targets other than the first are not supported\n",This);
5995 RenderTargetIndex = 0;
5998 /* MSDN says that null disables the render target
5999 but a device must always be associated with a render target
6000 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
6002 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
6005 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
6006 FIXME("Trying to set render target 0 to NULL\n");
6007 return WINED3DERR_INVALIDCALL;
6009 /* TODO: replace Impl* usage with interface usage */
6010 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
6011 FIXME("(%p)Trying to set the render target to a surface(%p) that wasn't created with a usage of WINED3DUSAGE_RENDERTARGET\n",This ,pRenderTarget);
6012 return WINED3DERR_INVALIDCALL;
6014 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
6015 * builds, but I think wine counts as a 'debug' build for now.
6016 ******************************/
6017 /* If we are trying to set what we already have, don't bother */
6018 if (pRenderTarget == This->renderTarget) {
6019 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6021 /* Otherwise, set the render target up */
6023 if (FALSE == This->sceneEnded) {
6024 IWineD3DDevice_EndScene(iface);
6026 TRACE("clearing renderer\n");
6027 /* IWineD3DDeviceImpl_CleanRender(iface); */
6028 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6029 depending on the renter target implementation being used.
6030 A shared context implementation will share all buffers between all rendertargets (including swapchains),
6031 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6032 stencil buffer and incure an extra memory overhead */
6033 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
6036 if (SUCCEEDED(hr)) {
6037 /* Finally, reset the viewport as the MSDN states. */
6038 /* TODO: Replace impl usage */
6039 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
6040 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
6043 viewport.MaxZ = 1.0f;
6044 viewport.MinZ = 0.0f;
6045 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
6047 FIXME("Unknown error setting the render target\n");
6049 This->sceneEnded = FALSE;
6053 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
6054 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6055 HRESULT hr = WINED3D_OK;
6056 IWineD3DSurface *tmp;
6058 TRACE("(%p) Swapping z-buffer\n",This);
6060 if (pNewZStencil == This->stencilBufferTarget) {
6061 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6063 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6064 * depending on the renter target implementation being used.
6065 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
6066 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6067 * stencil buffer and incure an extra memory overhead
6068 ******************************************************/
6071 tmp = This->stencilBufferTarget;
6072 This->stencilBufferTarget = pNewZStencil;
6073 /* should we be calling the parent or the wined3d surface? */
6074 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
6075 if (NULL != tmp) IWineD3DSurface_Release(tmp);
6077 /** TODO: glEnable/glDisable on depth/stencil depending on
6078 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
6079 **********************************************************/
6086 #ifdef GL_VERSION_1_3
6087 /* Internal functions not in DirectX */
6088 /** TODO: move this off to the opengl context manager
6089 *(the swapchain doesn't need to know anything about offscreen rendering!)
6090 ****************************************************/
6092 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
6094 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6096 TRACE("(%p), %p\n", This, swapchain);
6098 if (swapchain->win != swapchain->drawable) {
6099 /* Set everything back the way it ws */
6100 swapchain->render_ctx = swapchain->glCtx;
6101 swapchain->drawable = swapchain->win;
6106 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
6107 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
6108 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6111 unsigned int height;
6112 WINED3DFORMAT format;
6113 WINED3DSURFACE_DESC surfaceDesc;
6114 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
6115 surfaceDesc.Width = &width;
6116 surfaceDesc.Height = &height;
6117 surfaceDesc.Format = &format;
6118 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
6120 /* I need a get width/height function (and should do something with the format) */
6121 for (i = 0; i < CONTEXT_CACHE; ++i) {
6122 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
6123 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
6124 the pSurface can be set to 0 allowing it to be reused from cache **/
6125 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
6126 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
6127 *context = &This->contextCache[i];
6130 if (This->contextCache[i].Width == 0) {
6131 This->contextCache[i].pSurface = pSurface;
6132 This->contextCache[i].Width = width;
6133 This->contextCache[i].Height = height;
6134 *context = &This->contextCache[i];
6138 if (i == CONTEXT_CACHE) {
6139 int minUsage = 0x7FFFFFFF; /* MAX_INT */
6140 glContext *dropContext = 0;
6141 for (i = 0; i < CONTEXT_CACHE; i++) {
6142 if (This->contextCache[i].usedcount < minUsage) {
6143 dropContext = &This->contextCache[i];
6144 minUsage = This->contextCache[i].usedcount;
6147 /* clean up the context (this doesn't work for ATI at the moment */
6149 glXDestroyContext(swapchain->display, dropContext->context);
6150 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
6153 dropContext->Width = 0;
6154 dropContext->pSurface = pSurface;
6155 *context = dropContext;
6157 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
6158 for (i = 0; i < CONTEXT_CACHE; i++) {
6159 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
6163 if (*context != NULL)
6166 return E_OUTOFMEMORY;
6170 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
6171 * the functionality needs splitting up so that we don't do more than we should do.
6172 * this only seems to impact performance a little.
6173 ******************************/
6174 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
6175 IWineD3DSurface *RenderSurface) {
6176 HRESULT ret = WINED3DERR_INVALIDCALL;
6179 * Currently only active for GLX >= 1.3
6180 * for others versions we'll have to use GLXPixmaps
6182 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
6183 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
6184 * so only check OpenGL version
6185 * ..........................
6186 * I don't believe that it is a problem with NVidia headers,
6187 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
6188 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
6190 * Your application will report GLX version 1.2 on glXQueryVersion.
6191 * However, it is safe to call the GLX 1.3 functions as described below.
6193 #if defined(GL_VERSION_1_3)
6195 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6196 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
6197 IWineD3DSurface *tmp;
6198 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
6199 GLXFBConfig* cfgs = NULL;
6203 IWineD3DSwapChain *currentSwapchain;
6204 IWineD3DSwapChainImpl *swapchain;
6205 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
6206 * but switch them off if the StencilSurface is set to NULL
6207 ** *********************************************************/
6208 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
6209 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
6212 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
6213 it StencilSurface != NULL && zBufferTarget == NULL switch it on
6216 #define PUSH1(att) attribs[nAttribs++] = (att);
6217 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
6219 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
6221 /** TODO: remove the reff to Impl (context manager should fix this!) **/
6222 IWineD3DSwapChainImpl *impSwapChain;
6223 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
6224 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
6225 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
6230 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
6231 PUSH2(GLX_X_RENDERABLE, TRUE);
6232 PUSH2(GLX_DOUBLEBUFFER, TRUE);
6233 TRACE("calling makeglcfg\n");
6234 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
6237 TRACE("calling chooseFGConfig\n");
6238 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
6241 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
6242 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
6243 why we failed and only show this message once! */
6244 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"); /**/
6246 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
6247 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
6248 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
6249 PUSH2(GLX_DOUBLEBUFFER, FALSE);
6250 TRACE("calling makeglcfg\n");
6251 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
6253 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
6260 for (i = 0; i < nCfgs; ++i) {
6261 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
6262 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
6263 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
6266 if (NULL != This->renderTarget) {
6268 vcheckGLcall("glFlush");
6269 /** This is only useful if the old render target was a swapchain,
6270 * we need to supercede this with a function that displays
6271 * the current buffer on the screen. This is easy to do in glx1.3 but
6272 * we need to do copy-write pixels in glx 1.2.
6273 ************************************************/
6274 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
6276 printf("Hit Enter to get next frame ...\n");
6282 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain) != WINED3D_OK) {
6283 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
6284 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
6288 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
6289 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
6290 **********************************************************************/
6291 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == WINED3D_OK) {
6292 /* We also need to make sure that the lights &co are also in the context of the swapchains */
6293 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
6294 TRACE("making swapchain active\n");
6295 if (RenderSurface != This->renderTarget) {
6296 if (RenderSurface == swapchain->backBuffer) {
6298 /* This could be flagged so that some operations work directly with the front buffer */
6299 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
6301 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
6303 TRACE("Error in setting current context: context %p drawable %ld !\n",
6304 impSwapChain->glCtx, impSwapChain->win);
6307 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
6309 checkGLcall("glXMakeContextCurrent");
6311 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
6313 else if (pbuffer_support == TRUE && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
6315 /** ********************************************************************
6316 * This is a quickly hacked out implementation of offscreen textures.
6317 * It will work in most cases but there may be problems if the client
6318 * modifies the texture directly, or expects the contents of the rendertarget
6321 * There are some real speed vs compatibility issues here:
6322 * we should really use a new context for every texture, but that eats ram.
6323 * we should also be restoring the texture to the pbuffer but that eats CPU
6324 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
6325 * but if this means reusing the display backbuffer then we need to make sure that
6326 * states are correctly preserved.
6327 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
6328 * and gain a good performance increase at the cost of compatibility.
6329 * I would suggest that, when this is the case, a user configurable flag be made
6330 * available, allowing the user to choose the best emulated experience for them.
6331 *********************************************************************/
6333 XVisualInfo *visinfo;
6334 glContext *newContext;
6336 /* Here were using a shared context model */
6337 if (WINED3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
6338 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6341 /* If the context doesn't exist then create a new one */
6342 /* TODO: This should really be part of findGlContext */
6343 if (NULL == newContext->context) {
6345 TRACE("making new buffer\n");
6347 PUSH2(GLX_PBUFFER_WIDTH, newContext->Width);
6348 PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
6351 newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
6353 /** ****************************************
6354 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
6356 * In future releases, we may provide the calls glXCreateNewContext,
6357 * glXQueryDrawable and glXMakeContextCurrent.
6358 * so until then we have to use glXGetVisualFromFBConfig &co..
6359 ********************************************/
6362 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
6364 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
6366 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
6370 if (NULL == newContext || NULL == newContext->context) {
6371 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6373 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
6374 if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
6375 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
6378 /* Clean up the old context */
6379 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
6380 /* Set the current context of the swapchain to the new context */
6381 impSwapChain->drawable = newContext->drawable;
6382 impSwapChain->render_ctx = newContext->context;
6386 #if 1 /* Apply the stateblock to the new context
6387 FIXME: This is a bit of a hack, each context should know it's own state,
6388 the directX current directX state should then be applied to the context */
6391 IWineD3DStateBlockImpl *oldUpdateStateBlock;
6392 oldUpdateStateBlock = This->updateStateBlock;
6393 oldRecording= This->isRecordingState;
6394 This->isRecordingState = FALSE;
6395 This->updateStateBlock = This->stateBlock;
6396 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
6398 This->isRecordingState = oldRecording;
6399 This->updateStateBlock = oldUpdateStateBlock;
6404 /* clean up the current rendertargets swapchain (if it belonged to one) */
6405 if (currentSwapchain != NULL) {
6406 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
6409 /* Were done with the opengl context management, setup the rendertargets */
6411 tmp = This->renderTarget;
6412 This->renderTarget = RenderSurface;
6413 IWineD3DSurface_AddRef(This->renderTarget);
6414 IWineD3DSurface_Release(tmp);
6420 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
6421 /* Check that the container is not a swapchain member */
6423 IWineD3DSwapChain *tmpSwapChain;
6424 if (WINED3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
6425 This->renderUpsideDown = TRUE;
6427 This->renderUpsideDown = FALSE;
6428 IWineD3DSwapChain_Release(tmpSwapChain);
6430 /* Force updating the cull mode */
6431 TRACE("setting render state\n");
6432 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
6433 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
6435 /* Force updating projection matrix */
6436 This->last_was_rhw = FALSE;
6437 This->proj_valid = FALSE;
6445 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
6446 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
6451 if ( NULL != impSwapChain) {
6452 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
6460 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
6461 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
6462 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6463 /* TODO: the use of Impl is deprecated. */
6464 /* some basic validation checks */
6465 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
6467 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
6469 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
6470 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
6471 return WINED3DERR_INVALIDCALL;
6473 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
6474 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
6475 return WINED3DERR_INVALIDCALL;
6477 /* TODO: make the cursor 'real' */
6479 This->xHotSpot = XHotSpot;
6480 This->yHotSpot = YHotSpot;
6485 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
6486 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6487 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
6489 This->xScreenSpace = XScreenSpace;
6490 This->yScreenSpace = YScreenSpace;
6496 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
6497 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6498 TRACE("(%p) : visible(%d)\n", This, bShow);
6500 This->bCursorVisible = bShow;
6505 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
6506 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6507 TRACE("(%p) : state (%lu)\n", This, This->state);
6508 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
6509 switch (This->state) {
6512 case WINED3DERR_DEVICELOST:
6514 ResourceList *resourceList = This->resources;
6515 while (NULL != resourceList) {
6516 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
6517 return WINED3DERR_DEVICENOTRESET;
6518 resourceList = resourceList->next;
6520 return WINED3DERR_DEVICELOST;
6522 case WINED3DERR_DRIVERINTERNALERROR:
6523 return WINED3DERR_DRIVERINTERNALERROR;
6527 return WINED3DERR_DRIVERINTERNALERROR;
6531 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
6532 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6533 /** FIXME: Resource tracking needs to be done,
6534 * The closes we can do to this is set the priorities of all managed textures low
6535 * and then reset them.
6536 ***********************************************************/
6537 FIXME("(%p) : stub\n", This);
6541 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
6542 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6543 /** FIXME: Resource trascking needs to be done.
6544 * in effect this pulls all non only default
6545 * textures out of video memory and deletes all glTextures (glDeleteTextures)
6546 * and should clear down the context and set it up according to pPresentationParameters
6547 ***********************************************************/
6548 FIXME("(%p) : stub\n", This);
6552 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
6553 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6554 /** FIXME: always true at the moment **/
6555 if(bEnableDialogs == FALSE) {
6556 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
6562 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
6563 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6564 TRACE("(%p) : pParameters %p\n", This, pParameters);
6566 *pParameters = This->createParms;
6570 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
6571 IWineD3DSwapChain *swapchain;
6572 HRESULT hrc = WINED3D_OK;
6574 TRACE("Relaying to swapchain\n");
6576 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
6577 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
6578 IWineD3DSwapChain_Release(swapchain);
6583 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
6584 IWineD3DSwapChain *swapchain;
6585 HRESULT hrc = WINED3D_OK;
6587 TRACE("Relaying to swapchain\n");
6589 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
6590 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
6591 IWineD3DSwapChain_Release(swapchain);
6597 /** ********************************************************
6598 * Notification functions
6599 ** ********************************************************/
6600 /** This function must be called in the release of a resource when ref == 0,
6601 * the contents of resource must still be correct,
6602 * any handels to other resource held by the caller must be closed
6603 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
6604 *****************************************************/
6605 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6606 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6607 ResourceList* resourceList;
6609 TRACE("(%p) : resource %p\n", This, resource);
6611 EnterCriticalSection(&resourceStoreCriticalSection);
6613 /* add a new texture to the frot of the linked list */
6614 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
6615 resourceList->resource = resource;
6617 /* Get the old head */
6618 resourceList->next = This->resources;
6620 This->resources = resourceList;
6621 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
6624 LeaveCriticalSection(&resourceStoreCriticalSection);
6629 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6630 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6631 ResourceList* resourceList = NULL;
6632 ResourceList* previousResourceList = NULL;
6634 TRACE("(%p) : resource %p\n", This, resource);
6637 EnterCriticalSection(&resourceStoreCriticalSection);
6639 resourceList = This->resources;
6641 while (resourceList != NULL) {
6642 if(resourceList->resource == resource) break;
6643 previousResourceList = resourceList;
6644 resourceList = resourceList->next;
6647 if (resourceList == NULL) {
6648 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
6650 LeaveCriticalSection(&resourceStoreCriticalSection);
6654 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
6656 /* make sure we don't leave a hole in the list */
6657 if (previousResourceList != NULL) {
6658 previousResourceList->next = resourceList->next;
6660 This->resources = resourceList->next;
6664 LeaveCriticalSection(&resourceStoreCriticalSection);
6670 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
6671 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6674 TRACE("(%p) : resource %p\n", This, resource);
6675 switch(IWineD3DResource_GetType(resource)){
6676 case WINED3DRTYPE_SURFACE:
6677 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
6679 case WINED3DRTYPE_TEXTURE:
6680 case WINED3DRTYPE_CUBETEXTURE:
6681 case WINED3DRTYPE_VOLUMETEXTURE:
6682 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
6683 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6684 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6685 This->stateBlock->textures[counter] = NULL;
6687 if (This->updateStateBlock != This->stateBlock ){
6688 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6689 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6690 This->updateStateBlock->textures[counter] = NULL;
6695 case WINED3DRTYPE_VOLUME:
6696 /* TODO: nothing really? */
6698 case WINED3DRTYPE_VERTEXBUFFER:
6699 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
6702 TRACE("Cleaning up stream pointers\n");
6704 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
6705 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
6706 FINDOUT: should changes.streamSource[StreamNumber] be set ?
6708 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6709 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
6710 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
6711 This->updateStateBlock->streamSource[streamNumber] = 0;
6712 /* Set changed flag? */
6715 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) */
6716 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
6717 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
6718 This->stateBlock->streamSource[streamNumber] = 0;
6721 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
6722 else { /* This shouldn't happen */
6723 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
6730 case WINED3DRTYPE_INDEXBUFFER:
6731 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
6732 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6733 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6734 This->updateStateBlock->pIndexData = NULL;
6737 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
6738 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6739 This->stateBlock->pIndexData = NULL;
6745 FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
6750 /* Remove the resoruce from the resourceStore */
6751 IWineD3DDeviceImpl_RemoveResource(iface, resource);
6753 TRACE("Resource released\n");
6758 /** This function is to be called by the swapchain when it is released and it's ref = 0
6759 *****************************************************/
6760 void WINAPI IWineD3DDeviceImpl_SwapChainReleased(IWineD3DDevice *iface, IWineD3DSwapChain *swapChain){
6761 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6762 SwapChainList **nextSwapchain;
6763 nextSwapchain = &This->swapchains;
6765 /* Check to see if the swapchian is being used as the render target */
6766 if (This->renderTarget != NULL) {
6767 IWineD3DSurface *swapchainBackBuffer;
6769 IWineD3DSwapChain_GetBackBuffer(swapChain, 0 ,( D3DBACKBUFFER_TYPE) 0, &swapchainBackBuffer);
6770 if (This->renderTarget == swapchainBackBuffer) {
6771 /* Don't know what to do, so warn and carry on as usual (which in this case leaves the renderterget in limbo) */
6772 FIXME("Atempting to release a swapchain that is currently beuing used as a render target, behaviour is undefined\n");
6776 /* Go through the swapchain list and try to find the swapchain being released */
6777 while(*nextSwapchain != NULL && (*nextSwapchain)->swapchain != swapChain) {
6778 nextSwapchain = &(*nextSwapchain)->next;
6781 /* Check to see if we found the swapchain */
6782 if (NULL != *nextSwapchain) {
6783 /* We found the swapchain so remove it from the list */
6784 TRACE("(%p) releasing swapchain(%p)\n", iface, swapChain);
6785 HeapFree(GetProcessHeap(), 0 , *nextSwapchain);
6786 *nextSwapchain = (*nextSwapchain)->next;
6788 /* We didn't find the swapchain on the list, this can only heppen because of a programming error in wined3d */
6789 FIXME("(%p) Attempting to release a swapchain (%p) that hasn't been stored\n", iface, swapChain);
6792 TRACE("swapchain (%p) released\n", swapChain);
6796 /**********************************************************
6797 * IWineD3DDevice VTbl follows
6798 **********************************************************/
6800 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
6802 /*** IUnknown methods ***/
6803 IWineD3DDeviceImpl_QueryInterface,
6804 IWineD3DDeviceImpl_AddRef,
6805 IWineD3DDeviceImpl_Release,
6806 /*** IWineD3DDevice methods ***/
6807 IWineD3DDeviceImpl_GetParent,
6808 /*** Creation methods**/
6809 IWineD3DDeviceImpl_CreateVertexBuffer,
6810 IWineD3DDeviceImpl_CreateIndexBuffer,
6811 IWineD3DDeviceImpl_CreateStateBlock,
6812 IWineD3DDeviceImpl_CreateSurface,
6813 IWineD3DDeviceImpl_CreateTexture,
6814 IWineD3DDeviceImpl_CreateVolumeTexture,
6815 IWineD3DDeviceImpl_CreateVolume,
6816 IWineD3DDeviceImpl_CreateCubeTexture,
6817 IWineD3DDeviceImpl_CreateQuery,
6818 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
6819 IWineD3DDeviceImpl_CreateVertexDeclaration,
6820 IWineD3DDeviceImpl_CreateVertexShader,
6821 IWineD3DDeviceImpl_CreatePixelShader,
6822 /*** Odd functions **/
6823 IWineD3DDeviceImpl_Init3D,
6824 IWineD3DDeviceImpl_Uninit3D,
6825 IWineD3DDeviceImpl_EvictManagedResources,
6826 IWineD3DDeviceImpl_GetAvailableTextureMem,
6827 IWineD3DDeviceImpl_GetBackBuffer,
6828 IWineD3DDeviceImpl_GetCreationParameters,
6829 IWineD3DDeviceImpl_GetDeviceCaps,
6830 IWineD3DDeviceImpl_GetDirect3D,
6831 IWineD3DDeviceImpl_GetDisplayMode,
6832 IWineD3DDeviceImpl_GetHWND,
6833 IWineD3DDeviceImpl_SetHWND,
6834 IWineD3DDeviceImpl_GetNumberOfSwapChains,
6835 IWineD3DDeviceImpl_GetRasterStatus,
6836 IWineD3DDeviceImpl_GetSwapChain,
6837 IWineD3DDeviceImpl_Reset,
6838 IWineD3DDeviceImpl_SetDialogBoxMode,
6839 IWineD3DDeviceImpl_SetCursorProperties,
6840 IWineD3DDeviceImpl_SetCursorPosition,
6841 IWineD3DDeviceImpl_ShowCursor,
6842 IWineD3DDeviceImpl_TestCooperativeLevel,
6843 /*** Getters and setters **/
6844 IWineD3DDeviceImpl_SetClipPlane,
6845 IWineD3DDeviceImpl_GetClipPlane,
6846 IWineD3DDeviceImpl_SetClipStatus,
6847 IWineD3DDeviceImpl_GetClipStatus,
6848 IWineD3DDeviceImpl_SetCurrentTexturePalette,
6849 IWineD3DDeviceImpl_GetCurrentTexturePalette,
6850 IWineD3DDeviceImpl_SetDepthStencilSurface,
6851 IWineD3DDeviceImpl_GetDepthStencilSurface,
6852 IWineD3DDeviceImpl_SetFVF,
6853 IWineD3DDeviceImpl_GetFVF,
6854 IWineD3DDeviceImpl_SetGammaRamp,
6855 IWineD3DDeviceImpl_GetGammaRamp,
6856 IWineD3DDeviceImpl_SetIndices,
6857 IWineD3DDeviceImpl_GetIndices,
6858 IWineD3DDeviceImpl_SetLight,
6859 IWineD3DDeviceImpl_GetLight,
6860 IWineD3DDeviceImpl_SetLightEnable,
6861 IWineD3DDeviceImpl_GetLightEnable,
6862 IWineD3DDeviceImpl_SetMaterial,
6863 IWineD3DDeviceImpl_GetMaterial,
6864 IWineD3DDeviceImpl_SetNPatchMode,
6865 IWineD3DDeviceImpl_GetNPatchMode,
6866 IWineD3DDeviceImpl_SetPaletteEntries,
6867 IWineD3DDeviceImpl_GetPaletteEntries,
6868 IWineD3DDeviceImpl_SetPixelShader,
6869 IWineD3DDeviceImpl_GetPixelShader,
6870 IWineD3DDeviceImpl_SetPixelShaderConstant,
6871 IWineD3DDeviceImpl_GetPixelShaderConstant,
6872 IWineD3DDeviceImpl_SetPixelShaderConstantB,
6873 IWineD3DDeviceImpl_GetPixelShaderConstantB,
6874 IWineD3DDeviceImpl_SetPixelShaderConstantI,
6875 IWineD3DDeviceImpl_GetPixelShaderConstantI,
6876 IWineD3DDeviceImpl_SetPixelShaderConstantF,
6877 IWineD3DDeviceImpl_GetPixelShaderConstantF,
6878 IWineD3DDeviceImpl_SetPixelShaderConstantN,
6879 IWineD3DDeviceImpl_SetRenderState,
6880 IWineD3DDeviceImpl_GetRenderState,
6881 IWineD3DDeviceImpl_SetRenderTarget,
6882 IWineD3DDeviceImpl_GetRenderTarget,
6883 IWineD3DDeviceImpl_SetFrontBackBuffers,
6884 IWineD3DDeviceImpl_SetSamplerState,
6885 IWineD3DDeviceImpl_GetSamplerState,
6886 IWineD3DDeviceImpl_SetScissorRect,
6887 IWineD3DDeviceImpl_GetScissorRect,
6888 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
6889 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
6890 IWineD3DDeviceImpl_SetStreamSource,
6891 IWineD3DDeviceImpl_GetStreamSource,
6892 IWineD3DDeviceImpl_SetStreamSourceFreq,
6893 IWineD3DDeviceImpl_GetStreamSourceFreq,
6894 IWineD3DDeviceImpl_SetTexture,
6895 IWineD3DDeviceImpl_GetTexture,
6896 IWineD3DDeviceImpl_SetTextureStageState,
6897 IWineD3DDeviceImpl_GetTextureStageState,
6898 IWineD3DDeviceImpl_SetTransform,
6899 IWineD3DDeviceImpl_GetTransform,
6900 IWineD3DDeviceImpl_SetVertexDeclaration,
6901 IWineD3DDeviceImpl_GetVertexDeclaration,
6902 IWineD3DDeviceImpl_SetVertexShader,
6903 IWineD3DDeviceImpl_GetVertexShader,
6904 IWineD3DDeviceImpl_SetVertexShaderConstant,
6905 IWineD3DDeviceImpl_GetVertexShaderConstant,
6906 IWineD3DDeviceImpl_SetVertexShaderConstantB,
6907 IWineD3DDeviceImpl_GetVertexShaderConstantB,
6908 IWineD3DDeviceImpl_SetVertexShaderConstantI,
6909 IWineD3DDeviceImpl_GetVertexShaderConstantI,
6910 IWineD3DDeviceImpl_SetVertexShaderConstantF,
6911 IWineD3DDeviceImpl_GetVertexShaderConstantF,
6912 IWineD3DDeviceImpl_SetVertexShaderConstantN,
6913 IWineD3DDeviceImpl_SetViewport,
6914 IWineD3DDeviceImpl_GetViewport,
6915 IWineD3DDeviceImpl_MultiplyTransform,
6916 IWineD3DDeviceImpl_ValidateDevice,
6917 IWineD3DDeviceImpl_ProcessVertices,
6918 /*** State block ***/
6919 IWineD3DDeviceImpl_BeginStateBlock,
6920 IWineD3DDeviceImpl_EndStateBlock,
6921 /*** Scene management ***/
6922 IWineD3DDeviceImpl_BeginScene,
6923 IWineD3DDeviceImpl_EndScene,
6924 IWineD3DDeviceImpl_Present,
6925 IWineD3DDeviceImpl_Clear,
6927 IWineD3DDeviceImpl_DrawPrimitive,
6928 IWineD3DDeviceImpl_DrawIndexedPrimitive,
6929 IWineD3DDeviceImpl_DrawPrimitiveUP,
6930 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
6931 IWineD3DDeviceImpl_DrawRectPatch,
6932 IWineD3DDeviceImpl_DrawTriPatch,
6933 IWineD3DDeviceImpl_DeletePatch,
6934 IWineD3DDeviceImpl_ColorFill,
6935 IWineD3DDeviceImpl_UpdateTexture,
6936 IWineD3DDeviceImpl_UpdateSurface,
6937 IWineD3DDeviceImpl_CopyRects,
6938 IWineD3DDeviceImpl_StretchRect,
6939 IWineD3DDeviceImpl_GetRenderTargetData,
6940 IWineD3DDeviceImpl_GetFrontBufferData,
6941 /*** Internal use IWineD3DDevice methods ***/
6942 IWineD3DDeviceImpl_SetupTextureStates,
6943 /*** object tracking ***/
6944 IWineD3DDeviceImpl_SwapChainReleased,
6945 IWineD3DDeviceImpl_ResourceReleased
6949 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
6950 WINED3DRS_ALPHABLENDENABLE ,
6951 WINED3DRS_ALPHAFUNC ,
6952 WINED3DRS_ALPHAREF ,
6953 WINED3DRS_ALPHATESTENABLE ,
6955 WINED3DRS_COLORWRITEENABLE ,
6956 WINED3DRS_DESTBLEND ,
6957 WINED3DRS_DITHERENABLE ,
6958 WINED3DRS_FILLMODE ,
6959 WINED3DRS_FOGDENSITY ,
6961 WINED3DRS_FOGSTART ,
6962 WINED3DRS_LASTPIXEL ,
6963 WINED3DRS_SHADEMODE ,
6964 WINED3DRS_SRCBLEND ,
6965 WINED3DRS_STENCILENABLE ,
6966 WINED3DRS_STENCILFAIL ,
6967 WINED3DRS_STENCILFUNC ,
6968 WINED3DRS_STENCILMASK ,
6969 WINED3DRS_STENCILPASS ,
6970 WINED3DRS_STENCILREF ,
6971 WINED3DRS_STENCILWRITEMASK ,
6972 WINED3DRS_STENCILZFAIL ,
6973 WINED3DRS_TEXTUREFACTOR ,
6984 WINED3DRS_ZWRITEENABLE
6987 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
6988 WINED3DTSS_ADDRESSW ,
6989 WINED3DTSS_ALPHAARG0 ,
6990 WINED3DTSS_ALPHAARG1 ,
6991 WINED3DTSS_ALPHAARG2 ,
6992 WINED3DTSS_ALPHAOP ,
6993 WINED3DTSS_BUMPENVLOFFSET ,
6994 WINED3DTSS_BUMPENVLSCALE ,
6995 WINED3DTSS_BUMPENVMAT00 ,
6996 WINED3DTSS_BUMPENVMAT01 ,
6997 WINED3DTSS_BUMPENVMAT10 ,
6998 WINED3DTSS_BUMPENVMAT11 ,
6999 WINED3DTSS_COLORARG0 ,
7000 WINED3DTSS_COLORARG1 ,
7001 WINED3DTSS_COLORARG2 ,
7002 WINED3DTSS_COLOROP ,
7003 WINED3DTSS_RESULTARG ,
7004 WINED3DTSS_TEXCOORDINDEX ,
7005 WINED3DTSS_TEXTURETRANSFORMFLAGS
7008 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
7009 WINED3DSAMP_ADDRESSU ,
7010 WINED3DSAMP_ADDRESSV ,
7011 WINED3DSAMP_ADDRESSW ,
7012 WINED3DSAMP_BORDERCOLOR ,
7013 WINED3DSAMP_MAGFILTER ,
7014 WINED3DSAMP_MINFILTER ,
7015 WINED3DSAMP_MIPFILTER ,
7016 WINED3DSAMP_MIPMAPLODBIAS ,
7017 WINED3DSAMP_MAXMIPLEVEL ,
7018 WINED3DSAMP_MAXANISOTROPY ,
7019 WINED3DSAMP_SRGBTEXTURE ,
7020 WINED3DSAMP_ELEMENTINDEX
7023 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
7025 WINED3DRS_AMBIENTMATERIALSOURCE ,
7026 WINED3DRS_CLIPPING ,
7027 WINED3DRS_CLIPPLANEENABLE ,
7028 WINED3DRS_COLORVERTEX ,
7029 WINED3DRS_DIFFUSEMATERIALSOURCE ,
7030 WINED3DRS_EMISSIVEMATERIALSOURCE ,
7031 WINED3DRS_FOGDENSITY ,
7033 WINED3DRS_FOGSTART ,
7034 WINED3DRS_FOGTABLEMODE ,
7035 WINED3DRS_FOGVERTEXMODE ,
7036 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
7037 WINED3DRS_LIGHTING ,
7038 WINED3DRS_LOCALVIEWER ,
7039 WINED3DRS_MULTISAMPLEANTIALIAS ,
7040 WINED3DRS_MULTISAMPLEMASK ,
7041 WINED3DRS_NORMALIZENORMALS ,
7042 WINED3DRS_PATCHEDGESTYLE ,
7043 WINED3DRS_POINTSCALE_A ,
7044 WINED3DRS_POINTSCALE_B ,
7045 WINED3DRS_POINTSCALE_C ,
7046 WINED3DRS_POINTSCALEENABLE ,
7047 WINED3DRS_POINTSIZE ,
7048 WINED3DRS_POINTSIZE_MAX ,
7049 WINED3DRS_POINTSIZE_MIN ,
7050 WINED3DRS_POINTSPRITEENABLE ,
7051 WINED3DRS_RANGEFOGENABLE ,
7052 WINED3DRS_SPECULARMATERIALSOURCE ,
7053 WINED3DRS_TWEENFACTOR ,
7054 WINED3DRS_VERTEXBLEND
7057 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
7058 WINED3DTSS_TEXCOORDINDEX ,
7059 WINED3DTSS_TEXTURETRANSFORMFLAGS
7062 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
7063 WINED3DSAMP_DMAPOFFSET