2 * IWineD3DDevice implementation
4 * Copyright 2002-2005 Jason Edmeades
5 * Copyright 2003-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include "wined3d_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
31 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
33 /* x11drv GDI escapes */
34 #define X11DRV_ESCAPE 6789
35 enum x11drv_escape_codes
37 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
38 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
39 X11DRV_GET_FONT, /* get current X font for a DC */
42 /* retrieve the X display to use on a given DC */
43 inline static Display *get_display( HDC hdc )
46 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
48 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
49 sizeof(display), (LPSTR)&display )) display = NULL;
53 /* Memory tracking and object counting */
54 static unsigned int emulated_textureram = 64*1024*1024;
56 /* TODO: setup some flags in the regestry to enable, disable pbuffer support */
57 /* enable pbuffer support for offscreen textures */
58 BOOL pbuffer_support = FALSE;
59 /* allocate one pbuffer per surface */
60 BOOL pbuffer_per_surface = FALSE;
62 /* static function declarations */
63 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
65 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type);
68 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return D3DERR_OUTOFVIDEOMEMORY;}
70 #define D3DCREATEOBJECTINSTANCE(object, type) { \
71 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
72 D3DMEMCHECK(object, pp##type); \
73 object->lpVtbl = &IWineD3D##type##_Vtbl; \
74 object->wineD3DDevice = This; \
75 object->parent = parent; \
77 *pp##type = (IWineD3D##type *) object; \
80 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
81 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
82 D3DMEMCHECK(object, pp##type); \
83 object->lpVtbl = &IWineD3D##type##_Vtbl; \
84 object->resource.wineD3DDevice = This; \
85 object->resource.parent = parent; \
86 object->resource.resourceType = d3dtype; \
87 object->resource.ref = 1; \
88 object->resource.pool = Pool; \
89 object->resource.format = Format; \
90 object->resource.usage = Usage; \
91 object->resource.size = _size; \
92 /* Check that we have enough video ram left */ \
93 if (Pool == D3DPOOL_DEFAULT) { \
94 if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
95 WARN("Out of 'bogus' video memory\n"); \
96 HeapFree(GetProcessHeap(), 0, object); \
98 return D3DERR_OUTOFVIDEOMEMORY; \
100 globalChangeGlRam(_size); \
102 object->resource.allocatedMemory = (0 == _size ? NULL : Pool == D3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
103 if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != D3DPOOL_DEFAULT) { \
104 FIXME("Out of memory!\n"); \
105 HeapFree(GetProcessHeap(), 0, object); \
107 return D3DERR_OUTOFVIDEOMEMORY; \
109 *pp##type = (IWineD3D##type *) object; \
110 IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
111 TRACE("(%p) : Created resource %p\n", This, object); \
114 #define D3DINITIALIZEBASETEXTURE(_basetexture) { \
115 _basetexture.levels = Levels; \
116 _basetexture.filterType = (Usage & WINED3DUSAGE_AUTOGENMIPMAP) ? D3DTEXF_LINEAR : D3DTEXF_NONE; \
117 _basetexture.LOD = 0; \
118 _basetexture.dirty = TRUE; \
121 /**********************************************************
122 * Global variable / Constants follow
123 **********************************************************/
124 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
126 /**********************************************************
127 * Utility functions follow
128 **********************************************************/
129 /* Convert the D3DLIGHT properties into equivalent gl lights */
130 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
133 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
134 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
136 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
137 glMatrixMode(GL_MODELVIEW);
139 glLoadMatrixf((float *)&This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
142 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
143 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
144 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
145 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
146 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
147 checkGLcall("glLightfv");
150 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
151 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
152 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
153 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
154 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
155 checkGLcall("glLightfv");
158 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
159 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
160 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
161 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
162 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
163 checkGLcall("glLightfv");
165 /* Attenuation - Are these right? guessing... */
166 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
167 checkGLcall("glLightf");
168 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
169 checkGLcall("glLightf");
171 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
172 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
174 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
177 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
178 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
179 checkGLcall("glLightf");
181 switch (lightInfo->OriginalParms.Type) {
184 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
185 checkGLcall("glLightfv");
186 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
187 checkGLcall("glLightf");
193 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
194 checkGLcall("glLightfv");
196 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
197 checkGLcall("glLightfv");
198 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
199 checkGLcall("glLightf");
200 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
201 checkGLcall("glLightf");
205 case D3DLIGHT_DIRECTIONAL:
207 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
208 checkGLcall("glLightfv");
209 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
210 checkGLcall("glLightf");
211 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
212 checkGLcall("glLightf");
216 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
219 /* Restore the modelview matrix */
223 /* Apply the current values to the specified texture stage */
224 void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Sampler, DWORD Flags) {
225 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
233 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
234 clamping, MIPLOD, etc. This will work for up to 16 samplers.
237 if (Sampler >= GL_LIMITS(samplers)) {
238 FIXME("Trying to set the state of more samplers %ld than are supported %d by this openGL implementation\n", Sampler, GL_LIMITS(samplers));
241 VTRACE(("Activating appropriate texture state %ld\n", Sampler));
242 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
244 GLACTIVETEXTURE(Sampler);
246 /* Could we use bindTexture and then apply the states instead of GLACTIVETEXTURE */
247 } else if (Sampler > 0) {
248 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
252 /* TODO: change this to a lookup table
253 LOOKUP_TEXTURE_STATES lists all texture states that should be applied.
254 LOOKUP_CONTEXT_SATES list all context applicable states that can be applied
255 etc.... it's a lot cleaner, quicker and possibly easier to maintain than running a switch and setting a skip flag...
256 especially when there are a number of groups of states. */
258 TRACE("-----------------------> Updating the texture at Sampler %ld to have new texture state information\n", Sampler);
260 /* The list of states not to apply is a big as the list of states to apply, so it makes sense to produce an inclusive list */
261 #define APPLY_STATE(_state) IWineD3DDeviceImpl_ApplyTextureUnitState(iface, Sampler, _state)
262 /* these are the only two supported states that need to be applied */
263 APPLY_STATE(WINED3DTSS_TEXCOORDINDEX);
264 APPLY_STATE(WINED3DTSS_TEXTURETRANSFORMFLAGS);
265 #if 0 /* not supported at the moment */
266 APPLY_STATE(WINED3DTSS_BUMPENVMAT00);
267 APPLY_STATE(WINED3DTSS_BUMPENVMAT01);
268 APPLY_STATE(WINED3DTSS_BUMPENVMAT10);
269 APPLY_STATE(WINED3DTSS_BUMPENVMAT11);
270 APPLY_STATE(WINED3DTSS_BUMPENVLSCALE);
271 APPLY_STATE(WINED3DTSS_BUMPENVLOFFSET);
272 APPLY_STATE(WINED3DTSS_RESULTARG);
273 APPLY_STATE(WINED3DTSS_CONSTANT);
275 /* a quick sanity check in case someone forgot to update this function */
276 if (WINED3D_HIGHEST_TEXTURE_STATE > WINED3DTSS_CONSTANT) {
277 FIXME("(%p) : There are more texture states than expected, update device.c to match\n", This);
281 /* apply any sampler states that always need applying */
282 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
283 tmpvalue.d = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPMAPLODBIAS];
284 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
285 GL_TEXTURE_LOD_BIAS_EXT,
287 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
290 /* Note the D3DRS value applies to all textures, but GL has one
291 * per texture, so apply it now ready to be used!
293 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
294 /* Set the default alpha blend color */
295 glBlendColor(col[0], col[1], col[2], col[3]);
296 checkGLcall("glBlendColor");
298 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
299 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
300 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
302 /* TODO: NV_POINT_SPRITE */
303 if (GL_SUPPORT(ARB_POINT_SPRITE)) {
304 if (This->stateBlock->renderState[WINED3DRS_POINTSPRITEENABLE] != FALSE) {
305 /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
306 glDisable(GL_POINT_SMOOTH);
308 /* Centre the texture on the vertex */
309 VTRACE("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
310 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
312 VTRACE("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
313 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
314 checkGLcall("glTexEnvf(...)");
315 VTRACE("glEnable( GL_POINT_SPRITE_ARB )\n");
316 glEnable( GL_POINT_SPRITE_ARB );
317 checkGLcall("glEnable(...)");
319 VTRACE("glDisable( GL_POINT_SPRITE_ARB )\n");
320 glDisable( GL_POINT_SPRITE_ARB );
321 checkGLcall("glEnable(...)");
325 TRACE("-----------------------> Updated the texture at Sampler %ld to have new texture state information\n", Sampler);
328 /**********************************************************
329 * IUnknown parts follows
330 **********************************************************/
332 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
334 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
336 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
337 if (IsEqualGUID(riid, &IID_IUnknown)
338 || IsEqualGUID(riid, &IID_IWineD3DBase)
339 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
340 IUnknown_AddRef(iface);
345 return E_NOINTERFACE;
348 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
349 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
350 ULONG refCount = InterlockedIncrement(&This->ref);
352 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
356 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
357 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
358 ULONG refCount = InterlockedDecrement(&This->ref);
360 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
363 /* TODO: Clean up all the surfaces and textures! */
364 /* FIXME: Create targets and state blocks in d3d8 */
365 if (((IWineD3DImpl *)This->wineD3D)->dxVersion >= 8) { /*We don't create state blocks for d3d7 yet*/
366 /* NOTE: You must release the parent if the object was created via a callback
367 ** ***************************/
368 /* TODO: this is exactly the same as required by _Reset.., so at some point we need to move the code so that is can be called by reset add release... */
369 /* Release all of the swapchains, except the implicit swapchain */
370 IUnknown* stencilBufferParent;
371 IUnknown* swapChainParent;
373 /* NOTE: Don't release swapchain 0 here, it's 'special' */
374 SwapChainList *nextSwapchain = This->swapchains;
375 if (nextSwapchain != NULL) {
376 nextSwapchain = nextSwapchain->next;
378 WARN("Expected to find the implicit swapchain\n");
381 /* release all the other swapchains */
382 while (nextSwapchain != NULL) {
383 SwapChainList *prevSwapchain = nextSwapchain;
384 nextSwapchain = nextSwapchain->next;
385 IWineD3DSwapChain_Release(prevSwapchain->swapchain);
386 /* NOTE: no need to free the list element, it will be done by the release callback
387 HeapFree(GetProcessHeap(), 0, prevSwapchain); */
389 /* Release the buffers (with sanity checks)*/
390 if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
391 if(This->depthStencilBuffer != This->stencilBufferTarget)
392 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
394 This->stencilBufferTarget = NULL;
396 if(IWineD3DSurface_Release(This->renderTarget) >0){
397 /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
399 This->renderTarget = NULL;
401 IWineD3DSurface_GetParent(This->depthStencilBuffer, &stencilBufferParent);
402 IUnknown_Release(stencilBufferParent); /* once for the get parent */
403 if(IUnknown_Release(stencilBufferParent) >0){ /* the second time for when it was created */
404 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
406 This->depthStencilBuffer = NULL;
408 /* Release the update stateblock */
409 if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){
410 if(This->updateStateBlock != This->stateBlock)
411 FIXME("(%p) Something's still holding the Update stateblock\n",This);
413 This->updateStateBlock = NULL;
414 { /* because were not doing proper internal refcounts releasing the primary state block
415 causes recursion with the extra checks in ResourceReleased, to avoid this we have
416 to set this->stateBlock = NULL; first */
417 IWineD3DStateBlock *stateBlock = (IWineD3DStateBlock *)This->stateBlock;
418 This->stateBlock = NULL;
420 /* Release the stateblock */
421 if(IWineD3DStateBlock_Release(stateBlock) > 0){
422 FIXME("(%p) Something's still holding the Update stateblock\n",This);
426 if (This->swapchains != NULL) {
427 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
428 IWineD3DSwapChain_GetParent(This->swapchains->swapchain, &swapChainParent);
429 IUnknown_Release(swapChainParent); /* once for the get parent */
430 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
431 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
435 if (This->resources != NULL ) {
436 FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This);
438 #if 0 /* TODO: Dump a list of all the resources still bound */
439 dumpResources(This->resources);
441 /* TODO: set the resources to a lost state */
445 IWineD3D_Release(This->wineD3D);
446 This->wineD3D = NULL;
447 HeapFree(GetProcessHeap(), 0, This);
448 TRACE("Freed device %p\n", This);
454 /**********************************************************
455 * IWineD3DDevice implementation follows
456 **********************************************************/
457 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
458 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
459 *pParent = This->parent;
460 IUnknown_AddRef(This->parent);
464 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
465 DWORD FVF, D3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
467 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
468 IWineD3DVertexBufferImpl *object;
469 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
470 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, WINED3DRTYPE_VERTEXBUFFER, Size)
473 if (Pool == D3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
474 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
478 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
479 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
484 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
485 WINED3DFORMAT Format, D3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
486 HANDLE *sharedHandle, IUnknown *parent) {
487 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
488 IWineD3DIndexBufferImpl *object;
489 TRACE("(%p) Creating index buffer\n", This);
491 /* Allocate the storage for the device */
492 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,WINED3DRTYPE_INDEXBUFFER, Length)
495 if (Pool == D3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
496 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
499 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
500 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
501 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
506 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
508 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
509 IWineD3DStateBlockImpl *object;
512 D3DCREATEOBJECTINSTANCE(object, StateBlock)
513 object->blockType = Type;
515 /* Special case - Used during initialization to produce a placeholder stateblock
516 so other functions called can update a state block */
517 if (Type == WINED3DSBT_INIT) {
518 /* Don't bother increasing the reference count otherwise a device will never
519 be freed due to circular dependencies */
523 /* Otherwise, might as well set the whole state block to the appropriate values */
524 if ( This->stateBlock != NULL) {
525 memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
527 memset(object->streamFreq, 1, sizeof(object->streamFreq));
530 /* Reset the ref and type after kludging it */
531 object->wineD3DDevice = This;
533 object->blockType = Type;
535 TRACE("Updating changed flags appropriate for type %d\n", Type);
537 if (Type == WINED3DSBT_ALL) {
539 TRACE("ALL => Pretend everything has changed\n");
540 memset(&object->changed, TRUE, sizeof(This->stateBlock->changed));
541 } else if (Type == WINED3DSBT_PIXELSTATE) {
543 TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
544 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
546 object->changed.pixelShader = TRUE;
548 /* Pixel Shader Constants */
549 for (i = 0; i < MAX_PSHADER_CONSTANTS; ++i) {
550 object->changed.pixelShaderConstants[i] = TRUE;
552 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
553 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
555 for (j = 0; j < GL_LIMITS(textures); j++) {
556 for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
557 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
560 for (j = 0 ; j < 16; j++) {
561 for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
563 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
567 } else if (Type == WINED3DSBT_VERTEXSTATE) {
569 TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
570 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
572 object->changed.vertexShader = TRUE;
574 /* Vertex Shader Constants */
575 for (i = 0; i < MAX_VSHADER_CONSTANTS; ++i) {
576 object->changed.vertexShaderConstants[i] = TRUE;
578 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
579 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
581 for (j = 0; j < GL_LIMITS(textures); j++) {
582 for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
583 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
586 for (j = 0 ; j < 16; j++){
587 for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
588 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
592 /* Duplicate light chain */
594 PLIGHTINFOEL *src = NULL;
595 PLIGHTINFOEL *dst = NULL;
596 PLIGHTINFOEL *newEl = NULL;
597 src = This->stateBlock->lights;
598 object->lights = NULL;
602 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
603 if (newEl == NULL) return D3DERR_OUTOFVIDEOMEMORY;
604 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
606 newEl->changed = TRUE;
607 newEl->enabledChanged = TRUE;
609 object->lights = newEl;
620 FIXME("Unrecognized state block type %d\n", Type);
623 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
628 /* ************************************
630 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
633 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
635 If this flag is set, the contents of the depth stencil buffer will be invalid after calling either IDirect3DDevice9::Present or IDirect3DDevice9::SetDepthStencilSurface with a different depth surface.
637 ******************************** */
639 HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height, WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **ppSurface,WINED3DRESOURCETYPE Type, DWORD Usage, D3DPOOL Pool, D3DMULTISAMPLE_TYPE MultiSample ,DWORD MultisampleQuality, HANDLE* pSharedHandle, IUnknown *parent) {
640 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
641 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
642 unsigned int pow2Width, pow2Height;
643 unsigned int Size = 1;
644 TRACE("(%p) Create surface\n",This);
646 /** FIXME: Check ranges on the inputs are valid
649 * [in] Quality level. The valid range is between zero and one less than the level
650 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
651 * Passing a larger value returns the error D3DERR_INVALIDCALL. The MultisampleQuality
652 * values of paired render targets, depth stencil surfaces, and the MultiSample type
654 *******************************/
659 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
661 * If this flag is set, the contents of the depth stencil buffer will be
662 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
663 * with a different depth surface.
665 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
666 ***************************/
668 if(MultisampleQuality < 0) {
669 FIXME("Invalid multisample level %ld\n", MultisampleQuality);
670 return D3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
673 if(MultisampleQuality > 0) {
674 FIXME("MultisampleQuality set to %ld, substituting 0\n", MultisampleQuality);
675 MultisampleQuality=0;
678 /** FIXME: Check that the format is supported
680 *******************************/
682 /* Non-power2 support */
684 /* Find the nearest pow2 match */
685 pow2Width = pow2Height = 1;
686 while (pow2Width < Width) pow2Width <<= 1;
687 while (pow2Height < Height) pow2Height <<= 1;
689 if (pow2Width > Width || pow2Height > Height) {
690 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
691 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
692 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
693 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
694 This, Width, Height);
695 return D3DERR_NOTAVAILABLE;
699 /** Check against the maximum texture sizes supported by the video card **/
700 if (pow2Width > GL_LIMITS(texture_size) || pow2Height > GL_LIMITS(texture_size)) {
701 /* one of three options
702 1: Do the same as we do with nonpow 2 and scale the texture, (any texture ops would require the texture to be scaled which is potentially slow)
703 2: Set the texture to the maxium size (bad idea)
704 3: WARN and return D3DERR_NOTAVAILABLE;
706 WARN("(%p) Application requested a surface w %d, h %d, but the graphics card only supports %d\n", This, Width, Height, GL_LIMITS(texture_size));
707 return D3DERR_NOTAVAILABLE;
712 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
713 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
715 *********************************/
716 if (WINED3DFMT_UNKNOWN == Format) {
718 } else if (Format == WINED3DFMT_DXT1) {
719 /* DXT1 is half byte per pixel */
720 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4)) >> 1;
722 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
723 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
724 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4));
726 Size = (pow2Width * D3DFmtGetBpp(This, Format)) * pow2Height;
729 /** Create and initialise the surface resource **/
730 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,WINED3DRTYPE_SURFACE, Size)
731 /* "Standalone" surface */
732 IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL);
734 object->currentDesc.Width = Width;
735 object->currentDesc.Height = Height;
736 object->currentDesc.MultiSampleType = MultiSample;
737 object->currentDesc.MultiSampleQuality = MultisampleQuality;
739 /* Setup some glformat defaults */
740 if (WINED3DFMT_UNKNOWN != Format) {
741 object->glDescription.glFormat = D3DFmt2GLFmt(This, object->resource.format);
742 object->glDescription.glFormatInternal = D3DFmt2GLIntFmt(This, object->resource.format);
743 object->glDescription.glType = D3DFmt2GLType(This, object->resource.format);
745 object->glDescription.glFormat = 0;
746 object->glDescription.glFormatInternal = 0;
747 object->glDescription.glType = 0;
750 object->glDescription.textureName = 0;
751 object->glDescription.level = Level;
752 object->glDescription.target = GL_TEXTURE_2D;
755 object->pow2Width = pow2Width;
756 object->pow2Height = pow2Height;
757 object->nonpow2 = (pow2Width != Width || pow2Height != Height) ? TRUE : FALSE;
758 object->discard = Discard;
759 object->activeLock = FALSE;
761 if (WINED3DFMT_UNKNOWN != Format) {
762 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
763 object->pow2Size = (pow2Width * object->bytesPerPixel) * pow2Height;
765 object->bytesPerPixel = 0;
766 object->pow2Size = 0;
769 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
771 TRACE("Pool %d %d %d %d",Pool, D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM);
773 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
774 * this function is too deap to need to care about things like this.
775 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
776 * ****************************************/
778 case D3DPOOL_SCRATCH:
779 if(Lockable == FALSE)
780 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
781 which are mutually exclusive, setting lockable to true\n");
784 case D3DPOOL_SYSTEMMEM:
785 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
786 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
787 case D3DPOOL_MANAGED:
788 if(Usage == WINED3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
789 Usage of DYNAMIC which are mutually exclusive, not doing \
790 anything just telling you.\n");
792 case D3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
793 if(!(Usage & WINED3DUSAGE_DYNAMIC) && !(Usage & WINED3DUSAGE_RENDERTARGET)
794 && !(Usage && WINED3DUSAGE_DEPTHSTENCIL ) && Lockable == TRUE)
795 FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
798 FIXME("(%p) Unknown pool %d\n", This, Pool);
802 if (Usage & WINED3DUSAGE_RENDERTARGET && Pool != D3DPOOL_DEFAULT) {
803 FIXME("Trying to create a render target that isn't in the default pool\n");
807 object->locked = FALSE;
808 object->lockable = (WINED3DFMT_D16_LOCKABLE == Format) ? TRUE : Lockable;
810 /* mark the texture as dirty so that it get's loaded first time around*/
811 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
812 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
813 This, Width, Height, Format, debug_d3dformat(Format),
814 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
819 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
820 DWORD Usage, WINED3DFORMAT Format, D3DPOOL Pool,
821 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
822 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
824 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
825 IWineD3DTextureImpl *object;
830 unsigned int pow2Width = Width;
831 unsigned int pow2Height = Height;
834 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) ....\n", This, Width, Height, Levels, Usage);
836 /* TODO: It should only be possible to create textures for formats
837 that are reported as supported */
838 if (WINED3DFMT_UNKNOWN >= Format) {
839 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
840 return D3DERR_INVALIDCALL;
843 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, WINED3DRTYPE_TEXTURE, 0);
844 D3DINITIALIZEBASETEXTURE(object->baseTexture);
845 object->width = Width;
846 object->height = Height;
848 /** Non-power2 support **/
849 /* Find the nearest pow2 match */
850 pow2Width = pow2Height = 1;
851 while (pow2Width < Width) pow2Width <<= 1;
852 while (pow2Height < Height) pow2Height <<= 1;
854 /** FIXME: add support for real non-power-two if it's provided by the video card **/
855 /* Precalculated scaling for 'faked' non power of two texture coords */
856 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
857 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
858 TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
860 /* Calculate levels for mip mapping */
862 TRACE("calculating levels %d\n", object->baseTexture.levels);
863 object->baseTexture.levels++;
866 while (tmpW > 1 && tmpH > 1) {
867 tmpW = max(1, tmpW >> 1);
868 tmpH = max(1, tmpH >> 1);
869 object->baseTexture.levels++;
871 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
874 /* Generate all the surfaces */
877 for (i = 0; i < object->baseTexture.levels; i++)
879 /* use the callback to create the texture surface */
880 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
883 FIXME("Failed to create surface %p\n", object);
885 for (j = 0 ; j < i ; j++) {
886 IWineD3DSurface_Release(object->surfaces[j]);
888 /* heap free object */
889 HeapFree(GetProcessHeap(), 0, object);
895 IWineD3DSurface_SetContainer(object->surfaces[i], (IWineD3DBase *)object);
896 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
897 /* calculate the next mipmap level */
898 tmpW = max(1, tmpW >> 1);
899 tmpH = max(1, tmpH >> 1);
902 TRACE("(%p) : Created texture %p\n", This, object);
906 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
907 UINT Width, UINT Height, UINT Depth,
908 UINT Levels, DWORD Usage,
909 WINED3DFORMAT Format, D3DPOOL Pool,
910 IWineD3DVolumeTexture **ppVolumeTexture,
911 HANDLE *pSharedHandle, IUnknown *parent,
912 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
914 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
915 IWineD3DVolumeTextureImpl *object;
921 /* TODO: It should only be possible to create textures for formats
922 that are reported as supported */
923 if (WINED3DFMT_UNKNOWN >= Format) {
924 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
925 return D3DERR_INVALIDCALL;
928 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, WINED3DRTYPE_VOLUMETEXTURE, 0);
929 D3DINITIALIZEBASETEXTURE(object->baseTexture);
931 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
932 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
934 object->width = Width;
935 object->height = Height;
936 object->depth = Depth;
938 /* Calculate levels for mip mapping */
940 object->baseTexture.levels++;
944 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
945 tmpW = max(1, tmpW >> 1);
946 tmpH = max(1, tmpH >> 1);
947 tmpD = max(1, tmpD >> 1);
948 object->baseTexture.levels++;
950 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
953 /* Generate all the surfaces */
958 for (i = 0; i < object->baseTexture.levels; i++)
960 /* Create the volume */
961 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
962 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
964 /* Set it's container to this object */
965 IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)object);
967 /* calcualte the next mipmap level */
968 tmpW = max(1, tmpW >> 1);
969 tmpH = max(1, tmpH >> 1);
970 tmpD = max(1, tmpD >> 1);
973 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
974 TRACE("(%p) : Created volume texture %p\n", This, object);
978 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
979 UINT Width, UINT Height, UINT Depth,
981 WINED3DFORMAT Format, D3DPOOL Pool,
982 IWineD3DVolume** ppVolume,
983 HANDLE* pSharedHandle, IUnknown *parent) {
985 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
986 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
988 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, WINED3DRTYPE_VOLUME, ((Width * D3DFmtGetBpp(This, Format)) * Height * Depth))
990 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
991 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
993 object->currentDesc.Width = Width;
994 object->currentDesc.Height = Height;
995 object->currentDesc.Depth = Depth;
996 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
998 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
999 object->lockable = TRUE;
1000 object->locked = FALSE;
1001 memset(&object->lockedBox, 0, sizeof(D3DBOX));
1002 object->dirty = TRUE;
1004 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
1007 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
1008 UINT Levels, DWORD Usage,
1009 WINED3DFORMAT Format, D3DPOOL Pool,
1010 IWineD3DCubeTexture **ppCubeTexture,
1011 HANDLE *pSharedHandle, IUnknown *parent,
1012 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1014 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1015 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1019 unsigned int pow2EdgeLength = EdgeLength;
1021 /* TODO: It should only be possible to create textures for formats
1022 that are reported as supported */
1023 if (WINED3DFMT_UNKNOWN >= Format) {
1024 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
1025 return D3DERR_INVALIDCALL;
1028 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, WINED3DRTYPE_CUBETEXTURE, 0);
1029 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1031 TRACE("(%p) Create Cube Texture\n", This);
1033 /** Non-power2 support **/
1035 /* Find the nearest pow2 match */
1037 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
1039 object->edgeLength = EdgeLength;
1040 /* TODO: support for native non-power 2 */
1041 /* Precalculated scaling for 'faked' non power of two texture coords */
1042 object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
1044 /* Calculate levels for mip mapping */
1046 object->baseTexture.levels++;
1049 tmpW = max(1, tmpW >> 1);
1050 object->baseTexture.levels++;
1052 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1055 /* Generate all the surfaces */
1057 for (i = 0; i < object->baseTexture.levels; i++) {
1059 /* Create the 6 faces */
1060 for (j = 0; j < 6; j++) {
1062 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
1063 i /* Level */, &object->surfaces[j][i],pSharedHandle);
1069 for (l = 0; l < j; l++) {
1070 IWineD3DSurface_Release(object->surfaces[j][i]);
1072 for (k = 0; k < i; k++) {
1073 for (l = 0; l < 6; l++) {
1074 IWineD3DSurface_Release(object->surfaces[l][j]);
1078 FIXME("(%p) Failed to create surface\n",object);
1079 HeapFree(GetProcessHeap(),0,object);
1080 *ppCubeTexture = NULL;
1083 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IWineD3DBase *)object);
1084 TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1086 tmpW = max(1, tmpW >> 1);
1089 TRACE("(%p) : Created Cube Texture %p\n", This, object);
1090 *ppCubeTexture = (IWineD3DCubeTexture *) object;
1094 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1095 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1096 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1098 if (NULL == ppQuery) {
1099 /* Just a check to see if we support this type of query */
1100 HRESULT hr = D3DERR_NOTAVAILABLE;
1102 case WINED3DQUERYTYPE_OCCLUSION:
1103 TRACE("(%p) occlusion query\n", This);
1104 if (GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY))
1107 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1109 case WINED3DQUERYTYPE_VCACHE:
1110 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1111 case WINED3DQUERYTYPE_VERTEXSTATS:
1112 case WINED3DQUERYTYPE_EVENT:
1113 case WINED3DQUERYTYPE_TIMESTAMP:
1114 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1115 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1116 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1117 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1118 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1119 case WINED3DQUERYTYPE_PIXELTIMINGS:
1120 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1121 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1123 FIXME("(%p) Unhandled query type %d\n", This, Type);
1128 D3DCREATEOBJECTINSTANCE(object, Query)
1129 object->type = Type;
1130 /* allocated the 'extended' data based on the type of query requested */
1132 case D3DQUERYTYPE_OCCLUSION:
1133 if(GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY)) {
1134 TRACE("(%p) Allocating data for an occlusion query\n", This);
1135 object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1138 case D3DQUERYTYPE_VCACHE:
1139 case D3DQUERYTYPE_RESOURCEMANAGER:
1140 case D3DQUERYTYPE_VERTEXSTATS:
1141 case D3DQUERYTYPE_EVENT:
1142 case D3DQUERYTYPE_TIMESTAMP:
1143 case D3DQUERYTYPE_TIMESTAMPDISJOINT:
1144 case D3DQUERYTYPE_TIMESTAMPFREQ:
1145 case D3DQUERYTYPE_PIPELINETIMINGS:
1146 case D3DQUERYTYPE_INTERFACETIMINGS:
1147 case D3DQUERYTYPE_VERTEXTIMINGS:
1148 case D3DQUERYTYPE_PIXELTIMINGS:
1149 case D3DQUERYTYPE_BANDWIDTHTIMINGS:
1150 case D3DQUERYTYPE_CACHEUTILIZATION:
1152 object->extendedData = 0;
1153 FIXME("(%p) Unhandled query type %d\n",This , Type);
1155 TRACE("(%p) : Created Query %p\n", This, object);
1159 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1160 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1162 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1163 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1164 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1167 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1169 XVisualInfo template;
1170 GLXContext oldContext;
1171 Drawable oldDrawable;
1172 HRESULT hr = D3D_OK;
1174 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1176 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1177 * does a device hold a reference to a swap chain giving them a lifetime of the device
1178 * or does the swap chain notify the device of its destruction.
1179 *******************************/
1181 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1183 /* Initialize other useful values */
1184 object->presentParms.BackBufferCount = 1; /* TODO:? support for gl_aux buffers */
1186 /*********************
1187 * Lookup the window Handle and the relating X window handle
1188 ********************/
1190 /* Setup hwnd we are using, plus which display this equates to */
1191 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1192 if (!object->win_handle) {
1193 object->win_handle = This->createParms.hFocusWindow;
1196 object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window" );
1197 hDc = GetDC(object->win_handle);
1198 object->display = get_display(hDc);
1199 ReleaseDC(object->win_handle, hDc);
1200 TRACE("Using a display of %p %p\n", object->display, hDc);
1202 if (NULL == object->display || NULL == hDc) {
1203 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1204 return D3DERR_NOTAVAILABLE;
1207 if (object->win == 0) {
1208 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1209 return D3DERR_NOTAVAILABLE;
1212 * Create an opengl context for the display visual
1213 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1214 * use different properties after that point in time. FIXME: How to handle when requested format
1215 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1216 * it chooses is identical to the one already being used!
1217 **********************************/
1219 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1222 /* Create a new context for this swapchain */
1223 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1224 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1225 (or the best possible if none is requested) */
1226 TRACE("Found x visual ID : %ld\n", template.visualid);
1228 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1229 if (NULL == object->visInfo) {
1230 ERR("cannot really get XVisual\n");
1232 return D3DERR_NOTAVAILABLE;
1235 /* Write out some debug info about the visual/s */
1236 TRACE("Using x visual ID : %ld\n", template.visualid);
1237 TRACE(" visual info: %p\n", object->visInfo);
1238 TRACE(" num items : %d\n", num);
1239 for (n = 0;n < num; n++) {
1240 TRACE("=====item=====: %d\n", n + 1);
1241 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1242 TRACE(" screen : %d\n", object->visInfo[n].screen);
1243 TRACE(" depth : %u\n", object->visInfo[n].depth);
1244 TRACE(" class : %d\n", object->visInfo[n].class);
1245 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1246 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1247 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1248 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1249 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1250 /* log some extra glx info */
1251 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1252 TRACE(" gl_aux_buffers : %d\n", value);
1253 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1254 TRACE(" gl_buffer_size : %d\n", value);
1255 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1256 TRACE(" gl_red_size : %d\n", value);
1257 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1258 TRACE(" gl_green_size : %d\n", value);
1259 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1260 TRACE(" gl_blue_size : %d\n", value);
1261 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1262 TRACE(" gl_alpha_size : %d\n", value);
1263 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1264 TRACE(" gl_depth_size : %d\n", value);
1265 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1266 TRACE(" gl_stencil_size : %d\n", value);
1268 /* Now choose a simila visual ID*/
1270 #ifdef USE_CONTEXT_MANAGER
1272 /** TODO: use a context mamager **/
1276 IWineD3DSwapChain *implSwapChain;
1277 if (D3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1278 /* The first time around we create the context that is shared with all other swapchains and render targets */
1279 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1280 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1283 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1284 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1285 /* and create a new context with the implicit swapchains context as the shared context */
1286 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1287 IWineD3DSwapChain_Release(implSwapChain);
1292 XFree(object->visInfo);
1293 object->visInfo = NULL;
1295 if (NULL == object->glCtx) {
1296 ERR("cannot create glxContext\n");
1298 return D3DERR_NOTAVAILABLE;
1302 if (object->glCtx == NULL) {
1303 ERR("Error in context creation !\n");
1304 return D3DERR_INVALIDCALL;
1306 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1307 object->win_handle, object->glCtx, object->win, object->visInfo);
1310 /*********************
1311 * Windowed / Fullscreen
1312 *******************/
1315 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1316 * so we should really check to see if there is a fullscreen swapchain already
1317 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1318 **************************************/
1320 if (!*(pPresentationParameters->Windowed)) {
1326 /* Get info on the current display setup */
1327 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1328 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1331 /* Change the display settings */
1332 memset(&devmode, 0, sizeof(DEVMODEW));
1333 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1334 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1335 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1336 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1337 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1338 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1340 /* Make popup window */
1341 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1342 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1343 *(pPresentationParameters->BackBufferWidth),
1344 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1350 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1351 * then the corresponding dimension of the client area of the hDeviceWindow
1352 * (or the focus window, if hDeviceWindow is NULL) is taken.
1353 **********************/
1355 if (*(pPresentationParameters->Windowed) &&
1356 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1357 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1360 GetClientRect(object->win_handle, &Rect);
1362 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1363 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1364 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1366 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1367 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1368 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1372 /*********************
1373 * finish off parameter initialization
1374 *******************/
1376 /* Put the correct figures in the presentation parameters */
1377 TRACE("Coppying accross presentaion paraneters\n");
1378 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1379 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1380 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1381 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1382 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1383 object->presentParms.MultiSampleQuality = NULL == pPresentationParameters->MultiSampleQuality ? 0 : *(pPresentationParameters->MultiSampleQuality);
1384 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1385 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1386 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1387 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1388 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1389 object->presentParms.Flags = *(pPresentationParameters->Flags);
1390 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1391 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1394 /*********************
1395 * Create the back, front and stencil buffers
1396 *******************/
1397 TRACE("calling rendertarget CB\n");
1398 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1399 object->presentParms.BackBufferWidth,
1400 object->presentParms.BackBufferHeight,
1401 object->presentParms.BackBufferFormat,
1402 object->presentParms.MultiSampleType,
1403 object->presentParms.MultiSampleQuality,
1404 TRUE /* Lockable */,
1405 &object->frontBuffer,
1406 NULL /* pShared (always null)*/);
1407 if (object->frontBuffer != NULL)
1408 IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
1409 TRACE("calling rendertarget CB\n");
1410 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1411 object->presentParms.BackBufferWidth,
1412 object->presentParms.BackBufferHeight,
1413 object->presentParms.BackBufferFormat,
1414 object->presentParms.MultiSampleType,
1415 object->presentParms.MultiSampleQuality,
1416 TRUE /* Lockable */,
1417 &object->backBuffer,
1418 NULL /* pShared (always null)*/);
1419 if (object->backBuffer != NULL)
1420 IWineD3DSurface_SetContainer(object->backBuffer, (IWineD3DBase *)object);
1422 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1423 if (pPresentationParameters->EnableAutoDepthStencil) {
1424 TRACE("Creating depth stencil buffer\n");
1425 if (This->depthStencilBuffer == NULL ) {
1426 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1427 object->presentParms.BackBufferWidth,
1428 object->presentParms.BackBufferHeight,
1429 object->presentParms.AutoDepthStencilFormat,
1430 object->presentParms.MultiSampleType,
1431 object->presentParms.MultiSampleQuality,
1432 FALSE /* FIXME: Discard */,
1433 &This->depthStencilBuffer,
1434 NULL /* pShared (always null)*/ );
1435 if (This->depthStencilBuffer != NULL)
1436 IWineD3DSurface_SetContainer(This->depthStencilBuffer, 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;
1457 /*********************
1458 * Setup some defaults and clear down the buffers
1459 *******************/
1461 /** save current context and drawable **/
1462 oldContext = glXGetCurrentContext();
1463 oldDrawable = glXGetCurrentDrawable();
1465 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1466 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1467 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1469 checkGLcall("glXMakeCurrent");
1471 TRACE("Setting up the screen\n");
1472 /* Clear the screen */
1473 glClearColor(1.0, 0.0, 0.0, 0.0);
1474 checkGLcall("glClearColor");
1477 glClearStencil(0xffff);
1479 checkGLcall("glClear");
1481 glColor3f(1.0, 1.0, 1.0);
1482 checkGLcall("glColor3f");
1484 glEnable(GL_LIGHTING);
1485 checkGLcall("glEnable");
1487 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1488 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1490 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1491 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1493 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1494 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1496 /* switch back to the original context (if there was one)*/
1497 if (This->swapchains != NULL) {
1498 /** TODO: restore the context and drawable **/
1499 glXMakeCurrent(object->display, oldDrawable, oldContext);
1504 { /* Finally add the swapchain to the end of the devices' swapchain list */
1505 SwapChainList **nextSwapchain;
1506 nextSwapchain = &This->swapchains;
1507 while (*nextSwapchain != NULL) {
1508 nextSwapchain = &((*nextSwapchain)->next);
1510 (*nextSwapchain) = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->swapchains));
1511 (*nextSwapchain)->swapchain = (IWineD3DSwapChain *)object;
1513 TRACE("Set swapchain to %p\n", object);
1514 } else { /* something went wrong so clean up */
1515 IUnknown* bufferParent;
1516 if (object->frontBuffer) {
1518 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1519 IUnknown_Release(bufferParent); /* once for the get parent */
1520 if (IUnknown_Release(bufferParent) > 0) {
1521 FIXME("(%p) Something's still holding the front buffer\n",This);
1524 if (object->backBuffer) {
1525 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1526 IUnknown_Release(bufferParent); /* once for the get parent */
1527 if (IUnknown_Release(bufferParent) > 0) {
1528 FIXME("(%p) Something's still holding the back buffer\n",This);
1531 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1532 /* Clean up the context */
1533 /* check that we are the current context first (we shouldn't be though!) */
1534 if (object->glCtx != 0) {
1535 if(glXGetCurrentContext() == object->glCtx) {
1536 glXMakeCurrent(object->display, None, NULL);
1538 glXDestroyContext(object->display, object->glCtx);
1540 HeapFree(GetProcessHeap(), 0, object);
1547 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1548 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1549 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1550 unsigned int numberOfSwapChains = 0;
1551 SwapChainList *swapchain;
1553 swapchain = This->swapchains;
1554 /* itterate through the list to get a count */
1555 while (swapchain != NULL) {
1556 swapchain = swapchain->next;
1557 numberOfSwapChains++;
1560 TRACE("(%p) returning %d\n", This, numberOfSwapChains);
1561 return numberOfSwapChains;
1564 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1565 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1566 SwapChainList *swapchain;
1568 HRESULT hr = D3DERR_INVALIDCALL;
1569 swapchain = This->swapchains;
1570 TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1573 TRACE("(%p) Finding swapchain %d\n", This, iSwapChain);
1574 while (i > 0 && swapchain != NULL) {
1575 swapchain = swapchain->next;
1580 FIXME("(%p) Unable to find swapchain %d\n", This, iSwapChain);
1582 } else if (swapchain != NULL) {
1583 /** TODO: move off to a linkesList implementation **/
1584 *pSwapChain = swapchain->swapchain;
1585 IWineD3DSwapChain_AddRef(*pSwapChain);
1589 TRACE("(%p) returning %p\n", This, *pSwapChain);
1593 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
1594 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1596 FIXME("(%p) : Stub\n",This);
1602 * Vertex Declaration
1604 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1605 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1606 IWineD3DVertexDeclarationImpl *object = NULL;
1607 HRESULT hr = D3D_OK;
1608 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1609 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1612 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1617 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1618 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pDeclaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1619 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1620 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1621 HRESULT hr = D3D_OK;
1622 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1624 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1626 /* If a vertex declaration has been passed, save it to the vertex shader, this affects d3d8 only. */
1627 /* Further it needs to be set before calling SetFunction as SetFunction needs the declaration. */
1628 if (pDeclaration != NULL) {
1629 IWineD3DVertexDeclaration *vertexDeclaration;
1630 hr = IWineD3DDevice_CreateVertexDeclaration(iface, pDeclaration, &vertexDeclaration ,NULL);
1632 TRACE("(%p) : Setting vertex declaration to %p\n", This, vertexDeclaration);
1633 object->vertexDeclaration = vertexDeclaration;
1635 FIXME("(%p) : Failed to set the declaration, returning D3DERR_INVALIDCALL\n", iface);
1636 IWineD3DVertexShader_Release(*ppVertexShader);
1637 return D3DERR_INVALIDCALL;
1641 hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1644 FIXME("(%p) : Failed to set the function, returning D3DERR_INVALIDCALL\n", iface);
1645 IWineD3DVertexShader_Release(*ppVertexShader);
1646 return D3DERR_INVALIDCALL;
1649 #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. */
1650 if(Usage == WINED3DUSAGE_SOFTWAREVERTEXPROCESSING) {
1661 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
1662 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1663 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1664 HRESULT hr = D3D_OK;
1666 D3DCREATEOBJECTINSTANCE(object, PixelShader)
1667 hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
1669 TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
1671 WARN("(%p) : Failed to create pixel shader\n", This);
1677 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
1678 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1679 *ppD3D= This->wineD3D;
1680 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1681 IWineD3D_AddRef(*ppD3D);
1685 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1686 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1687 * Into the video ram as possible and seeing how many fit
1688 * you can also get the correct initial value from via X and ATI's driver
1689 *******************/
1690 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1691 static BOOL showfixmes = TRUE;
1693 FIXME("(%p) : stub, emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1694 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1697 TRACE("(%p) : emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1698 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1699 /* videomemory is simulated videomemory + AGP memory left */
1700 return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1708 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1709 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1710 HRESULT hr = D3D_OK;
1712 /* Update the current state block */
1713 This->updateStateBlock->fvf = fvf;
1714 This->updateStateBlock->changed.fvf = TRUE;
1715 This->updateStateBlock->set.fvf = TRUE;
1717 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1720 /* clear down the vertex declaration
1721 NOTE: Axis and Allies doesn't work properly otherwise
1722 (may be a stateblock problem though!)
1724 hr = IWineD3DDevice_SetVertexDeclaration(iface, NULL);
1731 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1732 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1733 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1734 *pfvf = This->stateBlock->fvf;
1739 * Get / Set Stream Source
1741 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1742 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1743 IWineD3DVertexBuffer *oldSrc;
1745 /**TODO: instance and index data, see
1746 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1748 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
1751 /* D3d9 only, but shouldn't hurt d3d8 */
1754 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1756 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1757 FIXME("stream index data not supported\n");
1759 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1760 FIXME("stream instance data not supported\n");
1764 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1766 if (StreamNumber >= MAX_STREAMS) {
1767 WARN("Stream out of range %d\n", StreamNumber);
1768 return D3DERR_INVALIDCALL;
1771 oldSrc = This->stateBlock->streamSource[StreamNumber];
1772 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1774 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
1775 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
1776 This->updateStateBlock->streamStride[StreamNumber] = Stride;
1777 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
1778 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
1779 This->updateStateBlock->streamFlags[StreamNumber] = streamFlags;
1781 /* Handle recording of state blocks */
1782 if (This->isRecordingState) {
1783 TRACE("Recording... not performing anything\n");
1787 /* Not recording... */
1788 /* Need to do a getParent and pass the reffs up */
1789 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
1790 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
1791 so for now, just count internally */
1792 if (pStreamData != NULL) {
1793 IWineD3DVertexBuffer_AddRef(pStreamData);
1795 if (oldSrc != NULL) {
1796 IWineD3DVertexBuffer_Release(oldSrc);
1802 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
1803 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1806 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
1807 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
1810 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1812 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1813 FIXME("stream index data not supported\n");
1815 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1816 FIXME("stream instance data not supported\n");
1820 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1822 if (StreamNumber >= MAX_STREAMS) {
1823 WARN("Stream out of range %d\n", StreamNumber);
1824 return D3DERR_INVALIDCALL;
1826 *pStream = This->stateBlock->streamSource[StreamNumber];
1827 *pStride = This->stateBlock->streamStride[StreamNumber];
1828 *pOffset = This->stateBlock->streamOffset[StreamNumber];
1830 if (*pStream == NULL) {
1831 FIXME("Attempting to get an empty stream %d, returning D3DERR_INVALIDCALL\n", StreamNumber);
1832 return D3DERR_INVALIDCALL;
1835 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
1839 /*Should be quite easy, just an extension of vertexdata
1841 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1843 The divider is a bit odd though
1845 VertexOffset = StartVertex / Divider * StreamStride +
1846 VertexIndex / Divider * StreamStride + StreamOffset
1849 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
1850 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1852 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
1853 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (D3DSTREAMSOURCE_INSTANCEDATA | D3DSTREAMSOURCE_INDEXEDDATA );
1855 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
1856 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
1857 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
1859 if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
1860 FIXME("Stream indexing not fully supported\n");
1866 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
1867 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1869 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
1870 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
1872 TRACE("(%p) : returning %d\n", This, *Divider);
1878 * Get / Set & Multiply Transform
1880 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1881 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1883 /* Most of this routine, comments included copied from ddraw tree initially: */
1884 TRACE("(%p) : Transform State=%d\n", This, d3dts);
1886 /* Handle recording of state blocks */
1887 if (This->isRecordingState) {
1888 TRACE("Recording... not performing anything\n");
1889 This->updateStateBlock->changed.transform[d3dts] = TRUE;
1890 This->updateStateBlock->set.transform[d3dts] = TRUE;
1891 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1896 * If the new matrix is the same as the current one,
1897 * we cut off any further processing. this seems to be a reasonable
1898 * optimization because as was noticed, some apps (warcraft3 for example)
1899 * tend towards setting the same matrix repeatedly for some reason.
1901 * From here on we assume that the new matrix is different, wherever it matters.
1903 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1904 TRACE("The app is setting the same matrix over again\n");
1907 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1911 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1912 where ViewMat = Camera space, WorldMat = world space.
1914 In OpenGL, camera and world space is combined into GL_MODELVIEW
1915 matrix. The Projection matrix stay projection matrix.
1918 /* Capture the times we can just ignore the change for now */
1919 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1920 This->modelview_valid = FALSE;
1923 } else if (d3dts == D3DTS_PROJECTION) {
1924 This->proj_valid = FALSE;
1927 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1928 /* Indexed Vertex Blending Matrices 256 -> 511 */
1929 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1930 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1934 /* Now we really are going to have to change a matrix */
1937 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1938 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
1939 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1942 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1943 * NOTE: We have to reset the positions even if the light/plane is not currently
1944 * enabled, since the call to enable it will not reset the position.
1945 * NOTE2: Apparently texture transforms do NOT need reapplying
1948 PLIGHTINFOEL *lightChain = NULL;
1949 This->modelview_valid = FALSE;
1950 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
1952 glMatrixMode(GL_MODELVIEW);
1953 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1955 glLoadMatrixf((float *)lpmatrix);
1956 checkGLcall("glLoadMatrixf(...)");
1959 lightChain = This->stateBlock->lights;
1960 while (lightChain && lightChain->glIndex != -1) {
1961 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1962 checkGLcall("glLightfv posn");
1963 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1964 checkGLcall("glLightfv dirn");
1965 lightChain = lightChain->next;
1968 /* Reset Clipping Planes if clipping is enabled */
1969 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1970 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1971 checkGLcall("glClipPlane");
1975 } else { /* What was requested!?? */
1976 WARN("invalid matrix specified: %i\n", d3dts);
1979 /* Release lock, all done */
1984 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1985 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1986 TRACE("(%p) : for Transform State %d\n", This, State);
1987 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1991 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1992 D3DMATRIX *mat = NULL;
1995 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1996 * below means it will be recorded in a state block change, but it
1997 * works regardless where it is recorded.
1998 * If this is found to be wrong, change to StateBlock.
2000 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2001 TRACE("(%p) : For state %u\n", This, State);
2003 if (State < HIGHEST_TRANSFORMSTATE)
2005 mat = &This->updateStateBlock->transforms[State];
2007 FIXME("Unhandled transform state!!\n");
2010 /* Copied from ddraw code: */
2011 temp.u.s._11 = (mat->u.s._11 * pMatrix->u.s._11) + (mat->u.s._21 * pMatrix->u.s._12) +
2012 (mat->u.s._31 * pMatrix->u.s._13) + (mat->u.s._41 * pMatrix->u.s._14);
2013 temp.u.s._21 = (mat->u.s._11 * pMatrix->u.s._21) + (mat->u.s._21 * pMatrix->u.s._22) +
2014 (mat->u.s._31 * pMatrix->u.s._23) + (mat->u.s._41 * pMatrix->u.s._24);
2015 temp.u.s._31 = (mat->u.s._11 * pMatrix->u.s._31) + (mat->u.s._21 * pMatrix->u.s._32) +
2016 (mat->u.s._31 * pMatrix->u.s._33) + (mat->u.s._41 * pMatrix->u.s._34);
2017 temp.u.s._41 = (mat->u.s._11 * pMatrix->u.s._41) + (mat->u.s._21 * pMatrix->u.s._42) +
2018 (mat->u.s._31 * pMatrix->u.s._43) + (mat->u.s._41 * pMatrix->u.s._44);
2020 temp.u.s._12 = (mat->u.s._12 * pMatrix->u.s._11) + (mat->u.s._22 * pMatrix->u.s._12) +
2021 (mat->u.s._32 * pMatrix->u.s._13) + (mat->u.s._42 * pMatrix->u.s._14);
2022 temp.u.s._22 = (mat->u.s._12 * pMatrix->u.s._21) + (mat->u.s._22 * pMatrix->u.s._22) +
2023 (mat->u.s._32 * pMatrix->u.s._23) + (mat->u.s._42 * pMatrix->u.s._24);
2024 temp.u.s._32 = (mat->u.s._12 * pMatrix->u.s._31) + (mat->u.s._22 * pMatrix->u.s._32) +
2025 (mat->u.s._32 * pMatrix->u.s._33) + (mat->u.s._42 * pMatrix->u.s._34);
2026 temp.u.s._42 = (mat->u.s._12 * pMatrix->u.s._41) + (mat->u.s._22 * pMatrix->u.s._42) +
2027 (mat->u.s._32 * pMatrix->u.s._43) + (mat->u.s._42 * pMatrix->u.s._44);
2029 temp.u.s._13 = (mat->u.s._13 * pMatrix->u.s._11) + (mat->u.s._23 * pMatrix->u.s._12) +
2030 (mat->u.s._33 * pMatrix->u.s._13) + (mat->u.s._43 * pMatrix->u.s._14);
2031 temp.u.s._23 = (mat->u.s._13 * pMatrix->u.s._21) + (mat->u.s._23 * pMatrix->u.s._22) +
2032 (mat->u.s._33 * pMatrix->u.s._23) + (mat->u.s._43 * pMatrix->u.s._24);
2033 temp.u.s._33 = (mat->u.s._13 * pMatrix->u.s._31) + (mat->u.s._23 * pMatrix->u.s._32) +
2034 (mat->u.s._33 * pMatrix->u.s._33) + (mat->u.s._43 * pMatrix->u.s._34);
2035 temp.u.s._43 = (mat->u.s._13 * pMatrix->u.s._41) + (mat->u.s._23 * pMatrix->u.s._42) +
2036 (mat->u.s._33 * pMatrix->u.s._43) + (mat->u.s._43 * pMatrix->u.s._44);
2038 temp.u.s._14 = (mat->u.s._14 * pMatrix->u.s._11) + (mat->u.s._24 * pMatrix->u.s._12) +
2039 (mat->u.s._34 * pMatrix->u.s._13) + (mat->u.s._44 * pMatrix->u.s._14);
2040 temp.u.s._24 = (mat->u.s._14 * pMatrix->u.s._21) + (mat->u.s._24 * pMatrix->u.s._22) +
2041 (mat->u.s._34 * pMatrix->u.s._23) + (mat->u.s._44 * pMatrix->u.s._24);
2042 temp.u.s._34 = (mat->u.s._14 * pMatrix->u.s._31) + (mat->u.s._24 * pMatrix->u.s._32) +
2043 (mat->u.s._34 * pMatrix->u.s._33) + (mat->u.s._44 * pMatrix->u.s._34);
2044 temp.u.s._44 = (mat->u.s._14 * pMatrix->u.s._41) + (mat->u.s._24 * pMatrix->u.s._42) +
2045 (mat->u.s._34 * pMatrix->u.s._43) + (mat->u.s._44 * pMatrix->u.s._44);
2047 /* Apply change via set transform - will reapply to eg. lights this way */
2048 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2053 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
2055 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2056 you can reference any indexes you want as long as that number max are enabled at any
2057 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2058 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2059 but when recording, just build a chain pretty much of commands to be replayed. */
2061 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2063 PLIGHTINFOEL *object, *temp;
2065 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2066 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2068 /* If recording state block, just add to end of lights chain */
2069 if (This->isRecordingState) {
2070 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2071 if (NULL == object) {
2072 return D3DERR_OUTOFVIDEOMEMORY;
2074 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2075 object->OriginalIndex = Index;
2076 object->glIndex = -1;
2077 object->changed = TRUE;
2079 /* Add to the END of the chain of lights changes to be replayed */
2080 if (This->updateStateBlock->lights == NULL) {
2081 This->updateStateBlock->lights = object;
2083 temp = This->updateStateBlock->lights;
2084 while (temp->next != NULL) temp=temp->next;
2085 temp->next = object;
2087 TRACE("Recording... not performing anything more\n");
2091 /* Ok, not recording any longer so do real work */
2092 object = This->stateBlock->lights;
2093 while (object != NULL && object->OriginalIndex != Index) object = object->next;
2095 /* If we didn't find it in the list of lights, time to add it */
2096 if (object == NULL) {
2097 PLIGHTINFOEL *insertAt,*prevPos;
2099 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2100 if (NULL == object) {
2101 return D3DERR_OUTOFVIDEOMEMORY;
2103 object->OriginalIndex = Index;
2104 object->glIndex = -1;
2106 /* Add it to the front of list with the idea that lights will be changed as needed
2107 BUT after any lights currently assigned GL indexes */
2108 insertAt = This->stateBlock->lights;
2110 while (insertAt != NULL && insertAt->glIndex != -1) {
2112 insertAt = insertAt->next;
2115 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2116 This->stateBlock->lights = object;
2117 } else if (insertAt == NULL) { /* End of list */
2118 prevPos->next = object;
2119 object->prev = prevPos;
2120 } else { /* Middle of chain */
2121 if (prevPos == NULL) {
2122 This->stateBlock->lights = object;
2124 prevPos->next = object;
2126 object->prev = prevPos;
2127 object->next = insertAt;
2128 insertAt->prev = object;
2132 /* Initialize the object */
2133 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,
2134 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2135 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2136 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2137 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2138 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2139 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2141 /* Save away the information */
2142 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2144 switch (pLight->Type) {
2145 case D3DLIGHT_POINT:
2147 object->lightPosn[0] = pLight->Position.x;
2148 object->lightPosn[1] = pLight->Position.y;
2149 object->lightPosn[2] = pLight->Position.z;
2150 object->lightPosn[3] = 1.0f;
2151 object->cutoff = 180.0f;
2155 case D3DLIGHT_DIRECTIONAL:
2157 object->lightPosn[0] = -pLight->Direction.x;
2158 object->lightPosn[1] = -pLight->Direction.y;
2159 object->lightPosn[2] = -pLight->Direction.z;
2160 object->lightPosn[3] = 0.0;
2161 object->exponent = 0.0f;
2162 object->cutoff = 180.0f;
2167 object->lightPosn[0] = pLight->Position.x;
2168 object->lightPosn[1] = pLight->Position.y;
2169 object->lightPosn[2] = pLight->Position.z;
2170 object->lightPosn[3] = 1.0;
2173 object->lightDirn[0] = pLight->Direction.x;
2174 object->lightDirn[1] = pLight->Direction.y;
2175 object->lightDirn[2] = pLight->Direction.z;
2176 object->lightDirn[3] = 1.0;
2179 * opengl-ish and d3d-ish spot lights use too different models for the
2180 * light "intensity" as a function of the angle towards the main light direction,
2181 * so we only can approximate very roughly.
2182 * however spot lights are rather rarely used in games (if ever used at all).
2183 * furthermore if still used, probably nobody pays attention to such details.
2185 if (pLight->Falloff == 0) {
2188 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2190 if (rho < 0.0001) rho = 0.0001f;
2191 object->exponent = -0.3/log(cos(rho/2));
2192 object->cutoff = pLight->Phi*90/M_PI;
2198 FIXME("Unrecognized light type %d\n", pLight->Type);
2201 /* Update the live definitions if the light is currently assigned a glIndex */
2202 if (object->glIndex != -1) {
2203 setup_light(iface, object->glIndex, object);
2208 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2209 PLIGHTINFOEL *lightInfo = NULL;
2210 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2211 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2213 /* Locate the light in the live lights */
2214 lightInfo = This->stateBlock->lights;
2215 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2217 if (lightInfo == NULL) {
2218 TRACE("Light information requested but light not defined\n");
2219 return D3DERR_INVALIDCALL;
2222 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
2227 * Get / Set Light Enable
2228 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2230 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2231 PLIGHTINFOEL *lightInfo = NULL;
2232 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2233 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2235 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2236 if (This->isRecordingState) {
2237 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2238 if (NULL == lightInfo) {
2239 return D3DERR_OUTOFVIDEOMEMORY;
2241 lightInfo->OriginalIndex = Index;
2242 lightInfo->glIndex = -1;
2243 lightInfo->enabledChanged = TRUE;
2245 /* Add to the END of the chain of lights changes to be replayed */
2246 if (This->updateStateBlock->lights == NULL) {
2247 This->updateStateBlock->lights = lightInfo;
2249 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2250 while (temp->next != NULL) temp=temp->next;
2251 temp->next = lightInfo;
2253 TRACE("Recording... not performing anything more\n");
2257 /* Not recording... So, locate the light in the live lights */
2258 lightInfo = This->stateBlock->lights;
2259 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2261 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2262 if (lightInfo == NULL) {
2263 D3DLIGHT9 lightParms;
2264 /* Warning - untested code :-) Prob safe to change fixme to a trace but
2265 wait until someone confirms it seems to work! */
2266 TRACE("Light enabled requested but light not defined, so defining one!\n");
2267 lightParms.Type = D3DLIGHT_DIRECTIONAL;
2268 lightParms.Diffuse.r = 1.0;
2269 lightParms.Diffuse.g = 1.0;
2270 lightParms.Diffuse.b = 1.0;
2271 lightParms.Diffuse.a = 0.0;
2272 lightParms.Specular.r = 0.0;
2273 lightParms.Specular.g = 0.0;
2274 lightParms.Specular.b = 0.0;
2275 lightParms.Specular.a = 0.0;
2276 lightParms.Ambient.r = 0.0;
2277 lightParms.Ambient.g = 0.0;
2278 lightParms.Ambient.b = 0.0;
2279 lightParms.Ambient.a = 0.0;
2280 lightParms.Position.x = 0.0;
2281 lightParms.Position.y = 0.0;
2282 lightParms.Position.z = 0.0;
2283 lightParms.Direction.x = 0.0;
2284 lightParms.Direction.y = 0.0;
2285 lightParms.Direction.z = 1.0;
2286 lightParms.Range = 0.0;
2287 lightParms.Falloff = 0.0;
2288 lightParms.Attenuation0 = 0.0;
2289 lightParms.Attenuation1 = 0.0;
2290 lightParms.Attenuation2 = 0.0;
2291 lightParms.Theta = 0.0;
2292 lightParms.Phi = 0.0;
2293 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
2295 /* Search for it again! Should be fairly quick as near head of list */
2296 lightInfo = This->stateBlock->lights;
2297 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2298 if (lightInfo == NULL) {
2299 FIXME("Adding default lights has failed dismally\n");
2300 return D3DERR_INVALIDCALL;
2304 /* OK, we now have a light... */
2305 if (Enable == FALSE) {
2307 /* If we are disabling it, check it was enabled, and
2308 still only do something if it has assigned a glIndex (which it should have!) */
2309 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2310 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2312 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2313 checkGLcall("glDisable GL_LIGHT0+Index");
2316 TRACE("Nothing to do as light was not enabled\n");
2318 lightInfo->lightEnabled = FALSE;
2321 /* We are enabling it. If it is enabled, it's really simple */
2322 if (lightInfo->lightEnabled) {
2324 TRACE("Nothing to do as light was enabled\n");
2326 /* If it already has a glIndex, it's still simple */
2327 } else if (lightInfo->glIndex != -1) {
2328 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2329 lightInfo->lightEnabled = TRUE;
2331 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2332 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2335 /* Otherwise got to find space - lights are ordered gl indexes first */
2337 PLIGHTINFOEL *bsf = NULL;
2338 PLIGHTINFOEL *pos = This->stateBlock->lights;
2339 PLIGHTINFOEL *prev = NULL;
2343 /* Try to minimize changes as much as possible */
2344 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2346 /* Try to remember which index can be replaced if necessary */
2347 if (bsf==NULL && pos->lightEnabled == FALSE) {
2348 /* Found a light we can replace, save as best replacement */
2352 /* Step to next space */
2358 /* If we have too many active lights, fail the call */
2359 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2360 FIXME("Program requests too many concurrent lights\n");
2361 return D3DERR_INVALIDCALL;
2363 /* If we have allocated all lights, but not all are enabled,
2364 reuse one which is not enabled */
2365 } else if (Index == This->maxConcurrentLights) {
2366 /* use bsf - Simply swap the new light and the BSF one */
2367 PLIGHTINFOEL *bsfNext = bsf->next;
2368 PLIGHTINFOEL *bsfPrev = bsf->prev;
2371 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2372 if (bsf->prev != NULL) {
2373 bsf->prev->next = lightInfo;
2375 This->stateBlock->lights = lightInfo;
2378 /* If not side by side, lots of chains to update */
2379 if (bsf->next != lightInfo) {
2380 lightInfo->prev->next = bsf;
2381 bsf->next->prev = lightInfo;
2382 bsf->next = lightInfo->next;
2383 bsf->prev = lightInfo->prev;
2384 lightInfo->next = bsfNext;
2385 lightInfo->prev = bsfPrev;
2389 bsf->prev = lightInfo;
2390 bsf->next = lightInfo->next;
2391 lightInfo->next = bsf;
2392 lightInfo->prev = bsfPrev;
2397 glIndex = bsf->glIndex;
2399 lightInfo->glIndex = glIndex;
2400 lightInfo->lightEnabled = TRUE;
2402 /* Finally set up the light in gl itself */
2403 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2405 setup_light(iface, glIndex, lightInfo);
2406 glEnable(GL_LIGHT0 + glIndex);
2407 checkGLcall("glEnable GL_LIGHT0 new setup");
2410 /* If we reached the end of the allocated lights, with space in the
2411 gl lights, setup a new light */
2412 } else if (pos->glIndex == -1) {
2414 /* We reached the end of the allocated gl lights, so already
2415 know the index of the next one! */
2417 lightInfo->glIndex = glIndex;
2418 lightInfo->lightEnabled = TRUE;
2420 /* In an ideal world, it's already in the right place */
2421 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2422 /* No need to move it */
2424 /* Remove this light from the list */
2425 lightInfo->prev->next = lightInfo->next;
2426 if (lightInfo->next != NULL) {
2427 lightInfo->next->prev = lightInfo->prev;
2430 /* Add in at appropriate place (inbetween prev and pos) */
2431 lightInfo->prev = prev;
2432 lightInfo->next = pos;
2434 This->stateBlock->lights = lightInfo;
2436 prev->next = lightInfo;
2439 pos->prev = lightInfo;
2443 /* Finally set up the light in gl itself */
2444 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2446 setup_light(iface, glIndex, lightInfo);
2447 glEnable(GL_LIGHT0 + glIndex);
2448 checkGLcall("glEnable GL_LIGHT0 new setup");
2457 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2459 PLIGHTINFOEL *lightInfo = NULL;
2460 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2461 TRACE("(%p) : for idx(%ld)\n", This, Index);
2463 /* Locate the light in the live lights */
2464 lightInfo = This->stateBlock->lights;
2465 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2467 if (lightInfo == NULL) {
2468 TRACE("Light enabled state requested but light not defined\n");
2469 return D3DERR_INVALIDCALL;
2471 *pEnable = lightInfo->lightEnabled;
2476 * Get / Set Clip Planes
2478 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2479 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2480 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2482 /* Validate Index */
2483 if (Index >= GL_LIMITS(clipplanes)) {
2484 TRACE("Application has requested clipplane this device doesn't support\n");
2485 return D3DERR_INVALIDCALL;
2488 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2489 This->updateStateBlock->set.clipplane[Index] = TRUE;
2490 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2491 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2492 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2493 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2495 /* Handle recording of state blocks */
2496 if (This->isRecordingState) {
2497 TRACE("Recording... not performing anything\n");
2505 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2506 glMatrixMode(GL_MODELVIEW);
2508 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2510 TRACE("Clipplane [%f,%f,%f,%f]\n",
2511 This->updateStateBlock->clipplane[Index][0],
2512 This->updateStateBlock->clipplane[Index][1],
2513 This->updateStateBlock->clipplane[Index][2],
2514 This->updateStateBlock->clipplane[Index][3]);
2515 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2516 checkGLcall("glClipPlane");
2524 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2525 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2526 TRACE("(%p) : for idx %ld\n", This, Index);
2528 /* Validate Index */
2529 if (Index >= GL_LIMITS(clipplanes)) {
2530 TRACE("Application has requested clipplane this device doesn't support\n");
2531 return D3DERR_INVALIDCALL;
2534 pPlane[0] = This->stateBlock->clipplane[Index][0];
2535 pPlane[1] = This->stateBlock->clipplane[Index][1];
2536 pPlane[2] = This->stateBlock->clipplane[Index][2];
2537 pPlane[3] = This->stateBlock->clipplane[Index][3];
2542 * Get / Set Clip Plane Status
2543 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2545 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2546 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2547 FIXME("(%p) : stub\n", This);
2548 if (NULL == pClipStatus) {
2549 return D3DERR_INVALIDCALL;
2551 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2552 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2556 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2557 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2558 FIXME("(%p) : stub\n", This);
2559 if (NULL == pClipStatus) {
2560 return D3DERR_INVALIDCALL;
2562 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2563 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2568 * Get / Set Material
2569 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2571 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2572 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2574 This->updateStateBlock->changed.material = TRUE;
2575 This->updateStateBlock->set.material = TRUE;
2576 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2578 /* Handle recording of state blocks */
2579 if (This->isRecordingState) {
2580 TRACE("Recording... not performing anything\n");
2585 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2586 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2587 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2588 pMaterial->Ambient.b, pMaterial->Ambient.a);
2589 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2590 pMaterial->Specular.b, pMaterial->Specular.a);
2591 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2592 pMaterial->Emissive.b, pMaterial->Emissive.a);
2593 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2595 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2596 checkGLcall("glMaterialfv(GL_AMBIENT)");
2597 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2598 checkGLcall("glMaterialfv(GL_DIFFUSE)");
2600 /* Only change material color if specular is enabled, otherwise it is set to black */
2601 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2602 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2603 checkGLcall("glMaterialfv(GL_SPECULAR");
2605 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2606 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2607 checkGLcall("glMaterialfv(GL_SPECULAR");
2609 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2610 checkGLcall("glMaterialfv(GL_EMISSION)");
2611 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2612 checkGLcall("glMaterialf(GL_SHININESS");
2618 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2619 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2620 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2621 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2622 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2623 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2624 pMaterial->Ambient.b, pMaterial->Ambient.a);
2625 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2626 pMaterial->Specular.b, pMaterial->Specular.a);
2627 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2628 pMaterial->Emissive.b, pMaterial->Emissive.a);
2629 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2637 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2638 UINT BaseVertexIndex) {
2639 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2640 IWineD3DIndexBuffer *oldIdxs;
2642 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2643 oldIdxs = This->updateStateBlock->pIndexData;
2645 This->updateStateBlock->changed.indices = TRUE;
2646 This->updateStateBlock->set.indices = TRUE;
2647 This->updateStateBlock->pIndexData = pIndexData;
2648 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2650 /* Handle recording of state blocks */
2651 if (This->isRecordingState) {
2652 TRACE("Recording... not performing anything\n");
2656 if (NULL != pIndexData) {
2657 IWineD3DIndexBuffer_AddRef(pIndexData);
2659 if (NULL != oldIdxs) {
2660 IWineD3DIndexBuffer_Release(oldIdxs);
2665 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2666 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2668 *ppIndexData = This->stateBlock->pIndexData;
2670 /* up ref count on ppindexdata */
2672 IWineD3DIndexBuffer_AddRef(*ppIndexData);
2673 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2674 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
2676 TRACE("(%p) No index data set\n", This);
2678 TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
2684 * Get / Set Viewports
2686 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2687 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2689 TRACE("(%p)\n", This);
2690 This->updateStateBlock->changed.viewport = TRUE;
2691 This->updateStateBlock->set.viewport = TRUE;
2692 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2694 /* Handle recording of state blocks */
2695 if (This->isRecordingState) {
2696 TRACE("Recording... not performing anything\n");
2699 This->viewport_changed = TRUE;
2703 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2704 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2706 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2707 checkGLcall("glDepthRange");
2708 /* Note: GL requires lower left, DirectX supplies upper left */
2709 /* TODO: replace usage of renderTarget with context management */
2710 glViewport(pViewport->X,
2711 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2712 pViewport->Width, pViewport->Height);
2714 checkGLcall("glViewport");
2722 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2723 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2724 TRACE("(%p)\n", This);
2725 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2730 * Get / Set Render States
2731 * TODO: Verify against dx9 definitions
2733 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2735 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2736 DWORD OldValue = This->stateBlock->renderState[State];
2738 /* Simple way of referring to either a DWORD or a 4 byte float */
2744 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2745 This->updateStateBlock->changed.renderState[State] = TRUE;
2746 This->updateStateBlock->set.renderState[State] = TRUE;
2747 This->updateStateBlock->renderState[State] = Value;
2749 /* Handle recording of state blocks */
2750 if (This->isRecordingState) {
2751 TRACE("Recording... not performing anything\n");
2758 case WINED3DRS_FILLMODE :
2759 switch ((D3DFILLMODE) Value) {
2760 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2761 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2762 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2764 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
2766 checkGLcall("glPolygonMode (fillmode)");
2769 case WINED3DRS_LIGHTING :
2771 glEnable(GL_LIGHTING);
2772 checkGLcall("glEnable GL_LIGHTING");
2774 glDisable(GL_LIGHTING);
2775 checkGLcall("glDisable GL_LIGHTING");
2779 case WINED3DRS_ZENABLE :
2780 switch ((D3DZBUFFERTYPE) Value) {
2782 glDisable(GL_DEPTH_TEST);
2783 checkGLcall("glDisable GL_DEPTH_TEST");
2786 glEnable(GL_DEPTH_TEST);
2787 checkGLcall("glEnable GL_DEPTH_TEST");
2790 glEnable(GL_DEPTH_TEST);
2791 checkGLcall("glEnable GL_DEPTH_TEST");
2792 FIXME("W buffer is not well handled\n");
2795 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2799 case WINED3DRS_CULLMODE :
2801 /* If we are culling "back faces with clockwise vertices" then
2802 set front faces to be counter clockwise and enable culling
2804 switch ((D3DCULL) Value) {
2806 glDisable(GL_CULL_FACE);
2807 checkGLcall("glDisable GL_CULL_FACE");
2810 glEnable(GL_CULL_FACE);
2811 checkGLcall("glEnable GL_CULL_FACE");
2812 if (This->renderUpsideDown) {
2814 checkGLcall("glFrontFace GL_CW");
2816 glFrontFace(GL_CCW);
2817 checkGLcall("glFrontFace GL_CCW");
2819 glCullFace(GL_BACK);
2822 glEnable(GL_CULL_FACE);
2823 checkGLcall("glEnable GL_CULL_FACE");
2824 if (This->renderUpsideDown) {
2825 glFrontFace(GL_CCW);
2826 checkGLcall("glFrontFace GL_CCW");
2829 checkGLcall("glFrontFace GL_CW");
2831 glCullFace(GL_BACK);
2834 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2838 case WINED3DRS_SHADEMODE :
2839 switch ((D3DSHADEMODE) Value) {
2841 glShadeModel(GL_FLAT);
2842 checkGLcall("glShadeModel");
2844 case D3DSHADE_GOURAUD:
2845 glShadeModel(GL_SMOOTH);
2846 checkGLcall("glShadeModel");
2848 case D3DSHADE_PHONG:
2849 FIXME("D3DSHADE_PHONG isn't supported?\n");
2852 return D3DERR_INVALIDCALL;
2854 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2858 case WINED3DRS_DITHERENABLE :
2860 glEnable(GL_DITHER);
2861 checkGLcall("glEnable GL_DITHER");
2863 glDisable(GL_DITHER);
2864 checkGLcall("glDisable GL_DITHER");
2868 case WINED3DRS_ZWRITEENABLE :
2871 checkGLcall("glDepthMask");
2874 checkGLcall("glDepthMask");
2878 case WINED3DRS_ZFUNC :
2880 int glParm = GL_LESS;
2882 switch ((D3DCMPFUNC) Value) {
2883 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2884 case D3DCMP_LESS: glParm=GL_LESS; break;
2885 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2886 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2887 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2888 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2889 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2890 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2892 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2894 glDepthFunc(glParm);
2895 checkGLcall("glDepthFunc");
2899 case WINED3DRS_AMBIENT :
2902 D3DCOLORTOGLFLOAT4(Value, col);
2903 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2904 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2905 checkGLcall("glLightModel for MODEL_AMBIENT");
2910 case WINED3DRS_ALPHABLENDENABLE :
2913 checkGLcall("glEnable GL_BLEND");
2915 glDisable(GL_BLEND);
2916 checkGLcall("glDisable GL_BLEND");
2920 case WINED3DRS_SRCBLEND :
2921 case WINED3DRS_DESTBLEND :
2923 int newVal = GL_ZERO;
2925 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2926 case D3DBLEND_ONE : newVal = GL_ONE; break;
2927 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2928 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2929 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2930 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2931 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2932 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2933 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2934 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2935 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2937 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2938 This->srcBlend = newVal;
2939 This->dstBlend = newVal;
2942 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2943 This->srcBlend = newVal;
2944 This->dstBlend = newVal;
2947 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2950 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2951 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2952 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2953 glBlendFunc(This->srcBlend, This->dstBlend);
2955 checkGLcall("glBlendFunc");
2959 case WINED3DRS_ALPHATESTENABLE :
2961 glEnable(GL_ALPHA_TEST);
2962 checkGLcall("glEnable GL_ALPHA_TEST");
2964 glDisable(GL_ALPHA_TEST);
2965 checkGLcall("glDisable GL_ALPHA_TEST");
2969 case WINED3DRS_ALPHAFUNC :
2971 int glParm = GL_LESS;
2972 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2974 switch ((D3DCMPFUNC) Value) {
2975 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2976 case D3DCMP_LESS: glParm = GL_LESS; break;
2977 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2978 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2979 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2980 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2981 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2982 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2984 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2986 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2987 glAlphaFunc(glParm, ref);
2988 This->alphafunc = glParm;
2989 checkGLcall("glAlphaFunc");
2993 case WINED3DRS_ALPHAREF :
2995 int glParm = This->alphafunc;
2998 ref = ((float) Value) / 255.0f;
2999 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
3000 glAlphaFunc(glParm, ref);
3001 checkGLcall("glAlphaFunc");
3005 case WINED3DRS_CLIPPLANEENABLE :
3006 case WINED3DRS_CLIPPING :
3008 /* Ensure we only do the changed clip planes */
3009 DWORD enable = 0xFFFFFFFF;
3010 DWORD disable = 0x00000000;
3012 /* If enabling / disabling all */
3013 if (State == WINED3DRS_CLIPPING) {
3015 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3018 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3022 enable = Value & ~OldValue;
3023 disable = ~Value & OldValue;
3026 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
3027 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
3028 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
3029 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
3030 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
3031 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
3033 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
3034 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
3035 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
3036 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
3037 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
3038 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
3040 /** update clipping status */
3042 This->stateBlock->clip_status.ClipUnion = 0;
3043 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
3045 This->stateBlock->clip_status.ClipUnion = 0;
3046 This->stateBlock->clip_status.ClipIntersection = 0;
3051 case WINED3DRS_BLENDOP :
3053 int glParm = GL_FUNC_ADD;
3055 switch ((D3DBLENDOP) Value) {
3056 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
3057 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
3058 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3059 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
3060 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
3062 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
3064 TRACE("glBlendEquation(%x)\n", glParm);
3065 glBlendEquation(glParm);
3066 checkGLcall("glBlendEquation");
3070 case WINED3DRS_TEXTUREFACTOR :
3074 /* Note the texture color applies to all textures whereas
3075 GL_TEXTURE_ENV_COLOR applies to active only */
3077 D3DCOLORTOGLFLOAT4(Value, col);
3078 /* Set the default alpha blend color */
3079 glBlendColor(col[0], col[1], col[2], col[3]);
3080 checkGLcall("glBlendColor");
3082 /* And now the default texture color as well */
3083 for (i = 0; i < GL_LIMITS(textures); i++) {
3085 /* Note the D3DRS value applies to all textures, but GL has one
3086 per texture, so apply it now ready to be used! */
3087 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3090 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3093 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3094 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3099 case WINED3DRS_SPECULARENABLE :
3101 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3102 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3103 specular color. This is wrong:
3104 Separate specular color means the specular colour is maintained separately, whereas
3105 single color means it is merged in. However in both cases they are being used to
3107 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3108 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3112 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3113 checkGLcall("glMaterialfv");
3114 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3115 glEnable(GL_COLOR_SUM_EXT);
3117 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3119 checkGLcall("glEnable(GL_COLOR_SUM)");
3121 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3123 /* for the case of enabled lighting: */
3124 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3125 checkGLcall("glMaterialfv");
3127 /* for the case of disabled lighting: */
3128 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3129 glDisable(GL_COLOR_SUM_EXT);
3131 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3133 checkGLcall("glDisable(GL_COLOR_SUM)");
3138 case WINED3DRS_STENCILENABLE :
3140 glEnable(GL_STENCIL_TEST);
3141 checkGLcall("glEnable GL_STENCIL_TEST");
3143 glDisable(GL_STENCIL_TEST);
3144 checkGLcall("glDisable GL_STENCIL_TEST");
3148 case WINED3DRS_STENCILFUNC :
3151 GLint ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3152 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3155 switch ((D3DCMPFUNC)Value) {
3156 case D3DCMP_NEVER: func = GL_NEVER; break;
3157 case D3DCMP_LESS: func = GL_LESS; break;
3158 case D3DCMP_EQUAL: func = GL_EQUAL; break;
3159 case D3DCMP_LESSEQUAL: func = GL_LEQUAL; break;
3160 case D3DCMP_GREATER: func = GL_GREATER; break;
3161 case D3DCMP_NOTEQUAL: func = GL_NOTEQUAL; break;
3162 case D3DCMP_GREATEREQUAL: func = GL_GEQUAL; break;
3163 case D3DCMP_ALWAYS: func = GL_ALWAYS; break;
3165 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3167 This->stencilfunc = func;
3168 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3169 #if 0 /* Don't use OpenGL 2.0 calls for now */
3170 if(GL_EXTCALL(glStencilFuncSeparate)) {
3171 GL_EXTCALL(glStencilFuncSeparate(GL_FRONT, func, ref, mask));
3172 checkGLcall("glStencilFuncSeparate(GL_FRONT,...)");
3176 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3177 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3178 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3179 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
3180 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
3181 glStencilFunc(func, ref, mask);
3182 checkGLcall("glStencilFunc(...)");
3184 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3185 GL_EXTCALL(glStencilFuncSeparateATI(GL_FRONT, func, ref, mask));
3186 checkGLcall("glStencilFuncSeparateATI(GL_FRONT,...)");
3188 TRACE("Separate stencil function not supported on this version of opengl");
3189 glStencilFunc(func, ref, mask);
3190 checkGLcall("glStencilFunc(...)");
3193 glStencilFunc(func, ref, mask);
3194 checkGLcall("glStencilFunc(...)");
3198 case WINED3DRS_STENCILREF :
3200 int glParm = This->stencilfunc;
3202 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3205 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3206 glStencilFunc(glParm, ref, mask);
3207 checkGLcall("glStencilFunc");
3211 case WINED3DRS_STENCILMASK :
3213 int glParm = This->stencilfunc;
3214 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3215 GLuint mask = Value;
3217 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3218 glStencilFunc(glParm, ref, mask);
3219 checkGLcall("glStencilFunc");
3223 case WINED3DRS_STENCILFAIL :
3224 case WINED3DRS_STENCILZFAIL :
3225 case WINED3DRS_STENCILPASS :
3231 GLint action = StencilOp(Value);
3233 glGetIntegerv(GL_STENCIL_FAIL, &stencilFail);
3234 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &depthFail);
3235 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &stencilPass);
3237 if(WINED3DRS_STENCILFAIL == State) {
3238 stencilFail = action;
3240 else if(WINED3DRS_STENCILZFAIL == State) {
3243 else if(WINED3DRS_STENCILPASS == State) {
3244 stencilPass = action;
3247 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3248 #if 0 /* Don't use OpenGL 2.0 calls for now */
3249 if(GL_EXTCALL(glStencilOpSeparate)) {
3250 GL_EXTCALL(glStencilOpSeparate(GL_FRONT, stencilFail, depthFail, stencilPass));
3251 checkGLcall("glStencilOpSeparate(GL_FRONT,...)");
3255 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3256 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3257 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3258 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
3259 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
3260 glStencilOp(stencilFail, depthFail, stencilPass);
3261 checkGLcall("glStencilOp(...)");
3263 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3264 GL_EXTCALL(glStencilOpSeparateATI(GL_FRONT, stencilFail, depthFail, stencilPass));
3265 checkGLcall("glStencilOpSeparateATI(GL_FRONT,...)");
3267 TRACE("Separate stencil operation not supported on this version of opengl");
3268 glStencilOp(stencilFail, depthFail, stencilPass);
3269 checkGLcall("glStencilOp(...)");
3272 glStencilOp(stencilFail, depthFail, stencilPass);
3273 checkGLcall("glStencilOp(...)");
3277 case WINED3DRS_STENCILWRITEMASK :
3279 glStencilMask(Value);
3280 TRACE("glStencilMask(%lu)\n", Value);
3281 checkGLcall("glStencilMask");
3285 case WINED3DRS_FOGENABLE :
3287 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
3289 checkGLcall("glEnable GL_FOG");
3292 checkGLcall("glDisable GL_FOG");
3297 case WINED3DRS_RANGEFOGENABLE :
3300 TRACE("Enabled RANGEFOG");
3302 TRACE("Disabled RANGEFOG");
3307 case WINED3DRS_FOGCOLOR :
3310 D3DCOLORTOGLFLOAT4(Value, col);
3311 /* Set the default alpha blend color */
3312 glFogfv(GL_FOG_COLOR, &col[0]);
3313 checkGLcall("glFog GL_FOG_COLOR");
3317 case WINED3DRS_FOGTABLEMODE :
3319 glHint(GL_FOG_HINT, GL_NICEST);
3321 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3322 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3323 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3324 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3326 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3328 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3329 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3334 case WINED3DRS_FOGVERTEXMODE :
3336 glHint(GL_FOG_HINT, GL_FASTEST);
3338 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3339 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3340 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3341 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3343 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3345 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3346 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
3351 case WINED3DRS_FOGSTART :
3354 glFogfv(GL_FOG_START, &tmpvalue.f);
3355 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3356 TRACE("Fog Start == %f\n", tmpvalue.f);
3360 case WINED3DRS_FOGEND :
3363 glFogfv(GL_FOG_END, &tmpvalue.f);
3364 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3365 TRACE("Fog End == %f\n", tmpvalue.f);
3369 case WINED3DRS_FOGDENSITY :
3372 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3373 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3377 case WINED3DRS_VERTEXBLEND :
3379 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3380 TRACE("Vertex Blending state to %ld\n", Value);
3384 case WINED3DRS_TWEENFACTOR :
3387 This->updateStateBlock->tween_factor = tmpvalue.f;
3388 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3392 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
3394 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3398 case WINED3DRS_COLORVERTEX :
3399 case WINED3DRS_DIFFUSEMATERIALSOURCE :
3400 case WINED3DRS_SPECULARMATERIALSOURCE :
3401 case WINED3DRS_AMBIENTMATERIALSOURCE :
3402 case WINED3DRS_EMISSIVEMATERIALSOURCE :
3404 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3406 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3407 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3408 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3409 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3410 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3411 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3413 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3414 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3415 Parm = GL_AMBIENT_AND_DIFFUSE;
3419 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3421 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3423 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3430 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3432 This->tracking_color = NEEDS_TRACKING;
3433 This->tracking_parm = Parm;
3437 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3442 case WINED3DRS_LINEPATTERN :
3448 tmppattern.d = Value;
3450 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3452 if (tmppattern.lp.wRepeatFactor) {
3453 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3454 checkGLcall("glLineStipple(repeat, linepattern)");
3455 glEnable(GL_LINE_STIPPLE);
3456 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3458 glDisable(GL_LINE_STIPPLE);
3459 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3464 case WINED3DRS_ZBIAS : /* D3D8 only */
3468 TRACE("ZBias value %f\n", tmpvalue.f);
3469 glPolygonOffset(0, -tmpvalue.f);
3470 checkGLcall("glPolygonOffset(0, -Value)");
3471 glEnable(GL_POLYGON_OFFSET_FILL);
3472 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3473 glEnable(GL_POLYGON_OFFSET_LINE);
3474 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3475 glEnable(GL_POLYGON_OFFSET_POINT);
3476 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3478 glDisable(GL_POLYGON_OFFSET_FILL);
3479 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3480 glDisable(GL_POLYGON_OFFSET_LINE);
3481 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3482 glDisable(GL_POLYGON_OFFSET_POINT);
3483 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3488 case WINED3DRS_NORMALIZENORMALS :
3490 glEnable(GL_NORMALIZE);
3491 checkGLcall("glEnable(GL_NORMALIZE);");
3493 glDisable(GL_NORMALIZE);
3494 checkGLcall("glDisable(GL_NORMALIZE);");
3498 case WINED3DRS_POINTSIZE :
3499 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
3501 TRACE("Set point size to %f\n", tmpvalue.f);
3502 glPointSize(tmpvalue.f);
3503 checkGLcall("glPointSize(...);");
3506 case WINED3DRS_POINTSIZE_MIN :
3507 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3509 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3510 checkGLcall("glPointParameterfEXT(...);");
3512 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3516 case WINED3DRS_POINTSIZE_MAX :
3517 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3519 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3520 checkGLcall("glPointParameterfEXT(...);");
3522 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3526 case WINED3DRS_POINTSCALE_A :
3527 case WINED3DRS_POINTSCALE_B :
3528 case WINED3DRS_POINTSCALE_C :
3529 case WINED3DRS_POINTSCALEENABLE :
3532 * POINTSCALEENABLE controls how point size value is treated. If set to
3533 * true, the point size is scaled with respect to height of viewport.
3534 * When set to false point size is in pixels.
3536 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
3539 /* Default values */
3540 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3543 * Minimum valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
3544 * This means that OpenGL will clamp really small point sizes to 1.0f.
3545 * To correct for this we need to multiply by the scale factor when sizes
3546 * are less than 1.0f. scale_factor = 1.0f / point_size.
3548 GLfloat pointSize = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSIZE]);
3549 if(pointSize > 0.0f) {
3550 GLfloat scaleFactor;
3552 if(pointSize < 1.0f) {
3553 scaleFactor = pointSize * pointSize;
3558 if(This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3559 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]) /
3560 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3561 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]) /
3562 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3563 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) /
3564 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3568 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
3569 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
3570 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
3572 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3573 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3574 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
3576 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
3580 case WINED3DRS_COLORWRITEENABLE :
3582 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3583 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3584 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3585 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3586 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3587 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3588 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3589 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3590 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3591 checkGLcall("glColorMask(...)");
3595 case WINED3DRS_LOCALVIEWER :
3597 GLint state = (Value) ? 1 : 0;
3598 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3599 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3603 case WINED3DRS_LASTPIXEL :
3606 TRACE("Last Pixel Drawing Enabled\n");
3608 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3613 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3616 TRACE("Software Processing Enabled\n");
3618 TRACE("Software Processing Disabled\n");
3623 /** not supported */
3624 case WINED3DRS_ZVISIBLE :
3627 return D3DERR_INVALIDCALL;
3629 case WINED3DRS_POINTSPRITEENABLE :
3631 /* TODO: NV_POINT_SPRITE */
3632 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
3633 TRACE("Point sprites not supported\n");
3638 * Point sprites are always enabled. Value controls texture coordinate
3639 * replacement mode. Must be set true for point sprites to use
3642 glEnable(GL_POINT_SPRITE_ARB);
3643 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
3646 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
3647 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, TRUE)");
3649 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, FALSE);
3650 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, FALSE)");
3654 case WINED3DRS_EDGEANTIALIAS :
3657 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3659 checkGLcall("glEnable(GL_BLEND)");
3660 glEnable(GL_LINE_SMOOTH);
3661 checkGLcall("glEnable(GL_LINE_SMOOTH)");
3663 glDisable(GL_BLEND);
3664 checkGLcall("glDisable(GL_BLEND)");
3665 glDisable(GL_LINE_SMOOTH);
3666 checkGLcall("glDisable(GL_LINE_SMOOTH)");
3670 case WINED3DRS_WRAP0 :
3671 case WINED3DRS_WRAP1 :
3672 case WINED3DRS_WRAP2 :
3673 case WINED3DRS_WRAP3 :
3674 case WINED3DRS_WRAP4 :
3675 case WINED3DRS_WRAP5 :
3676 case WINED3DRS_WRAP6 :
3677 case WINED3DRS_WRAP7 :
3679 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
3680 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
3681 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
3682 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
3683 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
3685 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
3687 TRACE("(%p)->(%d,%ld) Texture wraping not yet supported\n",This, State, Value);
3689 case WINED3DRS_MULTISAMPLEANTIALIAS :
3691 if (!GL_SUPPORT(ARB_MULTISAMPLE)) {
3692 TRACE("Multisample antialiasing not supported\n");
3697 glEnable(GL_MULTISAMPLE_ARB);
3698 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
3700 glDisable(GL_MULTISAMPLE_ARB);
3701 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
3705 case WINED3DRS_SCISSORTESTENABLE :
3708 glEnable(GL_SCISSOR_TEST);
3709 checkGLcall("glEnable(GL_SCISSOR_TEST)");
3711 glDisable(GL_SCISSOR_TEST);
3712 checkGLcall("glDisable(GL_SCISSOR_TEST)");
3716 case WINED3DRS_SLOPESCALEDEPTHBIAS :
3720 glEnable(GL_POLYGON_OFFSET_FILL);
3721 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
3722 glPolygonOffset(tmpvalue.f, *((float*)&This->stateBlock->renderState[WINED3DRS_DEPTHBIAS]));
3723 checkGLcall("glPolygonOffset(...)");
3725 glDisable(GL_POLYGON_OFFSET_FILL);
3726 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
3730 case WINED3DRS_ANTIALIASEDLINEENABLE :
3733 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3735 checkGLcall("glEnable(GL_BLEND)");
3736 glEnable(GL_LINE_SMOOTH);
3737 checkGLcall("glEnable(GL_LINE_SMOOTH)");
3739 glDisable(GL_BLEND);
3740 checkGLcall("glDisable(GL_BLEND)");
3741 glDisable(GL_LINE_SMOOTH);
3742 checkGLcall("glDisable(GL_LINE_SMOOTH)");
3746 case WINED3DRS_MULTISAMPLEMASK :
3747 case WINED3DRS_PATCHEDGESTYLE :
3748 case WINED3DRS_PATCHSEGMENTS :
3749 case WINED3DRS_DEBUGMONITORTOKEN :
3750 case WINED3DRS_POSITIONORDER :
3751 case WINED3DRS_NORMALORDER :
3752 /* Direct3D9 render states */
3753 case WINED3DRS_MINTESSELLATIONLEVEL :
3754 case WINED3DRS_MAXTESSELLATIONLEVEL :
3755 case WINED3DRS_ADAPTIVETESS_X :
3756 case WINED3DRS_ADAPTIVETESS_Y :
3757 case WINED3DRS_ADAPTIVETESS_Z :
3758 case WINED3DRS_ADAPTIVETESS_W :
3759 case WINED3DRS_ENABLEADAPTIVETESSELLATION :
3761 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3764 case WINED3DRS_TWOSIDEDSTENCILMODE :
3767 TRACE("Two-sided stencil mode enabled\n");
3769 TRACE("Two-sided stencil mode disabled\n");
3773 case WINED3DRS_CCW_STENCILFAIL :
3774 case WINED3DRS_CCW_STENCILZFAIL :
3775 case WINED3DRS_CCW_STENCILPASS :
3781 GLint action = StencilOp(Value);
3783 glGetIntegerv(GL_STENCIL_BACK_FAIL, &stencilFail);
3784 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &depthFail);
3785 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS, &stencilPass);
3787 if(WINED3DRS_CCW_STENCILFAIL == State) {
3788 stencilFail = action;
3790 else if(WINED3DRS_CCW_STENCILZFAIL == State) {
3793 else if(WINED3DRS_CCW_STENCILPASS == State) {
3794 stencilPass = action;
3797 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3798 #if 0 /* Don't use OpenGL 2.0 calls for now */
3799 if(GL_EXTCALL(glStencilOpSeparate)) {
3800 GL_EXTCALL(glStencilOpSeparate(GL_BACK, stencilFail, depthFail, stencilPass));
3801 checkGLcall("glStencilOpSeparate(GL_BACK,...)");
3805 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3806 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3807 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3808 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
3809 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
3810 glStencilOp(stencilFail, depthFail, stencilPass);
3811 checkGLcall("glStencilOp(...)");
3813 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3814 GL_EXTCALL(glStencilOpSeparateATI(GL_BACK, stencilFail, depthFail, stencilPass));
3815 checkGLcall("glStencilOpSeparateATI(GL_BACK,...)");
3817 TRACE("Separate stencil operation not supported on this version of opengl");
3818 glStencilOp(stencilFail, depthFail, stencilPass);
3819 checkGLcall("glStencilOp(...)");
3822 glStencilOp(stencilFail, depthFail, stencilPass);
3823 checkGLcall("glStencilOp(...)");
3827 case WINED3DRS_CCW_STENCILFUNC :
3830 GLint ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3831 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3834 switch ((D3DCMPFUNC)Value) {
3835 case D3DCMP_NEVER: func = GL_NEVER; break;
3836 case D3DCMP_LESS: func = GL_LESS; break;
3837 case D3DCMP_EQUAL: func = GL_EQUAL; break;
3838 case D3DCMP_LESSEQUAL: func = GL_LEQUAL; break;
3839 case D3DCMP_GREATER: func = GL_GREATER; break;
3840 case D3DCMP_NOTEQUAL: func = GL_NOTEQUAL; break;
3841 case D3DCMP_GREATEREQUAL: func = GL_GEQUAL; break;
3842 case D3DCMP_ALWAYS: func = GL_ALWAYS; break;
3844 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3846 This->stencilfunc = func;
3847 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3848 #if 0 /* Don't use OpenGL 2.0 calls for now */
3849 if(GL_EXTCALL(glStencilFuncSeparate)) {
3850 GL_EXTCALL(glStencilFuncSeparate(GL_BACK, func, ref, mask));
3851 checkGLcall("glStencilFuncSeparate(GL_BACK,...)");
3855 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3856 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3857 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3858 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
3859 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
3860 glStencilFunc(func, ref, mask);
3861 checkGLcall("glStencilFunc(...)");
3863 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3864 GL_EXTCALL(glStencilFuncSeparateATI(GL_BACK, func, ref, mask));
3865 checkGLcall("glStencilFuncSeparateATI(GL_BACK,...)");
3867 TRACE("Separate stencil function not supported on this version of opengl");
3868 glStencilFunc(func, ref, mask);
3869 checkGLcall("glStencilFunc(...)");
3872 glStencilFunc(func, ref, mask);
3873 checkGLcall("glStencilFunc(...)");
3877 case WINED3DRS_COLORWRITEENABLE1 :
3878 case WINED3DRS_COLORWRITEENABLE2 :
3879 case WINED3DRS_COLORWRITEENABLE3 :
3880 case WINED3DRS_BLENDFACTOR :
3881 case WINED3DRS_SRGBWRITEENABLE :
3883 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3886 case WINED3DRS_DEPTHBIAS :
3890 glEnable(GL_POLYGON_OFFSET_FILL);
3891 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
3892 glPolygonOffset(*((float*)&This->stateBlock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS]), tmpvalue.f);
3893 checkGLcall("glPolygonOffset(...)");
3895 glDisable(GL_POLYGON_OFFSET_FILL);
3896 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
3900 case WINED3DRS_WRAP8 :
3901 case WINED3DRS_WRAP9 :
3902 case WINED3DRS_WRAP10 :
3903 case WINED3DRS_WRAP11 :
3904 case WINED3DRS_WRAP12 :
3905 case WINED3DRS_WRAP13 :
3906 case WINED3DRS_WRAP14 :
3907 case WINED3DRS_WRAP15 :
3908 case WINED3DRS_SEPARATEALPHABLENDENABLE :
3909 case WINED3DRS_SRCBLENDALPHA :
3910 case WINED3DRS_DESTBLENDALPHA :
3911 case WINED3DRS_BLENDOPALPHA :
3912 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3913 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3916 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3924 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3925 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3926 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3927 *pValue = This->stateBlock->renderState[State];
3932 * Get / Set Sampler States
3933 * TODO: Verify against dx9 definitions
3936 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3937 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3939 * SetSampler is designed to allow for more than the standard up to 8 textures
3940 * and Geforce has stopped supporting more than 6 standard textures in openGL.
3941 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3943 * http://developer.nvidia.com/object/General_FAQ.html#t6
3945 * There are two new settings for GForce
3947 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3948 * and the texture one:
3949 * GL_MAX_TEXTURE_COORDS_ARB.
3950 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3952 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
3953 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
3955 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
3956 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE, Sampler, Type);
3957 return D3DERR_INVALIDCALL;
3959 TRACE("Setting sampler %ld %d to %ld\n", Sampler, Type, Value);
3960 This->updateStateBlock->samplerState[Sampler][Type] = Value;
3961 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
3962 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
3964 /* Handle recording of state blocks */
3965 if (This->isRecordingState) {
3966 TRACE("Recording... not performing anything\n");
3973 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3974 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3975 /** TODO: check that sampler is in range **/
3976 *Value = This->updateStateBlock->samplerState[Sampler][Type];
3977 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
3982 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3983 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3986 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3987 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3988 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3994 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3995 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3996 GLint scissorBox[4];
3999 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4000 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
4001 pRect->left = scissorBox[1];
4002 pRect->top = scissorBox[2];
4003 pRect->right = scissorBox[1] + scissorBox[3];
4004 pRect->bottom = scissorBox[2] + scissorBox[4];
4005 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4010 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
4011 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4012 IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
4014 TRACE("(%p) : pDecl=%p\n", This, pDecl);
4016 This->updateStateBlock->vertexDecl = pDecl;
4017 This->updateStateBlock->changed.vertexDecl = TRUE;
4018 This->updateStateBlock->set.vertexDecl = TRUE;
4020 if (This->isRecordingState) {
4021 TRACE("Recording... not performing anything\n");
4024 if (NULL != pDecl) {
4025 IWineD3DVertexDeclaration_AddRef(pDecl);
4027 if (NULL != oldDecl) {
4028 IWineD3DVertexDeclaration_Release(oldDecl);
4033 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
4034 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4036 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
4038 *ppDecl = This->stateBlock->vertexDecl;
4039 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
4043 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
4044 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4045 IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
4047 This->updateStateBlock->vertexShader = pShader;
4048 This->updateStateBlock->changed.vertexShader = TRUE;
4049 This->updateStateBlock->set.vertexShader = TRUE;
4051 if (This->isRecordingState) {
4052 TRACE("Recording... not performing anything\n");
4055 if (NULL != pShader) {
4056 IWineD3DVertexShader_AddRef(pShader);
4058 if (NULL != oldShader) {
4059 IWineD3DVertexShader_Release(oldShader);
4062 if (pShader != NULL && ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration != NULL) {
4063 TRACE("(%p) : setting vertexDeclaration(%p)\n", This, ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration);
4064 IWineD3DDevice_SetVertexDeclaration(iface, ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration);
4067 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4069 * TODO: merge HAL shaders context switching from prototype
4074 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
4075 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4077 if (NULL == ppShader) {
4078 return D3DERR_INVALIDCALL;
4080 *ppShader = This->stateBlock->vertexShader;
4081 if( NULL != *ppShader)
4082 IWineD3DVertexShader_AddRef(*ppShader);
4084 TRACE("(%p) : returning %p\n", This, *ppShader);
4088 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4089 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4092 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4094 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4095 iface, dstData, srcData, type, start, count, registersize);
4097 if (type != WINESHADERCNST_NONE) {
4098 if (srcData == NULL || cnt < 0) {
4099 return D3DERR_INVALIDCALL;
4102 CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
4105 for (i = start; i < cnt + start; ++i) {
4106 This->updateStateBlock->changed.vertexShaderConstants[i] = TRUE;
4107 This->updateStateBlock->set.vertexShaderConstants[i] = TRUE;
4108 This->updateStateBlock->vertexShaderConstantT[i] = type;
4114 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4115 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4118 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4120 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4121 iface, dstData, srcData, type, start, count, registersize);
4123 /* Verify that the requested shader constant was populated with the correct type */
4124 for (i = start; i < cnt + start; ++i) {
4125 if (This->updateStateBlock->vertexShaderConstantT[i] != type) {
4126 TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning D3DERR_INVALIDCALL\n",
4127 This, type, This->updateStateBlock->vertexShaderConstantT[i]);
4128 return D3DERR_INVALIDCALL;
4132 if (dstData == NULL || cnt < 0) {
4133 return D3DERR_INVALIDCALL;
4136 CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
4141 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
4142 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4144 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4145 This->updateStateBlock->vertexShaderConstantB,
4147 WINESHADERCNST_BOOL,
4150 sizeof(*pConstantData));
4153 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
4154 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4156 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4158 This->updateStateBlock->vertexShaderConstantB,
4159 WINESHADERCNST_BOOL,
4162 sizeof(*pConstantData));
4165 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
4166 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4168 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4169 This->updateStateBlock->vertexShaderConstantI,
4171 WINESHADERCNST_INTEGER,
4174 4 * sizeof(*pConstantData));
4177 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
4178 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4180 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4182 This->updateStateBlock->vertexShaderConstantI,
4183 WINESHADERCNST_INTEGER,
4186 4 * sizeof(*pConstantData));
4190 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
4191 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4193 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4194 This->updateStateBlock->vertexShaderConstantF,
4196 WINESHADERCNST_FLOAT,
4199 4 * sizeof(*pConstantData));
4202 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
4203 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4205 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4207 This->updateStateBlock->vertexShaderConstantF,
4208 WINESHADERCNST_FLOAT,
4211 4 * sizeof(*pConstantData));
4214 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
4215 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4218 WINESHADERCNST_NONE,
4224 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
4225 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4226 IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader;
4227 This->updateStateBlock->pixelShader = pShader;
4228 This->updateStateBlock->changed.pixelShader = TRUE;
4229 This->updateStateBlock->set.pixelShader = TRUE;
4231 /* Handle recording of state blocks */
4232 if (This->isRecordingState) {
4233 TRACE("Recording... not performing anything\n");
4236 if (NULL != pShader) {
4237 IWineD3DPixelShader_AddRef(pShader);
4239 if (NULL != oldShader) {
4240 IWineD3DPixelShader_Release(oldShader);
4243 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4245 * TODO: merge HAL shaders context switching from prototype
4250 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
4251 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4253 if (NULL == ppShader) {
4254 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
4255 return D3DERR_INVALIDCALL;
4258 *ppShader = This->stateBlock->pixelShader;
4259 if (NULL != ppShader) {
4260 IWineD3DPixelShader_AddRef(*ppShader);
4262 TRACE("(%p) : returning %p\n", This, *ppShader);
4266 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4267 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4270 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4272 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4273 iface, dstData, srcData, type, start, count, registersize);
4275 if (type != WINESHADERCNST_NONE) {
4276 if (srcData == NULL || cnt < 0) {
4277 return D3DERR_INVALIDCALL;
4280 CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
4283 for (i = start; i < cnt + start; ++i) {
4284 This->updateStateBlock->changed.pixelShaderConstants[i] = TRUE;
4285 This->updateStateBlock->set.pixelShaderConstants[i] = TRUE;
4286 This->updateStateBlock->pixelShaderConstantT[i] = type;
4292 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4293 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4296 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4298 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4299 iface, dstData, srcData, type, start, count, registersize);
4301 /* Verify that the requested shader constant was populated with the correct type */
4302 for (i = start; i < cnt + start; ++i) {
4303 if (This->updateStateBlock->pixelShaderConstantT[i] != type) {
4304 TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning D3DERR_INVALIDCALL\n",
4305 This, type, This->updateStateBlock->pixelShaderConstantT[i]);
4306 return D3DERR_INVALIDCALL;
4310 if (dstData == NULL || cnt < 0) {
4311 return D3DERR_INVALIDCALL;
4314 CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
4319 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
4320 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4322 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4323 This->updateStateBlock->pixelShaderConstantB,
4325 WINESHADERCNST_BOOL,
4328 sizeof(*pConstantData));
4331 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
4332 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4334 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4336 This->updateStateBlock->pixelShaderConstantB,
4337 WINESHADERCNST_BOOL,
4340 sizeof(*pConstantData));
4343 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
4344 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4346 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4347 This->updateStateBlock->pixelShaderConstantI,
4349 WINESHADERCNST_INTEGER,
4352 4 * sizeof(*pConstantData));
4355 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
4356 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4358 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4360 This->updateStateBlock->pixelShaderConstantI,
4361 WINESHADERCNST_INTEGER,
4364 4 * sizeof(*pConstantData));
4367 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
4368 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4370 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4371 This->updateStateBlock->pixelShaderConstantF,
4373 WINESHADERCNST_FLOAT,
4376 4 * sizeof(*pConstantData));
4379 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
4380 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4382 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4384 This->updateStateBlock->pixelShaderConstantF,
4385 WINESHADERCNST_FLOAT,
4388 4 * sizeof(*pConstantData));
4391 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
4392 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4395 WINESHADERCNST_NONE,
4401 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
4402 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4403 FIXME("(%p) : stub\n", This);
4408 * Apply / Get / Set Texture Stage States
4409 * TODO: Verify against dx9 definitions
4412 /* 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 */
4413 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
4414 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4415 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
4416 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4418 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4420 /* Check that the stage is within limits */
4421 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4422 TRACE("Attempt to access invalid texture rejected\n");
4429 case WINED3DTSS_ALPHAOP :
4430 case WINED3DTSS_COLOROP :
4431 /* nothing to do as moved to drawprim for now */
4433 case WINED3DTSS_ADDRESSW :
4434 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
4435 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
4436 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
4439 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
4440 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
4441 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
4442 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
4445 case WINED3DTSS_TEXCOORDINDEX :
4447 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
4449 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
4450 one flag, you can still specify an index value, which the system uses to
4451 determine the texture wrapping mode.
4452 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
4453 means use the vertex position (camera-space) as the input texture coordinates
4454 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
4455 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
4456 to the TEXCOORDINDEX value */
4459 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
4461 switch (Value & 0xFFFF0000) {
4462 case D3DTSS_TCI_PASSTHRU:
4463 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
4464 glDisable(GL_TEXTURE_GEN_S);
4465 glDisable(GL_TEXTURE_GEN_T);
4466 glDisable(GL_TEXTURE_GEN_R);
4467 glDisable(GL_TEXTURE_GEN_Q);
4468 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
4471 case D3DTSS_TCI_CAMERASPACEPOSITION:
4472 /* CameraSpacePosition means use the vertex position, transformed to camera space,
4473 as the input texture coordinates for this stage's texture transformation. This
4474 equates roughly to EYE_LINEAR */
4476 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4477 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4478 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4479 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4480 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4482 glMatrixMode(GL_MODELVIEW);
4485 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4486 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4487 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4488 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4491 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
4492 glEnable(GL_TEXTURE_GEN_S);
4493 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4494 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4495 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4496 glEnable(GL_TEXTURE_GEN_T);
4497 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4498 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4499 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4500 glEnable(GL_TEXTURE_GEN_R);
4501 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4502 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4503 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4507 case D3DTSS_TCI_CAMERASPACENORMAL:
4509 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4510 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4511 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4512 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4513 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4514 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
4516 glMatrixMode(GL_MODELVIEW);
4519 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4520 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4521 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4522 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4525 glEnable(GL_TEXTURE_GEN_S);
4526 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4527 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4528 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4529 glEnable(GL_TEXTURE_GEN_T);
4530 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4531 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4532 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4533 glEnable(GL_TEXTURE_GEN_R);
4534 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4535 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4536 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4541 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
4543 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4544 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4545 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4546 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4547 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4548 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
4550 glMatrixMode(GL_MODELVIEW);
4553 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4554 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4555 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4556 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4559 glEnable(GL_TEXTURE_GEN_S);
4560 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4561 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4562 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4563 glEnable(GL_TEXTURE_GEN_T);
4564 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4565 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4566 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4567 glEnable(GL_TEXTURE_GEN_R);
4568 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4569 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4570 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4575 /* Unhandled types: */
4578 /* ? disable GL_TEXTURE_GEN_n ? */
4579 glDisable(GL_TEXTURE_GEN_S);
4580 glDisable(GL_TEXTURE_GEN_T);
4581 glDisable(GL_TEXTURE_GEN_R);
4582 glDisable(GL_TEXTURE_GEN_Q);
4583 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
4590 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
4591 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);
4594 case WINED3DTSS_BUMPENVMAT00 :
4595 case WINED3DTSS_BUMPENVMAT01 :
4596 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
4598 case WINED3DTSS_BUMPENVMAT10 :
4599 case WINED3DTSS_BUMPENVMAT11 :
4600 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
4603 case WINED3DTSS_BUMPENVLSCALE :
4604 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4607 case WINED3DTSS_BUMPENVLOFFSET :
4608 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4611 case WINED3DTSS_RESULTARG :
4612 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4616 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
4617 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4626 * Get / Set Texture Stage States
4627 * TODO: Verify against dx9 definitions
4629 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
4630 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4632 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4634 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4636 /* Reject invalid texture units */
4637 if (Stage >= GL_LIMITS(textures)) {
4638 TRACE("Attempt to access invalid texture rejected\n");
4639 return D3DERR_INVALIDCALL;
4642 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
4643 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
4644 This->updateStateBlock->textureState[Stage][Type] = Value;
4649 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4650 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4651 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4652 *pValue = This->updateStateBlock->textureState[Stage][Type];
4659 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4661 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4662 IWineD3DBaseTexture *oldTexture;
4664 oldTexture = This->updateStateBlock->textures[Stage];
4665 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
4667 #if 0 /* TODO: check so vertex textures */
4668 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
4669 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
4674 /* Reject invalid texture units */
4675 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4676 WARN("Attempt to access invalid texture rejected\n");
4677 return D3DERR_INVALIDCALL;
4680 if(pTexture != NULL) {
4681 /* SetTexture isn't allowed on textures in D3DPOOL_SCRATCH; The same is
4682 * the case for D3DPOOL_SYSTEMMEM textures unless WINED3DDEVCAPS_TEXTURESYSTEMMORY is set.
4683 * We don't check the caps as GetDeviceCaps is inefficient and we don't set the cap anyway.
4685 if(((IWineD3DTextureImpl*)pTexture)->resource.pool == D3DPOOL_SCRATCH || ((IWineD3DTextureImpl*)pTexture)->resource.pool == D3DPOOL_SYSTEMMEM) {
4686 WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
4687 return D3DERR_INVALIDCALL;
4691 oldTexture = This->updateStateBlock->textures[Stage];
4692 TRACE("GL_LIMITS %d\n",GL_LIMITS(textures));
4693 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
4695 This->updateStateBlock->set.textures[Stage] = TRUE;
4696 This->updateStateBlock->changed.textures[Stage] = TRUE;
4697 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
4698 This->updateStateBlock->textures[Stage] = pTexture;
4700 /* Handle recording of state blocks */
4701 if (This->isRecordingState) {
4702 TRACE("Recording... not performing anything\n");
4706 /** NOTE: MSDN says that setTexture increases the reference count,
4707 * and the the application nust set the texture back to null (or have a leaky application),
4708 * This means we should pass the refcount up to the parent
4709 *******************************/
4710 if (NULL != This->updateStateBlock->textures[Stage]) {
4711 IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
4714 if (NULL != oldTexture) {
4715 IWineD3DBaseTexture_Release(oldTexture);
4721 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4722 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4723 TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
4725 /* Reject invalid texture units */
4726 if (Stage >= GL_LIMITS(textures)) {
4727 TRACE("Attempt to access invalid texture rejected\n");
4728 return D3DERR_INVALIDCALL;
4730 *ppTexture=This->updateStateBlock->textures[Stage];
4732 IWineD3DBaseTexture_AddRef(*ppTexture);
4734 return D3DERR_INVALIDCALL;
4741 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type,
4742 IWineD3DSurface **ppBackBuffer) {
4743 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4744 IWineD3DSwapChain *swapChain;
4747 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4749 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4751 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4752 IWineD3DSwapChain_Release(swapChain);
4754 *ppBackBuffer = NULL;
4759 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4760 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4761 WARN("(%p) : stub, calling idirect3d for now\n", This);
4762 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4765 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
4766 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4767 IWineD3DSwapChain *swapChain;
4770 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4772 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4773 IWineD3DSwapChain_Release(swapChain);
4775 FIXME("(%p) Error getting display mode\n", This);
4780 * Stateblock related functions
4783 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4784 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4785 IWineD3DStateBlockImpl *object;
4786 TRACE("(%p)", This);
4788 if (This->isRecordingState) {
4789 return D3DERR_INVALIDCALL;
4792 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4793 if (NULL == object ) {
4794 FIXME("(%p)Error allocating memory for stateblock\n", This);
4795 return E_OUTOFMEMORY;
4797 TRACE("(%p) creted object %p\n", This, object);
4798 object->wineD3DDevice= This;
4799 /** FIXME: object->parent = parent; **/
4800 object->parent = NULL;
4801 object->blockType = WINED3DSBT_ALL;
4803 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
4805 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4806 This->updateStateBlock = object;
4807 This->isRecordingState = TRUE;
4809 TRACE("(%p) recording stateblock %p\n",This , object);
4813 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4814 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4816 if (!This->isRecordingState) {
4817 FIXME("(%p) not recording! returning error\n", This);
4818 *ppStateBlock = NULL;
4819 return D3DERR_INVALIDCALL;
4822 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4823 This->isRecordingState = FALSE;
4824 This->updateStateBlock = This->stateBlock;
4825 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4826 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4827 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4832 * Scene related functions
4834 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4835 /* At the moment we have no need for any functionality at the beginning
4837 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4838 TRACE("(%p) : stub\n", This);
4842 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4843 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4844 TRACE("(%p)\n", This);
4846 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4848 checkGLcall("glFlush");
4850 TRACE("End Scene\n");
4851 if(This->renderTarget != NULL) {
4853 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4854 IUnknown *targetContainer = NULL;
4855 if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
4856 || D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
4857 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
4858 /** always dirtify for now. we must find a better way to see that surface have been modified
4859 (Modifications should will only occur via draw-primitive, but we do need better locking
4860 switching to render-to-texture should remove the overhead though.
4862 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4863 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
4864 IWineD3DSurface_PreLoad(This->renderTarget);
4865 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4866 IUnknown_Release(targetContainer);
4869 This->sceneEnded = TRUE;
4874 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4875 CONST RECT* pSourceRect, CONST RECT* pDestRect,
4876 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4877 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4878 IWineD3DSwapChain *swapChain = NULL;
4880 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4882 TRACE("(%p) Presenting the frame\n", This);
4884 for(i = 0 ; i < swapchains ; i ++) {
4886 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4887 TRACE("presentinng chain %d, %p\n", i, swapChain);
4888 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4889 IWineD3DSwapChain_Release(swapChain);
4895 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4896 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4897 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4899 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4900 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4901 when the depth-buffer format does not contain stencil buffer information, this method fails. */
4902 GLbitfield glMask = 0;
4903 GLboolean old_ztest;
4904 GLfloat old_z_clear_value;
4905 GLint old_stencil_clear_value;
4906 GLfloat old_color_clear_value[4];
4908 CONST D3DRECT* curRect;
4910 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4911 Count, pRects, Flags, Z, Stencil);
4915 glEnable(GL_SCISSOR_TEST);
4916 checkGLcall("glEnable GL_SCISSOR_TEST");
4918 if (Count > 0 && pRects) {
4924 /* Only set the values up once, as they are not changing */
4925 if (Flags & D3DCLEAR_STENCIL) {
4926 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4927 glClearStencil(Stencil);
4928 checkGLcall("glClearStencil");
4929 glMask = glMask | GL_STENCIL_BUFFER_BIT;
4930 glStencilMask(0xFFFFFFFF);
4933 if (Flags & D3DCLEAR_ZBUFFER) {
4934 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4935 glDepthMask(GL_TRUE);
4936 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4938 checkGLcall("glClearDepth");
4939 glMask = glMask | GL_DEPTH_BUFFER_BIT;
4942 if (Flags & D3DCLEAR_TARGET) {
4943 TRACE("Clearing screen with glClear to color %lx\n", Color);
4944 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4945 glClearColor(D3DCOLOR_R(Color),
4949 checkGLcall("glClearColor");
4951 /* Clear ALL colors! */
4952 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4953 glMask = glMask | GL_COLOR_BUFFER_BIT;
4956 /* Now process each rect in turn */
4957 for (i = 0; i < Count || i == 0; i++) {
4960 /* Note gl uses lower left, width/height */
4961 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4962 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4963 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4964 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4965 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4966 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4967 checkGLcall("glScissor");
4969 glScissor(This->stateBlock->viewport.X,
4970 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
4971 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4972 This->stateBlock->viewport.Width,
4973 This->stateBlock->viewport.Height);
4974 checkGLcall("glScissor");
4977 /* Clear the selected rectangle (or full screen) */
4979 checkGLcall("glClear");
4981 /* Step to the next rectangle */
4982 if (curRect) curRect = curRect + sizeof(D3DRECT);
4985 /* Restore the old values (why..?) */
4986 if (Flags & D3DCLEAR_STENCIL) {
4987 glClearStencil(old_stencil_clear_value);
4988 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4990 if (Flags & D3DCLEAR_ZBUFFER) {
4991 glDepthMask(old_ztest);
4992 glClearDepth(old_z_clear_value);
4994 if (Flags & D3DCLEAR_TARGET) {
4995 glClearColor(old_color_clear_value[0],
4996 old_color_clear_value[1],
4997 old_color_clear_value[2],
4998 old_color_clear_value[3]);
4999 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
5000 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
5001 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
5002 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
5005 glDisable(GL_SCISSOR_TEST);
5006 checkGLcall("glDisable");
5015 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
5016 UINT PrimitiveCount) {
5018 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5019 This->stateBlock->streamIsUP = FALSE;
5021 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
5022 debug_d3dprimitivetype(PrimitiveType),
5023 StartVertex, PrimitiveCount);
5024 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
5025 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
5031 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
5032 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
5033 D3DPRIMITIVETYPE PrimitiveType,
5034 INT baseVIndex, UINT minIndex,
5035 UINT NumVertices, UINT startIndex, UINT primCount) {
5037 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5039 IWineD3DIndexBuffer *pIB;
5040 WINED3DINDEXBUFFER_DESC IdxBufDsc;
5042 pIB = This->stateBlock->pIndexData;
5043 This->stateBlock->streamIsUP = FALSE;
5045 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
5046 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5047 minIndex, NumVertices, startIndex, baseVIndex, primCount);
5049 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
5050 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
5056 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
5057 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
5062 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
5063 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
5064 UINT VertexStreamZeroStride) {
5065 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5067 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
5068 debug_d3dprimitivetype(PrimitiveType),
5069 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
5071 /* release the stream source */
5072 if (This->stateBlock->streamSource[0] != NULL) {
5073 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5076 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5077 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5078 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5079 This->stateBlock->streamIsUP = TRUE;
5081 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
5082 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
5083 /* stream zero settings set to null at end, as per the msdn
5084 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
5086 This->stateBlock->streamStride[0] = 0;
5087 This->stateBlock->streamSource[0] = NULL;
5089 /*stream zero settings set to null at end, as per the msdn */
5093 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
5094 UINT MinVertexIndex, UINT NumVertices,
5095 UINT PrimitiveCount, CONST void* pIndexData,
5096 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
5097 UINT VertexStreamZeroStride) {
5099 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5101 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
5102 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5103 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
5104 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
5106 if (IndexDataFormat == WINED3DFMT_INDEX16) {
5112 /* release the stream and index data */
5113 if (This->stateBlock->streamSource[0] != NULL) {
5114 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5116 if (This->stateBlock->pIndexData) {
5117 IWineD3DIndexBuffer_Release(This->stateBlock->pIndexData);
5120 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5121 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5122 This->stateBlock->streamIsUP = TRUE;
5123 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5125 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
5126 /* stream zero settings set to null at end as per the msdn
5127 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
5130 /* stream zero settings set to null at end as per the msdn */
5131 This->stateBlock->streamSource[0] = NULL;
5132 This->stateBlock->streamStride[0] = 0;
5137 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
5138 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
5139 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5140 HRESULT hr = D3D_OK;
5141 WINED3DRESOURCETYPE sourceType;
5142 WINED3DRESOURCETYPE destinationType;
5145 /* TODO: think about moving the code into IWineD3DBaseTexture */
5147 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
5149 /* verify that the source and destination textures aren't NULL */
5150 if (NULL == pSourceTexture || NULL == pDestinationTexture) {
5151 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning D3DERR_INVALIDCALL\n",
5152 This, pSourceTexture, pDestinationTexture);
5153 hr = D3DERR_INVALIDCALL;
5156 if (pSourceTexture == pDestinationTexture) {
5157 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning D3DERR_INVALIDCALL\n",
5158 This, pSourceTexture, pDestinationTexture);
5159 hr = D3DERR_INVALIDCALL;
5161 /* Verify that the source and destination textures are the same type */
5162 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
5163 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
5165 if (sourceType != destinationType) {
5166 WARN("(%p) Sorce and destination types must match, returning D3DERR_INVALIDCALL\n",
5168 hr = D3DERR_INVALIDCALL;
5171 /* check that both textures have the identical numbers of levels */
5172 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
5173 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning D3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
5174 hr = D3DERR_INVALIDCALL;
5179 /* Make sure that the destination texture is loaded */
5180 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
5182 /* Update every surface level of the texture */
5183 levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
5185 switch (sourceType) {
5186 case WINED3DRTYPE_TEXTURE:
5188 IWineD3DSurface *srcSurface;
5189 IWineD3DSurface *destSurface;
5191 for (i = 0 ; i < levels ; ++i) {
5192 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture, i, &srcSurface);
5193 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
5194 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5195 IWineD3DSurface_Release(srcSurface);
5196 IWineD3DSurface_Release(destSurface);
5198 WARN("(%p) : Call to update surface failed\n", This);
5204 case WINED3DRTYPE_CUBETEXTURE:
5206 IWineD3DSurface *srcSurface;
5207 IWineD3DSurface *destSurface;
5208 D3DCUBEMAP_FACES faceType;
5210 for (i = 0 ; i < levels ; ++i) {
5211 /* Update each cube face */
5212 for (faceType = D3DCUBEMAP_FACE_POSITIVE_X; faceType <= D3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
5213 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture, faceType, i, &srcSurface);
5215 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5217 TRACE("Got srcSurface %p\n", srcSurface);
5219 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
5221 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5223 TRACE("Got desrSurface %p\n", destSurface);
5225 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5226 IWineD3DSurface_Release(srcSurface);
5227 IWineD3DSurface_Release(destSurface);
5229 WARN("(%p) : Call to update surface failed\n", This);
5236 #if 0 /* TODO: Add support for volume textures */
5237 case WINED3DRTYPE_VOLUMETEXTURE:
5239 IWineD3DVolume srcVolume = NULL;
5240 IWineD3DSurface destVolume = NULL;
5242 for (i = 0 ; i < levels ; ++i) {
5243 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture, i, &srcVolume);
5244 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
5245 hr = IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
5246 IWineD3DVolume_Release(srcSurface);
5247 IWineD3DVolume_Release(destSurface);
5249 WARN("(%p) : Call to update volume failed\n", This);
5257 FIXME("(%p) : Unsupported source and destination type\n", This);
5258 hr = D3DERR_INVALIDCALL;
5265 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
5266 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
5267 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
5268 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5270 TRACE("(%p) : stub\n", This);
5273 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
5274 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5275 /** TODO: remove remove casts to IWineD3DSurfaceImpl *
5276 * NOTE It may be best to move the code into surface to occomplish this
5277 ****************************************/
5279 WINED3DSURFACE_DESC surfaceDesc;
5280 unsigned int surfaceWidth, surfaceHeight;
5281 glDescriptor *targetGlDescription = NULL;
5282 glDescriptor *surfaceGlDescription = NULL;
5283 IWineD3DSwapChainImpl *container = NULL;
5285 IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
5286 IWineD3DSurface_GetGlDesc(pSurface, &surfaceGlDescription);
5287 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5289 surfaceDesc.Width = &surfaceWidth;
5290 surfaceDesc.Height = &surfaceHeight;
5291 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5292 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
5294 /* Ok, I may need to setup some kind of active swapchain reference on the device */
5295 IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
5297 /* TODO: opengl Context switching for swapchains etc... */
5298 if (NULL != container || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
5299 if (NULL != container && (pRenderTarget == container->backBuffer)) {
5300 glReadBuffer(GL_BACK);
5301 vcheckGLcall("glReadBuffer(GL_BACK)");
5302 } else if ((NULL != container && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
5303 glReadBuffer(GL_FRONT);
5304 vcheckGLcall("glReadBuffer(GL_FRONT)");
5305 } else if (pRenderTarget == This->depthStencilBuffer) {
5306 FIXME("Reading of depthstencil not yet supported\n");
5309 glReadPixels(surfaceGlDescription->target,
5310 surfaceGlDescription->level,
5313 surfaceGlDescription->glFormat,
5314 surfaceGlDescription->glType,
5315 (void *)IWineD3DSurface_GetData(pSurface));
5316 vcheckGLcall("glReadPixels(...)");
5317 if(NULL != container ){
5318 IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
5321 IWineD3DBaseTexture *container;
5322 GLenum textureDimensions = GL_TEXTURE_2D;
5324 if (D3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
5325 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
5326 IWineD3DBaseTexture_Release(container);
5328 /* TODO: 2D -> Cube surface coppies etc.. */
5329 if (surfaceGlDescription->target != textureDimensions) {
5330 FIXME("(%p) : Texture dimension mismatch\n", This);
5332 glEnable(textureDimensions);
5333 vcheckGLcall("glEnable(GL_TEXTURE_...)");
5334 /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
5335 glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
5336 vcheckGLcall("glBindTexture");
5337 glGetTexImage(surfaceGlDescription->target,
5338 surfaceGlDescription->level,
5339 surfaceGlDescription->glFormat,
5340 surfaceGlDescription->glType,
5341 (void *)IWineD3DSurface_GetData(pSurface));
5342 glDisable(textureDimensions);
5343 vcheckGLcall("glDisable(GL_TEXTURE_...)");
5350 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
5351 IWineD3DSwapChain *swapChain;
5353 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5355 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
5356 IWineD3DSwapChain_Release(swapChain);
5361 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5362 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5363 /* return a sensible default */
5365 /* TODO: If the window is minimized then validate device should return something other than d3d_ok */
5366 FIXME("(%p) : stub\n", This);
5370 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5371 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5373 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5374 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5375 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5376 return D3DERR_INVALIDCALL;
5378 for (j = 0; j < 256; ++j) {
5379 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
5380 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5381 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
5382 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5384 TRACE("(%p) : returning\n", This);
5388 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5389 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5391 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5392 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5393 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5394 return D3DERR_INVALIDCALL;
5396 for (j = 0; j < 256; ++j) {
5397 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
5398 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5399 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
5400 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5402 TRACE("(%p) : returning\n", This);
5406 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5407 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5408 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5409 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5410 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5411 return D3DERR_INVALIDCALL;
5413 /*TODO: stateblocks */
5414 This->currentPalette = PaletteNumber;
5415 TRACE("(%p) : returning\n", This);
5419 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
5420 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5421 if (PaletteNumber == NULL) {
5422 WARN("(%p) : returning Invalid Call\n", This);
5423 return D3DERR_INVALIDCALL;
5425 /*TODO: stateblocks */
5426 *PaletteNumber = This->currentPalette;
5427 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
5431 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
5432 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5433 static BOOL showFixmes = TRUE;
5435 FIXME("(%p) : stub\n", This);
5439 This->softwareVertexProcessing = bSoftware;
5444 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
5445 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5446 static BOOL showFixmes = TRUE;
5448 FIXME("(%p) : stub\n", This);
5451 return This->softwareVertexProcessing;
5455 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
5456 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5457 IWineD3DSwapChain *swapChain;
5460 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
5462 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5464 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
5465 IWineD3DSwapChain_Release(swapChain);
5467 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
5473 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
5474 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5475 static BOOL showfixmes = TRUE;
5476 if(nSegments != 0.0f) {
5478 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
5485 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
5486 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5487 static BOOL showfixmes = TRUE;
5489 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
5495 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
5496 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5497 /** TODO: remove casts to IWineD3DSurfaceImpl
5498 * NOTE: move code to surface to accomplish this
5499 ****************************************/
5500 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
5501 int srcWidth, srcHeight;
5502 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
5503 WINED3DFORMAT destFormat, srcFormat;
5505 int destLeft, destTop;
5506 D3DPOOL srcPool, destPool;
5508 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
5509 glDescriptor *glDescription = NULL;
5510 GLenum textureDimensions = GL_TEXTURE_2D;
5511 IWineD3DBaseTexture *baseTexture;
5513 WINED3DSURFACE_DESC winedesc;
5515 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
5516 memset(&winedesc, 0, sizeof(winedesc));
5517 winedesc.Width = &srcSurfaceWidth;
5518 winedesc.Height = &srcSurfaceHeight;
5519 winedesc.Pool = &srcPool;
5520 winedesc.Format = &srcFormat;
5522 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5524 winedesc.Width = &destSurfaceWidth;
5525 winedesc.Height = &destSurfaceHeight;
5526 winedesc.Pool = &destPool;
5527 winedesc.Format = &destFormat;
5528 winedesc.Size = &destSize;
5530 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5532 if(srcPool != D3DPOOL_SYSTEMMEM || destPool != D3DPOOL_DEFAULT){
5533 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning D3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
5534 return D3DERR_INVALIDCALL;
5537 if (destFormat == WINED3DFMT_UNKNOWN) {
5538 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5539 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5541 /* Get the update surface description */
5542 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5545 /* Make sure the surface is loaded and up to date */
5546 IWineD3DSurface_PreLoad(pDestinationSurface);
5548 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
5552 /* this needs to be done in lines if the sourceRect != the sourceWidth */
5553 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
5554 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
5555 destLeft = pDestPoint ? pDestPoint->x : 0;
5556 destTop = pDestPoint ? pDestPoint->y : 0;
5559 /* This function doesn't support compressed textures
5560 the pitch is just bytesPerPixel * width */
5561 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
5562 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
5563 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
5564 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
5566 /* TODO DXT formats */
5568 if(pSourceRect != NULL && pSourceRect->top != 0){
5569 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
5571 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
5573 ,glDescription->level
5578 ,glDescription->glFormat
5579 ,glDescription->glType
5580 ,IWineD3DSurface_GetData(pSourceSurface)
5584 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
5586 /* need to lock the surface to get the data */
5587 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5590 /* TODO: Cube and volume support */
5592 /* not a whole row so we have to do it a line at a time */
5595 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
5596 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5598 for(j = destTop ; j < (srcHeight + destTop) ; j++){
5600 glTexSubImage2D(glDescription->target
5601 ,glDescription->level
5606 ,glDescription->glFormat
5607 ,glDescription->glType
5608 ,data /* could be quicker using */
5613 } else { /* Full width, so just write out the whole texture */
5615 if (WINED3DFMT_DXT1 == destFormat ||
5616 WINED3DFMT_DXT2 == destFormat ||
5617 WINED3DFMT_DXT3 == destFormat ||
5618 WINED3DFMT_DXT4 == destFormat ||
5619 WINED3DFMT_DXT5 == destFormat) {
5620 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
5621 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
5622 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
5623 FIXME("Updating part of a compressed texture is not supported at the moment\n");
5624 } if (destFormat != srcFormat) {
5625 FIXME("Updating mixed format compressed texture is not curretly support\n");
5627 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
5628 glDescription->level,
5629 glDescription->glFormatInternal,
5634 IWineD3DSurface_GetData(pSourceSurface));
5637 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
5642 if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
5644 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
5645 to repack the data from pow2Width/Height to expected Width,Height, this makes the
5646 data returned by GetData non-power2 width/height with hardware non-power2
5647 pow2Width/height are set to surface width height, repacking isn't needed so it
5648 doesn't matter which function gets called. */
5649 glTexSubImage2D(glDescription->target
5650 ,glDescription->level
5655 ,glDescription->glFormat
5656 ,glDescription->glType
5657 ,IWineD3DSurface_GetData(pSourceSurface)
5661 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
5662 glTexSubImage2D(glDescription->target
5663 ,glDescription->level
5666 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
5667 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
5668 ,glDescription->glFormat
5669 ,glDescription->glType
5670 ,IWineD3DSurface_GetData(pSourceSurface)
5676 checkGLcall("glTexSubImage2D");
5678 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
5679 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
5680 * surface bigger than it needs to be hmm.. */
5681 if (D3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
5682 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
5683 IWineD3DBaseTexture_Release(baseTexture);
5686 glDisable(textureDimensions); /* This needs to be managed better.... */
5692 /* Used by DirectX 8 */
5693 HRESULT WINAPI IWineD3DDeviceImpl_CopyRects(IWineD3DDevice *iface,
5694 IWineD3DSurface* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
5695 IWineD3DSurface* pDestinationSurface, CONST POINT* pDestPointsArray) {
5697 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5698 HRESULT hr = D3D_OK;
5699 WINED3DFORMAT srcFormat, destFormat;
5700 UINT srcWidth, destWidth;
5701 UINT srcHeight, destHeight;
5703 WINED3DSURFACE_DESC winedesc;
5705 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
5706 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
5709 /* Check that the source texture is in D3DPOOL_SYSTEMMEM and the destination texture is in D3DPOOL_DEFAULT */
5710 memset(&winedesc, 0, sizeof(winedesc));
5712 winedesc.Format = &srcFormat;
5713 winedesc.Width = &srcWidth;
5714 winedesc.Height = &srcHeight;
5715 winedesc.Size = &srcSize;
5716 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5718 winedesc.Format = &destFormat;
5719 winedesc.Width = &destWidth;
5720 winedesc.Height = &destHeight;
5721 winedesc.Size = NULL;
5722 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5724 /* Check that the source and destination formats match */
5725 if (srcFormat != destFormat && WINED3DFMT_UNKNOWN != destFormat) {
5726 WARN("(%p) source %p format must match the dest %p format, returning D3DERR_INVALIDCALL\n", This, pSourceSurface, pDestinationSurface);
5727 return D3DERR_INVALIDCALL;
5728 } else if (WINED3DFMT_UNKNOWN == destFormat) {
5729 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5730 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5731 destFormat = srcFormat;
5734 /* Quick if complete copy ... */
5735 if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
5737 if (srcWidth == destWidth && srcHeight == destHeight) {
5738 D3DLOCKED_RECT lrSrc;
5739 D3DLOCKED_RECT lrDst;
5740 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, NULL, WINED3DLOCK_READONLY);
5741 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, NULL, 0L);
5742 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", srcWidth, srcHeight);
5744 memcpy(lrDst.pBits, lrSrc.pBits, srcSize);
5746 IWineD3DSurface_UnlockRect(pSourceSurface);
5747 IWineD3DSurface_UnlockRect(pDestinationSurface);
5748 TRACE("Unlocked src and dst\n");
5752 FIXME("Wanted to copy all surfaces but size not compatible, returning D3DERR_INVALIDCALL\n");
5753 hr = D3DERR_INVALIDCALL;
5758 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
5760 int bytesPerPixel = ((IWineD3DSurfaceImpl *) pSourceSurface)->bytesPerPixel;
5763 /* Copy rect by rect */
5764 for (i = 0; i < cRects; ++i) {
5765 CONST RECT* r = &pSourceRectsArray[i];
5766 CONST POINT* p = &pDestPointsArray[i];
5769 D3DLOCKED_RECT lrSrc;
5770 D3DLOCKED_RECT lrDst;
5773 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
5774 if (srcFormat == WINED3DFMT_DXT1) {
5775 copyperline = ((r->right - r->left) * bytesPerPixel) / 2; /* DXT1 is half byte per pixel */
5777 copyperline = ((r->right - r->left) * bytesPerPixel);
5780 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, r, WINED3DLOCK_READONLY);
5781 dest_rect.left = p->x;
5782 dest_rect.top = p->y;
5783 dest_rect.right = p->x + (r->right - r->left);
5784 dest_rect.bottom= p->y + (r->bottom - r->top);
5785 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, &dest_rect, 0L);
5786 TRACE("Locked src and dst\n");
5788 /* Find where to start */
5789 for (j = 0; j < (r->bottom - r->top - 1); ++j) {
5790 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
5792 IWineD3DSurface_UnlockRect(pSourceSurface);
5793 IWineD3DSurface_UnlockRect(pDestinationSurface);
5794 TRACE("Unlocked src and dst\n");
5797 FIXME("Wanted to copy partial surfaces not implemented, returning D3DERR_INVALIDCALL\n");
5798 hr = D3DERR_INVALIDCALL;
5805 /* Implementation details at http://developer.nvidia.com/attach/6494
5807 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
5808 hmm.. no longer supported use
5809 OpenGL evaluators or tessellate surfaces within your application.
5812 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
5813 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
5814 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5815 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
5816 FIXME("(%p) : Stub\n", This);
5821 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
5822 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
5823 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5824 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
5825 FIXME("(%p) : Stub\n", This);
5829 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5830 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5831 TRACE("(%p) Handle(%d)\n", This, Handle);
5832 FIXME("(%p) : Stub\n", This);
5836 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
5837 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
5838 fill a surface with a block of color! */
5839 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5840 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
5841 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
5842 IWineD3DSwapChainImpl *container = NULL;
5843 BOOL isRenderTarget = FALSE;
5844 unsigned int width, height;
5845 unsigned int top, left;
5848 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
5850 if (surface->resource.pool != D3DPOOL_DEFAULT) {
5851 FIXME("call to colorfill with non D3DPOOL_DEFAULT surface\n");
5852 return D3DERR_INVALIDCALL;
5855 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
5856 if (D3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
5857 if (WINED3DUSAGE_RENDERTARGET & surface->resource.usage) {
5858 /* TODO: make sure we set everything back to the way it was, and context management!
5859 glGetIntegerv(GL_READ_BUFFER, &prev_read);
5860 vcheckGLcall("glIntegerv");
5861 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
5862 vcheckGLcall("glIntegerv");
5864 TRACE("Color fill to render targets may cause some graphics issues\n");
5865 if (pSurface == container->frontBuffer) {
5866 glDrawBuffer(GL_FRONT);
5868 glDrawBuffer(GL_BACK);
5871 if (WINED3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
5872 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld\n", surface, surface->resource.usage);
5874 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
5876 if (container != NULL) {
5877 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5879 /* we can use GL_STENCIL_INDEX etc...*/
5882 if (container != NULL) {
5883 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5885 isRenderTarget = TRUE;
5887 /* TODO: drawing to GL_FRONT and GL_BACK */
5888 /* TODO: see if things can be speeded up by using the correct
5889 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
5890 if (pRect == NULL) {
5893 width = surface->currentDesc.Width;
5894 height = surface->currentDesc.Height;
5898 width = pRect->x2 - left;
5899 height = pRect->y2 - top;
5902 data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
5903 /* Create a 'line' of color color, in the correct format for the surface */
5904 for (u = 0 ; u < width ; u ++) {
5909 if (isRenderTarget == FALSE) {
5910 glDescriptor *glDesc;
5911 IWineD3DSurface_PreLoad(pSurface);
5913 /* draw a block of the coloured line on the sufrace */
5914 IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
5915 for (v = 0 ; v< height;v++) {
5916 glTexSubImage2D(glDesc->target
5917 ,glDesc->level /* level */
5927 checkGLcall("glTexSubImage2D");
5929 glDisable(glDesc->target);
5931 /** FIXME: Using GLClear may be faster **/
5932 glRasterPos2i(left, top);
5933 glPixelZoom((float)width ,(float)height);
5934 glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
5935 checkGLcall("glDrawPixels");
5937 HeapFree(GetProcessHeap(), 0, data);
5943 /* rendertarget and deptth stencil functions */
5944 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
5945 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5947 /* FIXME: Implelent RenderTargetIndex >0 */
5948 if(RenderTargetIndex > 0)
5949 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
5951 *ppRenderTarget = This->renderTarget;
5952 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
5953 /* Note inc ref on returned surface */
5954 if(*ppRenderTarget != NULL)
5955 IWineD3DSurface_AddRef(*ppRenderTarget);
5959 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5960 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5961 *ppZStencilSurface = This->depthStencilBuffer;
5962 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
5964 if(*ppZStencilSurface != NULL) {
5965 /* Note inc ref on returned surface */
5966 IWineD3DSurface_AddRef(*ppZStencilSurface);
5971 /* internal static helper functions */
5972 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5973 IWineD3DSurface *RenderSurface);
5975 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5976 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5977 HRESULT hr = D3D_OK;
5978 WINED3DVIEWPORT viewport;
5980 TRACE("(%p) Swapping rendertarget\n",This);
5981 if (RenderTargetIndex > 0) {
5982 FIXME("(%p) Render targets other than the first are not supported\n",This);
5983 RenderTargetIndex = 0;
5986 /* MSDN says that null disables the render target
5987 but a device must always be associated with a render target
5988 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5990 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5993 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5994 FIXME("Trying to set render target 0 to NULL\n");
5995 return D3DERR_INVALIDCALL;
5997 /* TODO: replace Impl* usage with interface usage */
5998 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
5999 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);
6000 return D3DERR_INVALIDCALL;
6002 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
6003 * builds, but I think wine counts as a 'debug' build for now.
6004 ******************************/
6005 /* If we are trying to set what we already have, don't bother */
6006 if (pRenderTarget == This->renderTarget) {
6007 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6009 /* Otherwise, set the render target up */
6011 if (FALSE == This->sceneEnded) {
6012 IWineD3DDevice_EndScene(iface);
6014 TRACE("clearing renderer\n");
6015 /* IWineD3DDeviceImpl_CleanRender(iface); */
6016 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6017 depending on the renter target implementation being used.
6018 A shared context implementation will share all buffers between all rendertargets (including swapchains),
6019 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6020 stencil buffer and incure an extra memory overhead */
6021 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
6024 if (SUCCEEDED(hr)) {
6025 /* Finally, reset the viewport as the MSDN states. */
6026 /* TODO: Replace impl usage */
6027 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
6028 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
6031 viewport.MaxZ = 1.0f;
6032 viewport.MinZ = 0.0f;
6033 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
6035 FIXME("Unknown error setting the render target\n");
6037 This->sceneEnded = FALSE;
6041 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
6042 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6043 HRESULT hr = D3D_OK;
6044 IWineD3DSurface *tmp;
6046 TRACE("(%p) Swapping z-buffer\n",This);
6048 if (pNewZStencil == This->stencilBufferTarget) {
6049 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6051 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6052 * depending on the renter target implementation being used.
6053 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
6054 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6055 * stencil buffer and incure an extra memory overhead
6056 ******************************************************/
6059 tmp = This->stencilBufferTarget;
6060 This->stencilBufferTarget = pNewZStencil;
6061 /* should we be calling the parent or the wined3d surface? */
6062 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
6063 if (NULL != tmp) IWineD3DSurface_Release(tmp);
6065 /** TODO: glEnable/glDisable on depth/stencil depending on
6066 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
6067 **********************************************************/
6074 #ifdef GL_VERSION_1_3
6075 /* Internal functions not in DirectX */
6076 /** TODO: move this off to the opengl context manager
6077 *(the swapchain doesn't need to know anything about offscreen rendering!)
6078 ****************************************************/
6080 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
6082 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6084 TRACE("(%p), %p\n", This, swapchain);
6086 if (swapchain->win != swapchain->drawable) {
6087 /* Set everything back the way it ws */
6088 swapchain->render_ctx = swapchain->glCtx;
6089 swapchain->drawable = swapchain->win;
6094 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
6095 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
6096 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6099 unsigned int height;
6100 WINED3DFORMAT format;
6101 WINED3DSURFACE_DESC surfaceDesc;
6102 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
6103 surfaceDesc.Width = &width;
6104 surfaceDesc.Height = &height;
6105 surfaceDesc.Format = &format;
6106 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
6108 /* I need a get width/height function (and should do something with the format) */
6109 for (i = 0; i < CONTEXT_CACHE; ++i) {
6110 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
6111 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
6112 the pSurface can be set to 0 allowing it to be reused from cache **/
6113 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
6114 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
6115 *context = &This->contextCache[i];
6118 if (This->contextCache[i].Width == 0) {
6119 This->contextCache[i].pSurface = pSurface;
6120 This->contextCache[i].Width = width;
6121 This->contextCache[i].Height = height;
6122 *context = &This->contextCache[i];
6126 if (i == CONTEXT_CACHE) {
6127 int minUsage = 0x7FFFFFFF; /* MAX_INT */
6128 glContext *dropContext = 0;
6129 for (i = 0; i < CONTEXT_CACHE; i++) {
6130 if (This->contextCache[i].usedcount < minUsage) {
6131 dropContext = &This->contextCache[i];
6132 minUsage = This->contextCache[i].usedcount;
6135 /* clean up the context (this doesn't work for ATI at the moment */
6137 glXDestroyContext(swapchain->display, dropContext->context);
6138 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
6141 dropContext->Width = 0;
6142 dropContext->pSurface = pSurface;
6143 *context = dropContext;
6145 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
6146 for (i = 0; i < CONTEXT_CACHE; i++) {
6147 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
6151 if (*context != NULL)
6154 return E_OUTOFMEMORY;
6158 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
6159 * the functionality needs splitting up so that we don't do more than we should do.
6160 * this only seems to impact performance a little.
6161 ******************************/
6162 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
6163 IWineD3DSurface *RenderSurface) {
6164 HRESULT ret = D3DERR_INVALIDCALL;
6167 * Currently only active for GLX >= 1.3
6168 * for others versions we'll have to use GLXPixmaps
6170 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
6171 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
6172 * so only check OpenGL version
6173 * ..........................
6174 * I don't believe that it is a problem with NVidia headers,
6175 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
6176 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
6178 * Your application will report GLX version 1.2 on glXQueryVersion.
6179 * However, it is safe to call the GLX 1.3 functions as described below.
6181 #if defined(GL_VERSION_1_3)
6183 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6184 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
6185 IWineD3DSurface *tmp;
6186 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
6187 GLXFBConfig* cfgs = NULL;
6191 IWineD3DSwapChain *currentSwapchain;
6192 IWineD3DSwapChainImpl *swapchain;
6193 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
6194 * but switch them off if the StencilSurface is set to NULL
6195 ** *********************************************************/
6196 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
6197 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
6200 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
6201 it StencilSurface != NULL && zBufferTarget == NULL switch it on
6204 #define PUSH1(att) attribs[nAttribs++] = (att);
6205 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
6207 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
6209 /** TODO: remove the reff to Impl (context manager should fix this!) **/
6210 IWineD3DSwapChainImpl *impSwapChain;
6211 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
6212 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
6213 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
6218 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
6219 PUSH2(GLX_X_RENDERABLE, TRUE);
6220 PUSH2(GLX_DOUBLEBUFFER, TRUE);
6221 TRACE("calling makeglcfg\n");
6222 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
6225 TRACE("calling chooseFGConfig\n");
6226 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
6229 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
6230 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
6231 why we failed and only show this message once! */
6232 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"); /**/
6234 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
6235 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
6236 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
6237 PUSH2(GLX_DOUBLEBUFFER, FALSE);
6238 TRACE("calling makeglcfg\n");
6239 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
6241 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
6248 for (i = 0; i < nCfgs; ++i) {
6249 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
6250 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
6251 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
6254 if (NULL != This->renderTarget) {
6256 vcheckGLcall("glFlush");
6257 /** This is only useful if the old render target was a swapchain,
6258 * we need to supercede this with a function that displays
6259 * the current buffer on the screen. This is easy to do in glx1.3 but
6260 * we need to do copy-write pixels in glx 1.2.
6261 ************************************************/
6262 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
6264 printf("Hit Enter to get next frame ...\n");
6270 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain) != D3D_OK) {
6271 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
6272 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
6276 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
6277 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
6278 **********************************************************************/
6279 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == D3D_OK) {
6280 /* We also need to make sure that the lights &co are also in the context of the swapchains */
6281 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
6282 TRACE("making swapchain active\n");
6283 if (RenderSurface != This->renderTarget) {
6284 if (RenderSurface == swapchain->backBuffer) {
6286 /* This could be flagged so that some operations work directly with the front buffer */
6287 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
6289 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
6291 TRACE("Error in setting current context: context %p drawable %ld !\n",
6292 impSwapChain->glCtx, impSwapChain->win);
6295 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
6297 checkGLcall("glXMakeContextCurrent");
6299 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
6301 else if (pbuffer_support == TRUE && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
6303 /** ********************************************************************
6304 * This is a quickly hacked out implementation of offscreen textures.
6305 * It will work in most cases but there may be problems if the client
6306 * modifies the texture directly, or expects the contents of the rendertarget
6309 * There are some real speed vs compatibility issues here:
6310 * we should really use a new context for every texture, but that eats ram.
6311 * we should also be restoring the texture to the pbuffer but that eats CPU
6312 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
6313 * but if this means reusing the display backbuffer then we need to make sure that
6314 * states are correctly preserved.
6315 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
6316 * and gain a good performance increase at the cost of compatibility.
6317 * I would suggest that, when this is the case, a user configurable flag be made
6318 * available, allowing the user to choose the best emulated experience for them.
6319 *********************************************************************/
6321 XVisualInfo *visinfo;
6322 glContext *newContext;
6324 /* Here were using a shared context model */
6325 if (D3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
6326 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6329 /* If the context doesn't exist then create a new one */
6330 /* TODO: This should really be part of findGlContext */
6331 if (NULL == newContext->context) {
6333 TRACE("making new buffer\n");
6335 PUSH2(GLX_PBUFFER_WIDTH, newContext->Width);
6336 PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
6339 newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
6341 /** ****************************************
6342 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
6344 * In future releases, we may provide the calls glXCreateNewContext,
6345 * glXQueryDrawable and glXMakeContextCurrent.
6346 * so until then we have to use glXGetVisualFromFBConfig &co..
6347 ********************************************/
6350 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
6352 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
6354 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
6358 if (NULL == newContext || NULL == newContext->context) {
6359 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6361 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
6362 if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
6363 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
6366 /* Clean up the old context */
6367 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
6368 /* Set the current context of the swapchain to the new context */
6369 impSwapChain->drawable = newContext->drawable;
6370 impSwapChain->render_ctx = newContext->context;
6374 #if 1 /* Apply the stateblock to the new context
6375 FIXME: This is a bit of a hack, each context should know it's own state,
6376 the directX current directX state should then be applied to the context */
6379 IWineD3DStateBlockImpl *oldUpdateStateBlock;
6380 oldUpdateStateBlock = This->updateStateBlock;
6381 oldRecording= This->isRecordingState;
6382 This->isRecordingState = FALSE;
6383 This->updateStateBlock = This->stateBlock;
6384 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
6386 This->isRecordingState = oldRecording;
6387 This->updateStateBlock = oldUpdateStateBlock;
6392 /* clean up the current rendertargets swapchain (if it belonged to one) */
6393 if (currentSwapchain != NULL) {
6394 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
6397 /* Were done with the opengl context management, setup the rendertargets */
6399 tmp = This->renderTarget;
6400 This->renderTarget = RenderSurface;
6401 IWineD3DSurface_AddRef(This->renderTarget);
6402 IWineD3DSurface_Release(tmp);
6408 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
6409 /* Check that the container is not a swapchain member */
6411 IWineD3DSwapChain *tmpSwapChain;
6412 if (D3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
6413 This->renderUpsideDown = TRUE;
6415 This->renderUpsideDown = FALSE;
6416 IWineD3DSwapChain_Release(tmpSwapChain);
6418 /* Force updating the cull mode */
6419 TRACE("setting render state\n");
6420 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
6421 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
6423 /* Force updating projection matrix */
6424 This->last_was_rhw = FALSE;
6425 This->proj_valid = FALSE;
6433 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
6434 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
6439 if ( NULL != impSwapChain) {
6440 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
6448 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
6449 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
6450 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6451 /* TODO: the use of Impl is deprecated. */
6452 /* some basic validation checks */
6453 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
6455 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
6457 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
6458 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
6459 return D3DERR_INVALIDCALL;
6461 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
6462 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
6463 return D3DERR_INVALIDCALL;
6465 /* TODO: make the cursor 'real' */
6467 This->xHotSpot = XHotSpot;
6468 This->yHotSpot = YHotSpot;
6473 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
6474 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6475 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
6477 This->xScreenSpace = XScreenSpace;
6478 This->yScreenSpace = YScreenSpace;
6484 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
6485 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6486 TRACE("(%p) : visible(%d)\n", This, bShow);
6488 This->bCursorVisible = bShow;
6493 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
6494 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6495 TRACE("(%p) : state (%lu)\n", This, This->state);
6496 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
6497 switch (This->state) {
6500 case D3DERR_DEVICELOST:
6502 ResourceList *resourceList = This->resources;
6503 while (NULL != resourceList) {
6504 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == D3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
6505 return D3DERR_DEVICENOTRESET;
6506 resourceList = resourceList->next;
6508 return D3DERR_DEVICELOST;
6510 case D3DERR_DRIVERINTERNALERROR:
6511 return D3DERR_DRIVERINTERNALERROR;
6515 return D3DERR_DRIVERINTERNALERROR;
6519 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
6520 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6521 /** FIXME: Resource tracking needs to be done,
6522 * The closes we can do to this is set the priorities of all managed textures low
6523 * and then reset them.
6524 ***********************************************************/
6525 FIXME("(%p) : stub\n", This);
6529 HRESULT WINAPI IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
6530 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6531 /** FIXME: Resource trascking needs to be done.
6532 * in effect this pulls all non only default
6533 * textures out of video memory and deletes all glTextures (glDeleteTextures)
6534 * and should clear down the context and set it up according to pPresentationParameters
6535 ***********************************************************/
6536 FIXME("(%p) : stub\n", This);
6540 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
6541 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6542 /** FIXME: always true at the moment **/
6543 if(bEnableDialogs == FALSE) {
6544 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
6550 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
6551 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6552 TRACE("(%p) : pParameters %p\n", This, pParameters);
6554 *pParameters = This->createParms;
6558 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
6559 IWineD3DSwapChain *swapchain;
6560 HRESULT hrc = D3D_OK;
6562 TRACE("Relaying to swapchain\n");
6564 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
6565 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (D3DGAMMARAMP *)pRamp);
6566 IWineD3DSwapChain_Release(swapchain);
6571 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
6572 IWineD3DSwapChain *swapchain;
6573 HRESULT hrc = D3D_OK;
6575 TRACE("Relaying to swapchain\n");
6577 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
6578 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
6579 IWineD3DSwapChain_Release(swapchain);
6585 /** ********************************************************
6586 * Notification functions
6587 ** ********************************************************/
6588 /** This function must be called in the release of a resource when ref == 0,
6589 * the contents of resource must still be correct,
6590 * any handels to other resource held by the caller must be closed
6591 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
6592 *****************************************************/
6593 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6594 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6595 ResourceList* resourceList;
6597 TRACE("(%p) : resource %p\n", This, resource);
6599 EnterCriticalSection(&resourceStoreCriticalSection);
6601 /* add a new texture to the frot of the linked list */
6602 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
6603 resourceList->resource = resource;
6605 /* Get the old head */
6606 resourceList->next = This->resources;
6608 This->resources = resourceList;
6609 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
6612 LeaveCriticalSection(&resourceStoreCriticalSection);
6617 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6618 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6619 ResourceList* resourceList = NULL;
6620 ResourceList* previousResourceList = NULL;
6622 TRACE("(%p) : resource %p\n", This, resource);
6625 EnterCriticalSection(&resourceStoreCriticalSection);
6627 resourceList = This->resources;
6629 while (resourceList != NULL) {
6630 if(resourceList->resource == resource) break;
6631 previousResourceList = resourceList;
6632 resourceList = resourceList->next;
6635 if (resourceList == NULL) {
6636 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
6638 LeaveCriticalSection(&resourceStoreCriticalSection);
6642 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
6644 /* make sure we don't leave a hole in the list */
6645 if (previousResourceList != NULL) {
6646 previousResourceList->next = resourceList->next;
6648 This->resources = resourceList->next;
6652 LeaveCriticalSection(&resourceStoreCriticalSection);
6658 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
6659 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6662 TRACE("(%p) : resource %p\n", This, resource);
6663 switch(IWineD3DResource_GetType(resource)){
6664 case WINED3DRTYPE_SURFACE:
6665 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
6667 case WINED3DRTYPE_TEXTURE:
6668 case WINED3DRTYPE_CUBETEXTURE:
6669 case WINED3DRTYPE_VOLUMETEXTURE:
6670 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
6671 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6672 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6673 This->stateBlock->textures[counter] = NULL;
6675 if (This->updateStateBlock != This->stateBlock ){
6676 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6677 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6678 This->updateStateBlock->textures[counter] = NULL;
6683 case WINED3DRTYPE_VOLUME:
6684 /* TODO: nothing really? */
6686 case WINED3DRTYPE_VERTEXBUFFER:
6687 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
6690 TRACE("Cleaning up stream pointers\n");
6692 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
6693 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
6694 FINDOUT: should changes.streamSource[StreamNumber] be set ?
6696 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6697 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
6698 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
6699 This->updateStateBlock->streamSource[streamNumber] = 0;
6700 /* Set changed flag? */
6703 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) */
6704 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
6705 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
6706 This->stateBlock->streamSource[streamNumber] = 0;
6709 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
6710 else { /* This shouldn't happen */
6711 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
6718 case WINED3DRTYPE_INDEXBUFFER:
6719 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
6720 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6721 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6722 This->updateStateBlock->pIndexData = NULL;
6725 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
6726 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6727 This->stateBlock->pIndexData = NULL;
6733 FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
6738 /* Remove the resoruce from the resourceStore */
6739 IWineD3DDeviceImpl_RemoveResource(iface, resource);
6741 TRACE("Resource released\n");
6746 /** This function is to be called by the swapchain when it is released and it's ref = 0
6747 *****************************************************/
6748 void WINAPI IWineD3DDeviceImpl_SwapChainReleased(IWineD3DDevice *iface, IWineD3DSwapChain *swapChain){
6749 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6750 SwapChainList **nextSwapchain;
6751 nextSwapchain = &This->swapchains;
6753 /* Check to see if the swapchian is being used as the render target */
6754 if (This->renderTarget != NULL) {
6755 IWineD3DSurface *swapchainBackBuffer;
6757 IWineD3DSwapChain_GetBackBuffer(swapChain, 0 ,( D3DBACKBUFFER_TYPE) 0, &swapchainBackBuffer);
6758 if (This->renderTarget == swapchainBackBuffer) {
6759 /* Don't know what to do, so warn and carry on as usual (which in this case leaves the renderterget in limbo) */
6760 FIXME("Atempting to release a swapchain that is currently beuing used as a render target, behaviour is undefined\n");
6764 /* Go through the swapchain list and try to find the swapchain being released */
6765 while(*nextSwapchain != NULL && (*nextSwapchain)->swapchain != swapChain) {
6766 nextSwapchain = &(*nextSwapchain)->next;
6769 /* Check to see if we found the swapchain */
6770 if (NULL != *nextSwapchain) {
6771 /* We found the swapchain so remove it from the list */
6772 TRACE("(%p) releasing swapchain(%p)\n", iface, swapChain);
6773 HeapFree(GetProcessHeap(), 0 , *nextSwapchain);
6774 *nextSwapchain = (*nextSwapchain)->next;
6776 /* We didn't find the swapchain on the list, this can only heppen because of a programming error in wined3d */
6777 FIXME("(%p) Attempting to release a swapchain (%p) that hasn't been stored\n", iface, swapChain);
6780 TRACE("swapchain (%p) released\n", swapChain);
6784 /**********************************************************
6785 * IWineD3DDevice VTbl follows
6786 **********************************************************/
6788 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
6790 /*** IUnknown methods ***/
6791 IWineD3DDeviceImpl_QueryInterface,
6792 IWineD3DDeviceImpl_AddRef,
6793 IWineD3DDeviceImpl_Release,
6794 /*** IWineD3DDevice methods ***/
6795 IWineD3DDeviceImpl_GetParent,
6796 /*** Creation methods**/
6797 IWineD3DDeviceImpl_CreateVertexBuffer,
6798 IWineD3DDeviceImpl_CreateIndexBuffer,
6799 IWineD3DDeviceImpl_CreateStateBlock,
6800 IWineD3DDeviceImpl_CreateSurface,
6801 IWineD3DDeviceImpl_CreateTexture,
6802 IWineD3DDeviceImpl_CreateVolumeTexture,
6803 IWineD3DDeviceImpl_CreateVolume,
6804 IWineD3DDeviceImpl_CreateCubeTexture,
6805 IWineD3DDeviceImpl_CreateQuery,
6806 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
6807 IWineD3DDeviceImpl_CreateVertexDeclaration,
6808 IWineD3DDeviceImpl_CreateVertexShader,
6809 IWineD3DDeviceImpl_CreatePixelShader,
6810 /*** Odd functions **/
6811 IWineD3DDeviceImpl_EvictManagedResources,
6812 IWineD3DDeviceImpl_GetAvailableTextureMem,
6813 IWineD3DDeviceImpl_GetBackBuffer,
6814 IWineD3DDeviceImpl_GetCreationParameters,
6815 IWineD3DDeviceImpl_GetDeviceCaps,
6816 IWineD3DDeviceImpl_GetDirect3D,
6817 IWineD3DDeviceImpl_GetDisplayMode,
6818 IWineD3DDeviceImpl_GetNumberOfSwapChains,
6819 IWineD3DDeviceImpl_GetRasterStatus,
6820 IWineD3DDeviceImpl_GetSwapChain,
6821 IWineD3DDeviceImpl_Reset,
6822 IWineD3DDeviceImpl_SetDialogBoxMode,
6823 IWineD3DDeviceImpl_SetCursorProperties,
6824 IWineD3DDeviceImpl_SetCursorPosition,
6825 IWineD3DDeviceImpl_ShowCursor,
6826 IWineD3DDeviceImpl_TestCooperativeLevel,
6827 /*** Getters and setters **/
6828 IWineD3DDeviceImpl_SetClipPlane,
6829 IWineD3DDeviceImpl_GetClipPlane,
6830 IWineD3DDeviceImpl_SetClipStatus,
6831 IWineD3DDeviceImpl_GetClipStatus,
6832 IWineD3DDeviceImpl_SetCurrentTexturePalette,
6833 IWineD3DDeviceImpl_GetCurrentTexturePalette,
6834 IWineD3DDeviceImpl_SetDepthStencilSurface,
6835 IWineD3DDeviceImpl_GetDepthStencilSurface,
6836 IWineD3DDeviceImpl_SetFVF,
6837 IWineD3DDeviceImpl_GetFVF,
6838 IWineD3DDeviceImpl_SetGammaRamp,
6839 IWineD3DDeviceImpl_GetGammaRamp,
6840 IWineD3DDeviceImpl_SetIndices,
6841 IWineD3DDeviceImpl_GetIndices,
6842 IWineD3DDeviceImpl_SetLight,
6843 IWineD3DDeviceImpl_GetLight,
6844 IWineD3DDeviceImpl_SetLightEnable,
6845 IWineD3DDeviceImpl_GetLightEnable,
6846 IWineD3DDeviceImpl_SetMaterial,
6847 IWineD3DDeviceImpl_GetMaterial,
6848 IWineD3DDeviceImpl_SetNPatchMode,
6849 IWineD3DDeviceImpl_GetNPatchMode,
6850 IWineD3DDeviceImpl_SetPaletteEntries,
6851 IWineD3DDeviceImpl_GetPaletteEntries,
6852 IWineD3DDeviceImpl_SetPixelShader,
6853 IWineD3DDeviceImpl_GetPixelShader,
6854 IWineD3DDeviceImpl_SetPixelShaderConstant,
6855 IWineD3DDeviceImpl_GetPixelShaderConstant,
6856 IWineD3DDeviceImpl_SetPixelShaderConstantB,
6857 IWineD3DDeviceImpl_GetPixelShaderConstantB,
6858 IWineD3DDeviceImpl_SetPixelShaderConstantI,
6859 IWineD3DDeviceImpl_GetPixelShaderConstantI,
6860 IWineD3DDeviceImpl_SetPixelShaderConstantF,
6861 IWineD3DDeviceImpl_GetPixelShaderConstantF,
6862 IWineD3DDeviceImpl_SetPixelShaderConstantN,
6863 IWineD3DDeviceImpl_SetRenderState,
6864 IWineD3DDeviceImpl_GetRenderState,
6865 IWineD3DDeviceImpl_SetRenderTarget,
6866 IWineD3DDeviceImpl_GetRenderTarget,
6867 IWineD3DDeviceImpl_SetSamplerState,
6868 IWineD3DDeviceImpl_GetSamplerState,
6869 IWineD3DDeviceImpl_SetScissorRect,
6870 IWineD3DDeviceImpl_GetScissorRect,
6871 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
6872 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
6873 IWineD3DDeviceImpl_SetStreamSource,
6874 IWineD3DDeviceImpl_GetStreamSource,
6875 IWineD3DDeviceImpl_SetStreamSourceFreq,
6876 IWineD3DDeviceImpl_GetStreamSourceFreq,
6877 IWineD3DDeviceImpl_SetTexture,
6878 IWineD3DDeviceImpl_GetTexture,
6879 IWineD3DDeviceImpl_SetTextureStageState,
6880 IWineD3DDeviceImpl_GetTextureStageState,
6881 IWineD3DDeviceImpl_SetTransform,
6882 IWineD3DDeviceImpl_GetTransform,
6883 IWineD3DDeviceImpl_SetVertexDeclaration,
6884 IWineD3DDeviceImpl_GetVertexDeclaration,
6885 IWineD3DDeviceImpl_SetVertexShader,
6886 IWineD3DDeviceImpl_GetVertexShader,
6887 IWineD3DDeviceImpl_SetVertexShaderConstant,
6888 IWineD3DDeviceImpl_GetVertexShaderConstant,
6889 IWineD3DDeviceImpl_SetVertexShaderConstantB,
6890 IWineD3DDeviceImpl_GetVertexShaderConstantB,
6891 IWineD3DDeviceImpl_SetVertexShaderConstantI,
6892 IWineD3DDeviceImpl_GetVertexShaderConstantI,
6893 IWineD3DDeviceImpl_SetVertexShaderConstantF,
6894 IWineD3DDeviceImpl_GetVertexShaderConstantF,
6895 IWineD3DDeviceImpl_SetVertexShaderConstantN,
6896 IWineD3DDeviceImpl_SetViewport,
6897 IWineD3DDeviceImpl_GetViewport,
6898 IWineD3DDeviceImpl_MultiplyTransform,
6899 IWineD3DDeviceImpl_ValidateDevice,
6900 IWineD3DDeviceImpl_ProcessVertices,
6901 /*** State block ***/
6902 IWineD3DDeviceImpl_BeginStateBlock,
6903 IWineD3DDeviceImpl_EndStateBlock,
6904 /*** Scene management ***/
6905 IWineD3DDeviceImpl_BeginScene,
6906 IWineD3DDeviceImpl_EndScene,
6907 IWineD3DDeviceImpl_Present,
6908 IWineD3DDeviceImpl_Clear,
6910 IWineD3DDeviceImpl_DrawPrimitive,
6911 IWineD3DDeviceImpl_DrawIndexedPrimitive,
6912 IWineD3DDeviceImpl_DrawPrimitiveUP,
6913 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
6914 IWineD3DDeviceImpl_DrawRectPatch,
6915 IWineD3DDeviceImpl_DrawTriPatch,
6916 IWineD3DDeviceImpl_DeletePatch,
6917 IWineD3DDeviceImpl_ColorFill,
6918 IWineD3DDeviceImpl_UpdateTexture,
6919 IWineD3DDeviceImpl_UpdateSurface,
6920 IWineD3DDeviceImpl_CopyRects,
6921 IWineD3DDeviceImpl_StretchRect,
6922 IWineD3DDeviceImpl_GetRenderTargetData,
6923 IWineD3DDeviceImpl_GetFrontBufferData,
6924 /*** Internal use IWineD3DDevice methods ***/
6925 IWineD3DDeviceImpl_SetupTextureStates,
6926 /*** object tracking ***/
6927 IWineD3DDeviceImpl_SwapChainReleased,
6928 IWineD3DDeviceImpl_ResourceReleased
6932 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
6933 WINED3DRS_ALPHABLENDENABLE ,
6934 WINED3DRS_ALPHAFUNC ,
6935 WINED3DRS_ALPHAREF ,
6936 WINED3DRS_ALPHATESTENABLE ,
6938 WINED3DRS_COLORWRITEENABLE ,
6939 WINED3DRS_DESTBLEND ,
6940 WINED3DRS_DITHERENABLE ,
6941 WINED3DRS_FILLMODE ,
6942 WINED3DRS_FOGDENSITY ,
6944 WINED3DRS_FOGSTART ,
6945 WINED3DRS_LASTPIXEL ,
6946 WINED3DRS_SHADEMODE ,
6947 WINED3DRS_SRCBLEND ,
6948 WINED3DRS_STENCILENABLE ,
6949 WINED3DRS_STENCILFAIL ,
6950 WINED3DRS_STENCILFUNC ,
6951 WINED3DRS_STENCILMASK ,
6952 WINED3DRS_STENCILPASS ,
6953 WINED3DRS_STENCILREF ,
6954 WINED3DRS_STENCILWRITEMASK ,
6955 WINED3DRS_STENCILZFAIL ,
6956 WINED3DRS_TEXTUREFACTOR ,
6967 WINED3DRS_ZWRITEENABLE
6970 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
6971 WINED3DTSS_ADDRESSW ,
6972 WINED3DTSS_ALPHAARG0 ,
6973 WINED3DTSS_ALPHAARG1 ,
6974 WINED3DTSS_ALPHAARG2 ,
6975 WINED3DTSS_ALPHAOP ,
6976 WINED3DTSS_BUMPENVLOFFSET ,
6977 WINED3DTSS_BUMPENVLSCALE ,
6978 WINED3DTSS_BUMPENVMAT00 ,
6979 WINED3DTSS_BUMPENVMAT01 ,
6980 WINED3DTSS_BUMPENVMAT10 ,
6981 WINED3DTSS_BUMPENVMAT11 ,
6982 WINED3DTSS_COLORARG0 ,
6983 WINED3DTSS_COLORARG1 ,
6984 WINED3DTSS_COLORARG2 ,
6985 WINED3DTSS_COLOROP ,
6986 WINED3DTSS_RESULTARG ,
6987 WINED3DTSS_TEXCOORDINDEX ,
6988 WINED3DTSS_TEXTURETRANSFORMFLAGS
6991 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
6992 WINED3DSAMP_ADDRESSU ,
6993 WINED3DSAMP_ADDRESSV ,
6994 WINED3DSAMP_ADDRESSW ,
6995 WINED3DSAMP_BORDERCOLOR ,
6996 WINED3DSAMP_MAGFILTER ,
6997 WINED3DSAMP_MINFILTER ,
6998 WINED3DSAMP_MIPFILTER ,
6999 WINED3DSAMP_MIPMAPLODBIAS ,
7000 WINED3DSAMP_MAXMIPLEVEL ,
7001 WINED3DSAMP_MAXANISOTROPY ,
7002 WINED3DSAMP_SRGBTEXTURE ,
7003 WINED3DSAMP_ELEMENTINDEX
7006 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
7008 WINED3DRS_AMBIENTMATERIALSOURCE ,
7009 WINED3DRS_CLIPPING ,
7010 WINED3DRS_CLIPPLANEENABLE ,
7011 WINED3DRS_COLORVERTEX ,
7012 WINED3DRS_DIFFUSEMATERIALSOURCE ,
7013 WINED3DRS_EMISSIVEMATERIALSOURCE ,
7014 WINED3DRS_FOGDENSITY ,
7016 WINED3DRS_FOGSTART ,
7017 WINED3DRS_FOGTABLEMODE ,
7018 WINED3DRS_FOGVERTEXMODE ,
7019 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
7020 WINED3DRS_LIGHTING ,
7021 WINED3DRS_LOCALVIEWER ,
7022 WINED3DRS_MULTISAMPLEANTIALIAS ,
7023 WINED3DRS_MULTISAMPLEMASK ,
7024 WINED3DRS_NORMALIZENORMALS ,
7025 WINED3DRS_PATCHEDGESTYLE ,
7026 WINED3DRS_POINTSCALE_A ,
7027 WINED3DRS_POINTSCALE_B ,
7028 WINED3DRS_POINTSCALE_C ,
7029 WINED3DRS_POINTSCALEENABLE ,
7030 WINED3DRS_POINTSIZE ,
7031 WINED3DRS_POINTSIZE_MAX ,
7032 WINED3DRS_POINTSIZE_MIN ,
7033 WINED3DRS_POINTSPRITEENABLE ,
7034 WINED3DRS_RANGEFOGENABLE ,
7035 WINED3DRS_SPECULARMATERIALSOURCE ,
7036 WINED3DRS_TWEENFACTOR ,
7037 WINED3DRS_VERTEXBLEND
7040 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
7041 WINED3DTSS_TEXCOORDINDEX ,
7042 WINED3DTSS_TEXTURETRANSFORMFLAGS
7045 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
7046 WINED3DSAMP_DMAPOFFSET