wined3d: Cleanup shader constants code a little bit.
[wine/multimedia.git] / dlls / wined3d / device.c
blobb057a3648f69126394c2c7aa95176af7aa21f296
1 /*
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
24 #include "config.h"
25 #include "wined3d_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
28 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
30 /* x11drv GDI escapes */
31 #define X11DRV_ESCAPE 6789
32 enum x11drv_escape_codes
34 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
35 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
36 X11DRV_GET_FONT, /* get current X font for a DC */
39 /* retrieve the X display to use on a given DC */
40 inline static Display *get_display( HDC hdc )
42 Display *display;
43 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
45 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
46 sizeof(display), (LPSTR)&display )) display = NULL;
47 return display;
50 /* Memory tracking and object counting */
51 static unsigned int emulated_textureram = 64*1024*1024;
53 /* TODO: setup some flags in the regestry to enable, disable pbuffer support */
54 /* enable pbuffer support for offscreen textures */
55 BOOL pbuffer_support = FALSE;
56 /* allocate one pbuffer per surface */
57 BOOL pbuffer_per_surface = FALSE;
59 /* static function declarations */
60 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
62 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type);
64 /* helper macros */
65 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return D3DERR_OUTOFVIDEOMEMORY;}
67 #define D3DCREATEOBJECTINSTANCE(object, type) { \
68 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
69 D3DMEMCHECK(object, pp##type); \
70 object->lpVtbl = &IWineD3D##type##_Vtbl; \
71 object->wineD3DDevice = This; \
72 object->parent = parent; \
73 object->ref = 1; \
74 *pp##type = (IWineD3D##type *) object; \
77 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
78 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
79 D3DMEMCHECK(object, pp##type); \
80 object->lpVtbl = &IWineD3D##type##_Vtbl; \
81 object->resource.wineD3DDevice = This; \
82 object->resource.parent = parent; \
83 object->resource.resourceType = d3dtype; \
84 object->resource.ref = 1; \
85 object->resource.pool = Pool; \
86 object->resource.format = Format; \
87 object->resource.usage = Usage; \
88 object->resource.size = _size; \
89 /* Check that we have enough video ram left */ \
90 if (Pool == D3DPOOL_DEFAULT) { \
91 if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
92 WARN("Out of 'bogus' video memory\n"); \
93 HeapFree(GetProcessHeap(), 0, object); \
94 *pp##type = NULL; \
95 return D3DERR_OUTOFVIDEOMEMORY; \
96 } \
97 globalChangeGlRam(_size); \
98 } \
99 object->resource.allocatedMemory = (0 == _size ? NULL : Pool == D3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
100 if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != D3DPOOL_DEFAULT) { \
101 FIXME("Out of memory!\n"); \
102 HeapFree(GetProcessHeap(), 0, object); \
103 *pp##type = NULL; \
104 return D3DERR_OUTOFVIDEOMEMORY; \
106 *pp##type = (IWineD3D##type *) object; \
107 IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
108 TRACE("(%p) : Created resource %p\n", This, object); \
111 #define D3DINITIALIZEBASETEXTURE(_basetexture) { \
112 _basetexture.levels = Levels; \
113 _basetexture.filterType = (Usage & D3DUSAGE_AUTOGENMIPMAP) ? D3DTEXF_LINEAR : D3DTEXF_NONE; \
114 _basetexture.LOD = 0; \
115 _basetexture.dirty = TRUE; \
118 /**********************************************************
119 * Global variable / Constants follow
120 **********************************************************/
121 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
123 /**********************************************************
124 * Utility functions follow
125 **********************************************************/
126 /* Convert the D3DLIGHT properties into equivalent gl lights */
127 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
129 float quad_att;
130 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
131 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
133 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
134 glMatrixMode(GL_MODELVIEW);
135 glPushMatrix();
136 glLoadMatrixf((float *)&This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
138 /* Diffuse: */
139 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
140 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
141 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
142 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
143 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
144 checkGLcall("glLightfv");
146 /* Specular */
147 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
148 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
149 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
150 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
151 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
152 checkGLcall("glLightfv");
154 /* Ambient */
155 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
156 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
157 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
158 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
159 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
160 checkGLcall("glLightfv");
162 /* Attenuation - Are these right? guessing... */
163 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
164 checkGLcall("glLightf");
165 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
166 checkGLcall("glLightf");
168 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) != 0) {
169 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
170 } else {
171 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
174 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
175 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
176 checkGLcall("glLightf");
178 switch (lightInfo->OriginalParms.Type) {
179 case D3DLIGHT_POINT:
180 /* Position */
181 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
182 checkGLcall("glLightfv");
183 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
184 checkGLcall("glLightf");
185 /* FIXME: Range */
186 break;
188 case D3DLIGHT_SPOT:
189 /* Position */
190 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
191 checkGLcall("glLightfv");
192 /* Direction */
193 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
194 checkGLcall("glLightfv");
195 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
196 checkGLcall("glLightf");
197 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
198 checkGLcall("glLightf");
199 /* FIXME: Range */
200 break;
202 case D3DLIGHT_DIRECTIONAL:
203 /* Direction */
204 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
205 checkGLcall("glLightfv");
206 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
207 checkGLcall("glLightf");
208 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
209 checkGLcall("glLightf");
210 break;
212 default:
213 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
216 /* Restore the modelview matrix */
217 glPopMatrix();
220 /* Apply the current values to the specified texture stage */
221 void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Sampler, DWORD Flags) {
222 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
223 float col[4];
225 union {
226 float f;
227 DWORD d;
228 } tmpvalue;
230 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
231 clamping, MIPLOD, etc. This will work for up to 16 samplers.
234 if (Sampler >= GL_LIMITS(samplers)) {
235 FIXME("Trying to set the state of more samplers %ld than are supported %d by this openGL implementation\n", Sampler, GL_LIMITS(samplers));
236 return;
238 VTRACE(("Activating appropriate texture state %ld\n", Sampler));
239 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
240 ENTER_GL();
241 GLACTIVETEXTURE(Sampler);
242 LEAVE_GL();
243 /* Could we use bindTexture and then apply the states instead of GLACTIVETEXTURE */
244 } else if (Sampler > 0) {
245 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
246 return;
249 /* TODO: change this to a lookup table
250 LOOKUP_TEXTURE_STATES lists all texture states that should be applied.
251 LOOKUP_CONTEXT_SATES list all context applicable states that can be applied
252 etc.... it's a lot cleaner, quicker and possibly easier to maintain than running a switch and setting a skip flag...
253 especially when there are a number of groups of states. */
255 TRACE("-----------------------> Updating the texture at Sampler %ld to have new texture state information\n", Sampler);
257 /* 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 */
258 #define APPLY_STATE(_state) IWineD3DDeviceImpl_ApplyTextureUnitState(iface, Sampler, _state)
259 /* these are the only two supported states that need to be applied */
260 APPLY_STATE(WINED3DTSS_TEXCOORDINDEX);
261 APPLY_STATE(WINED3DTSS_TEXTURETRANSFORMFLAGS);
262 #if 0 /* not supported at the moment */
263 APPLY_STATE(WINED3DTSS_BUMPENVMAT00);
264 APPLY_STATE(WINED3DTSS_BUMPENVMAT01);
265 APPLY_STATE(WINED3DTSS_BUMPENVMAT10);
266 APPLY_STATE(WINED3DTSS_BUMPENVMAT11);
267 APPLY_STATE(WINED3DTSS_BUMPENVLSCALE);
268 APPLY_STATE(WINED3DTSS_BUMPENVLOFFSET);
269 APPLY_STATE(WINED3DTSS_RESULTARG);
270 APPLY_STATE(WINED3DTSS_CONSTANT);
271 #endif
272 /* a quick sanity check in case someone forgot to update this function */
273 if (WINED3D_HIGHEST_TEXTURE_STATE > WINED3DTSS_CONSTANT) {
274 FIXME("(%p) : There are more texture states than expected, update device.c to match\n", This);
276 #undef APPLY_STATE
278 /* apply any sampler states that always need applying */
279 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
280 tmpvalue.d = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPMAPLODBIAS];
281 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
282 GL_TEXTURE_LOD_BIAS_EXT,
283 tmpvalue.f);
284 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
287 /* Note the D3DRS value applies to all textures, but GL has one
288 * per texture, so apply it now ready to be used!
290 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
291 /* Set the default alpha blend color */
292 glBlendColor(col[0], col[1], col[2], col[3]);
293 checkGLcall("glBlendColor");
295 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
296 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
297 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
299 /* TODO: NV_POINT_SPRITE */
300 if (GL_SUPPORT(ARB_POINT_SPRITE)) {
301 if (This->stateBlock->renderState[WINED3DRS_POINTSPRITEENABLE] != FALSE) {
302 /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
303 glDisable(GL_POINT_SMOOTH);
305 /* Centre the texture on the vertex */
306 VTRACE("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
307 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
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);
311 checkGLcall("glTexEnvf(...)");
312 VTRACE("glEnable( GL_POINT_SPRITE_ARB )\n");
313 glEnable( GL_POINT_SPRITE_ARB );
314 checkGLcall("glEnable(...)");
315 } else {
316 VTRACE("glDisable( GL_POINT_SPRITE_ARB )\n");
317 glDisable( GL_POINT_SPRITE_ARB );
318 checkGLcall("glEnable(...)");
322 TRACE("-----------------------> Updated the texture at Sampler %ld to have new texture state information\n", Sampler);
325 /**********************************************************
326 * IUnknown parts follows
327 **********************************************************/
329 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
331 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
332 /* FIXME: This needs to extend an IWineD3DBaseObject */
334 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
335 if (IsEqualGUID(riid, &IID_IUnknown)
336 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
337 IUnknown_AddRef(iface);
338 *ppobj = This;
339 return D3D_OK;
342 return E_NOINTERFACE;
345 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
346 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
347 ULONG refCount = InterlockedIncrement(&This->ref);
349 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
350 return refCount;
353 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
354 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
355 ULONG refCount = InterlockedDecrement(&This->ref);
357 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
359 if (!refCount) {
360 /* TODO: Clean up all the surfaces and textures! */
361 /* FIXME: Create targets and state blocks in d3d8 */
362 if (((IWineD3DImpl *)This->wineD3D)->dxVersion > 8) { /*We don't create a state block in d3d8 yet*/
363 /* NOTE: You must release the parent if the object was created via a callback
364 ** ***************************/
365 /* 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... */
366 /* Release all of the swapchains, except the implicit swapchain */
367 IUnknown* stencilBufferParent;
368 IUnknown* swapChainParent;
370 /* NOTE: Don't release swapchain 0 here, it's 'special' */
371 SwapChainList *nextSwapchain = This->swapchains;
372 if (nextSwapchain != NULL) {
373 nextSwapchain = nextSwapchain->next;
374 } else {
375 WARN("Expected to find the implicit swapchain\n");
378 /* release all the other swapchains */
379 while (nextSwapchain != NULL) {
380 SwapChainList *prevSwapchain = nextSwapchain;
381 nextSwapchain = nextSwapchain->next;
382 IWineD3DSwapChain_Release(prevSwapchain->swapchain);
383 /* NOTE: no need to free the list element, it will be done by the release callback
384 HeapFree(GetProcessHeap(), 0, prevSwapchain); */
386 /* Release the buffers (with sanity checks)*/
387 if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
388 if(This->depthStencilBuffer != This->stencilBufferTarget)
389 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
391 This->stencilBufferTarget = NULL;
393 if(IWineD3DSurface_Release(This->renderTarget) >0){
394 /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
396 This->renderTarget = NULL;
398 IWineD3DSurface_GetParent(This->depthStencilBuffer, &stencilBufferParent);
399 IUnknown_Release(stencilBufferParent); /* once for the get parent */
400 if(IUnknown_Release(stencilBufferParent) >0){ /* the second time for when it was created */
401 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
403 This->depthStencilBuffer = NULL;
405 /* Release the update stateblock */
406 if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){
407 if(This->updateStateBlock != This->stateBlock)
408 FIXME("(%p) Something's still holding the Update stateblock\n",This);
410 This->updateStateBlock = NULL;
411 { /* because were not doing proper internal refcounts releasing the primary state block
412 causes recursion with the extra checks in ResourceReleased, to avoid this we have
413 to set this->stateBlock = NULL; first */
414 IWineD3DStateBlock *stateBlock = (IWineD3DStateBlock *)This->stateBlock;
415 This->stateBlock = NULL;
417 /* Release the stateblock */
418 if(IWineD3DStateBlock_Release(stateBlock) > 0){
419 FIXME("(%p) Something's still holding the Update stateblock\n",This);
423 if (This->swapchains != NULL) {
424 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
425 IWineD3DSwapChain_GetParent(This->swapchains->swapchain, &swapChainParent);
426 IUnknown_Release(swapChainParent); /* once for the get parent */
427 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
428 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
432 if (This->resources != NULL ) {
433 FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This);
435 #if 0 /* TODO: Dump a list of all the resources still bound */
436 dumpResources(This->resources);
437 #endif
438 /* TODO: set the resources to a lost state */
442 IWineD3D_Release(This->wineD3D);
443 This->wineD3D = NULL;
444 HeapFree(GetProcessHeap(), 0, This);
445 TRACE("Freed device %p\n", This);
446 This = NULL;
448 return refCount;
451 /**********************************************************
452 * IWineD3DDevice implementation follows
453 **********************************************************/
454 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
455 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
456 *pParent = This->parent;
457 IUnknown_AddRef(This->parent);
458 return D3D_OK;
461 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
462 DWORD FVF, D3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
463 IUnknown *parent) {
464 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
465 IWineD3DVertexBufferImpl *object;
466 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
467 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, D3DRTYPE_VERTEXBUFFER, Size)
469 /*TODO: use VBO's */
470 if (Pool == D3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
471 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
473 object->fvf = FVF;
475 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
476 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
478 return D3D_OK;
481 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
482 WINED3DFORMAT Format, D3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
483 HANDLE *sharedHandle, IUnknown *parent) {
484 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
485 IWineD3DIndexBufferImpl *object;
486 TRACE("(%p) Creating index buffer\n", This);
488 /* Allocate the storage for the device */
489 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,D3DRTYPE_INDEXBUFFER, Length)
491 /*TODO: use VBO's */
492 if (Pool == D3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
493 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
496 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
497 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
498 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
500 return D3D_OK;
503 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
505 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
506 IWineD3DStateBlockImpl *object;
507 int i, j;
509 D3DCREATEOBJECTINSTANCE(object, StateBlock)
510 object->blockType = Type;
512 /* Special case - Used during initialization to produce a placeholder stateblock
513 so other functions called can update a state block */
514 if (Type == WINED3DSBT_INIT) {
515 /* Don't bother increasing the reference count otherwise a device will never
516 be freed due to circular dependencies */
517 return D3D_OK;
520 /* Otherwise, might as well set the whole state block to the appropriate values */
521 if ( This->stateBlock != NULL) {
522 memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
523 } else {
524 memset(object->streamFreq, 1, sizeof(object->streamFreq));
527 /* Reset the ref and type after kludging it */
528 object->wineD3DDevice = This;
529 object->ref = 1;
530 object->blockType = Type;
532 TRACE("Updating changed flags appropriate for type %d\n", Type);
534 if (Type == WINED3DSBT_ALL) {
536 TRACE("ALL => Pretend everything has changed\n");
537 memset(&object->changed, TRUE, sizeof(This->stateBlock->changed));
538 } else if (Type == WINED3DSBT_PIXELSTATE) {
540 TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
541 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
543 object->changed.pixelShader = TRUE;
545 /* Pixel Shader Constants */
546 for (i = 0; i < MAX_PSHADER_CONSTANTS; ++i) {
547 object->changed.pixelShaderConstants[i] = TRUE;
549 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
550 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
552 for (j = 0; j < GL_LIMITS(textures); j++) {
553 for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
554 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
557 for (j = 0 ; j < 16; j++) {
558 for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
560 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
564 } else if (Type == WINED3DSBT_VERTEXSTATE) {
566 TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
567 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
569 object->changed.vertexShader = TRUE;
571 /* Vertex Shader Constants */
572 for (i = 0; i < MAX_VSHADER_CONSTANTS; ++i) {
573 object->changed.vertexShaderConstants[i] = TRUE;
575 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
576 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
578 for (j = 0; j < GL_LIMITS(textures); j++) {
579 for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
580 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
583 for (j = 0 ; j < 16; j++){
584 for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
585 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
589 /* Duplicate light chain */
591 PLIGHTINFOEL *src = NULL;
592 PLIGHTINFOEL *dst = NULL;
593 PLIGHTINFOEL *newEl = NULL;
594 src = This->stateBlock->lights;
595 object->lights = NULL;
598 while (src) {
599 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
600 if (newEl == NULL) return D3DERR_OUTOFVIDEOMEMORY;
601 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
602 newEl->prev = dst;
603 newEl->changed = TRUE;
604 newEl->enabledChanged = TRUE;
605 if (dst == NULL) {
606 object->lights = newEl;
607 } else {
608 dst->next = newEl;
610 dst = newEl;
611 src = src->next;
616 } else {
617 FIXME("Unrecognized state block type %d\n", Type);
620 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
621 return D3D_OK;
625 /* ************************************
626 MSDN:
627 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
629 Discard
630 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
632 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.
634 ******************************** */
636 HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height, WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **ppSurface,D3DRESOURCETYPE Type, DWORD Usage, D3DPOOL Pool, D3DMULTISAMPLE_TYPE MultiSample ,DWORD MultisampleQuality, HANDLE* pSharedHandle, IUnknown *parent) {
637 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
638 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
639 unsigned int pow2Width, pow2Height;
640 unsigned int Size = 1;
641 TRACE("(%p) Create surface\n",This);
643 /** FIXME: Check ranges on the inputs are valid
644 * MSDN
645 * MultisampleQuality
646 * [in] Quality level. The valid range is between zero and one less than the level
647 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
648 * Passing a larger value returns the error D3DERR_INVALIDCALL. The MultisampleQuality
649 * values of paired render targets, depth stencil surfaces, and the MultiSample type
650 * must all match.
651 *******************************/
655 * TODO: Discard MSDN
656 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
658 * If this flag is set, the contents of the depth stencil buffer will be
659 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
660 * with a different depth surface.
662 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
663 ***************************/
665 if(MultisampleQuality < 0) {
666 FIXME("Invalid multisample level %ld\n", MultisampleQuality);
667 return D3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
670 if(MultisampleQuality > 0) {
671 FIXME("MultisampleQuality set to %ld, substituting 0\n", MultisampleQuality);
672 MultisampleQuality=0;
675 /** FIXME: Check that the format is supported
676 * by the device.
677 *******************************/
679 /* Non-power2 support */
681 /* Find the nearest pow2 match */
682 pow2Width = pow2Height = 1;
683 while (pow2Width < Width) pow2Width <<= 1;
684 while (pow2Height < Height) pow2Height <<= 1;
686 if (pow2Width > Width || pow2Height > Height) {
687 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
688 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
689 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
690 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
691 This, Width, Height);
692 return D3DERR_NOTAVAILABLE;
696 /** Check against the maximum texture sizes supported by the video card **/
697 if (pow2Width > GL_LIMITS(texture_size) || pow2Height > GL_LIMITS(texture_size)) {
698 /* one of three options
699 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)
700 2: Set the texture to the maxium size (bad idea)
701 3: WARN and return D3DERR_NOTAVAILABLE;
703 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));
704 return D3DERR_NOTAVAILABLE;
709 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
710 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
711 * space!
712 *********************************/
713 if (WINED3DFMT_UNKNOWN == Format) {
714 Size = 0;
715 } else if (Format == WINED3DFMT_DXT1) {
716 /* DXT1 is half byte per pixel */
717 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4)) >> 1;
719 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
720 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
721 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4));
722 } else {
723 Size = (pow2Width * D3DFmtGetBpp(This, Format)) * pow2Height;
726 /** Create and initialise the surface resource **/
727 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,D3DRTYPE_SURFACE, Size)
728 object->container = (IUnknown*) This;
730 object->currentDesc.Width = Width;
731 object->currentDesc.Height = Height;
732 object->currentDesc.MultiSampleType = MultiSample;
733 object->currentDesc.MultiSampleQuality = MultisampleQuality;
735 /* Setup some glformat defaults */
736 if (WINED3DFMT_UNKNOWN != Format) {
737 object->glDescription.glFormat = D3DFmt2GLFmt(This, object->resource.format);
738 object->glDescription.glFormatInternal = D3DFmt2GLIntFmt(This, object->resource.format);
739 object->glDescription.glType = D3DFmt2GLType(This, object->resource.format);
740 } else {
741 object->glDescription.glFormat = 0;
742 object->glDescription.glFormatInternal = 0;
743 object->glDescription.glType = 0;
746 object->glDescription.textureName = 0;
747 object->glDescription.level = Level;
748 object->glDescription.target = GL_TEXTURE_2D;
750 /* Internal data */
751 object->pow2Width = pow2Width;
752 object->pow2Height = pow2Height;
753 object->nonpow2 = (pow2Width != Width || pow2Height != Height) ? TRUE : FALSE;
754 object->discard = Discard;
755 object->activeLock = FALSE;
757 if (WINED3DFMT_UNKNOWN != Format) {
758 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
759 object->pow2Size = (pow2Width * object->bytesPerPixel) * pow2Height;
760 } else {
761 object->bytesPerPixel = 0;
762 object->pow2Size = 0;
765 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
767 TRACE("Pool %d %d %d %d",Pool, D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM);
769 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
770 * this function is too deap to need to care about things like this.
771 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
772 * ****************************************/
773 switch(Pool) {
774 case D3DPOOL_SCRATCH:
775 if(Lockable == FALSE)
776 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
777 which are mutually exclusive, setting lockable to true\n");
778 Lockable = TRUE;
779 break;
780 case D3DPOOL_SYSTEMMEM:
781 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
782 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
783 case D3DPOOL_MANAGED:
784 if(Usage == D3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
785 Usage of DYNAMIC which are mutually exclusive, not doing \
786 anything just telling you.\n");
787 break;
788 case D3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
789 if(!(Usage & D3DUSAGE_DYNAMIC) && !(Usage & D3DUSAGE_RENDERTARGET)
790 && !(Usage && D3DUSAGE_DEPTHSTENCIL ) && Lockable == TRUE)
791 FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
792 break;
793 default:
794 FIXME("(%p) Unknown pool %d\n", This, Pool);
795 break;
798 if (Usage & D3DUSAGE_RENDERTARGET && Pool != D3DPOOL_DEFAULT) {
799 FIXME("Trying to create a render target that isn't in the default pool\n");
803 object->locked = FALSE;
804 object->lockable = (WINED3DFMT_D16_LOCKABLE == Format) ? TRUE : Lockable;
806 /* mark the texture as dirty so that it get's loaded first time around*/
807 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
808 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
809 This, Width, Height, Format, debug_d3dformat(Format),
810 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
811 return D3D_OK;
815 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
816 DWORD Usage, WINED3DFORMAT Format, D3DPOOL Pool,
817 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
818 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
820 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
821 IWineD3DTextureImpl *object;
822 unsigned int i;
823 UINT tmpW;
824 UINT tmpH;
825 HRESULT hr;
826 unsigned int pow2Width = Width;
827 unsigned int pow2Height = Height;
830 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) ....\n", This, Width, Height, Levels, Usage);
832 /* TODO: It should only be possible to create textures for formats
833 that are reported as supported */
834 if (WINED3DFMT_UNKNOWN >= Format) {
835 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
836 return D3DERR_INVALIDCALL;
839 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, D3DRTYPE_TEXTURE, 0);
840 D3DINITIALIZEBASETEXTURE(object->baseTexture);
841 object->width = Width;
842 object->height = Height;
844 /** Non-power2 support **/
845 /* Find the nearest pow2 match */
846 pow2Width = pow2Height = 1;
847 while (pow2Width < Width) pow2Width <<= 1;
848 while (pow2Height < Height) pow2Height <<= 1;
850 /** FIXME: add support for real non-power-two if it's provided by the video card **/
851 /* Precalculated scaling for 'faked' non power of two texture coords */
852 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
853 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
854 TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
856 /* Calculate levels for mip mapping */
857 if (Levels == 0) {
858 TRACE("calculating levels %d\n", object->baseTexture.levels);
859 object->baseTexture.levels++;
860 tmpW = Width;
861 tmpH = Height;
862 while (tmpW > 1 && tmpH > 1) {
863 tmpW = max(1, tmpW >> 1);
864 tmpH = max(1, tmpH >> 1);
865 object->baseTexture.levels++;
867 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
870 /* Generate all the surfaces */
871 tmpW = Width;
872 tmpH = Height;
873 for (i = 0; i < object->baseTexture.levels; i++)
875 /* use the callback to create the texture surface */
876 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
877 if (hr!= D3D_OK) {
878 int j;
879 FIXME("Failed to create surface %p\n", object);
880 /* clean up */
881 for (j = 0 ; j < i ; j++) {
882 IWineD3DSurface_Release(object->surfaces[j]);
884 /* heap free object */
885 HeapFree(GetProcessHeap(), 0, object);
887 *ppTexture = NULL;
888 return hr;
891 IWineD3DSurface_SetContainer(object->surfaces[i], (IUnknown *)object);
892 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
893 /* calculate the next mipmap level */
894 tmpW = max(1, tmpW >> 1);
895 tmpH = max(1, tmpH >> 1);
898 TRACE("(%p) : Created texture %p\n", This, object);
899 return D3D_OK;
902 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
903 UINT Width, UINT Height, UINT Depth,
904 UINT Levels, DWORD Usage,
905 WINED3DFORMAT Format, D3DPOOL Pool,
906 IWineD3DVolumeTexture **ppVolumeTexture,
907 HANDLE *pSharedHandle, IUnknown *parent,
908 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
910 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
911 IWineD3DVolumeTextureImpl *object;
912 unsigned int i;
913 UINT tmpW;
914 UINT tmpH;
915 UINT tmpD;
917 /* TODO: It should only be possible to create textures for formats
918 that are reported as supported */
919 if (WINED3DFMT_UNKNOWN >= Format) {
920 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
921 return D3DERR_INVALIDCALL;
924 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, D3DRTYPE_VOLUMETEXTURE, 0);
925 D3DINITIALIZEBASETEXTURE(object->baseTexture);
927 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
928 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
930 object->width = Width;
931 object->height = Height;
932 object->depth = Depth;
934 /* Calculate levels for mip mapping */
935 if (Levels == 0) {
936 object->baseTexture.levels++;
937 tmpW = Width;
938 tmpH = Height;
939 tmpD = Depth;
940 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
941 tmpW = max(1, tmpW >> 1);
942 tmpH = max(1, tmpH >> 1);
943 tmpD = max(1, tmpD >> 1);
944 object->baseTexture.levels++;
946 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
949 /* Generate all the surfaces */
950 tmpW = Width;
951 tmpH = Height;
952 tmpD = Depth;
954 for (i = 0; i < object->baseTexture.levels; i++)
956 /* Create the volume */
957 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
958 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
960 /* Set it's container to this object */
961 IWineD3DVolume_SetContainer(object->volumes[i], (IUnknown *)object);
963 /* calcualte the next mipmap level */
964 tmpW = max(1, tmpW >> 1);
965 tmpH = max(1, tmpH >> 1);
966 tmpD = max(1, tmpD >> 1);
969 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
970 TRACE("(%p) : Created volume texture %p\n", This, object);
971 return D3D_OK;
974 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
975 UINT Width, UINT Height, UINT Depth,
976 DWORD Usage,
977 WINED3DFORMAT Format, D3DPOOL Pool,
978 IWineD3DVolume** ppVolume,
979 HANDLE* pSharedHandle, IUnknown *parent) {
981 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
982 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
984 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, D3DRTYPE_VOLUME, ((Width * D3DFmtGetBpp(This, Format)) * Height * Depth))
986 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
987 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
989 object->currentDesc.Width = Width;
990 object->currentDesc.Height = Height;
991 object->currentDesc.Depth = Depth;
992 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
994 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
995 object->lockable = TRUE;
996 object->locked = FALSE;
997 memset(&object->lockedBox, 0, sizeof(D3DBOX));
998 object->dirty = TRUE;
1000 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
1003 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
1004 UINT Levels, DWORD Usage,
1005 WINED3DFORMAT Format, D3DPOOL Pool,
1006 IWineD3DCubeTexture **ppCubeTexture,
1007 HANDLE *pSharedHandle, IUnknown *parent,
1008 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1010 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1011 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1012 unsigned int i, j;
1013 UINT tmpW;
1014 HRESULT hr;
1015 unsigned int pow2EdgeLength = EdgeLength;
1017 /* TODO: It should only be possible to create textures for formats
1018 that are reported as supported */
1019 if (WINED3DFMT_UNKNOWN >= Format) {
1020 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
1021 return D3DERR_INVALIDCALL;
1024 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, D3DRTYPE_CUBETEXTURE, 0);
1025 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1027 TRACE("(%p) Create Cube Texture\n", This);
1029 /** Non-power2 support **/
1031 /* Find the nearest pow2 match */
1032 pow2EdgeLength = 1;
1033 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
1035 object->edgeLength = EdgeLength;
1036 /* TODO: support for native non-power 2 */
1037 /* Precalculated scaling for 'faked' non power of two texture coords */
1038 object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
1040 /* Calculate levels for mip mapping */
1041 if (Levels == 0) {
1042 object->baseTexture.levels++;
1043 tmpW = EdgeLength;
1044 while (tmpW > 1) {
1045 tmpW = max(1, tmpW >> 1);
1046 object->baseTexture.levels++;
1048 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1051 /* Generate all the surfaces */
1052 tmpW = EdgeLength;
1053 for (i = 0; i < object->baseTexture.levels; i++) {
1055 /* Create the 6 faces */
1056 for (j = 0; j < 6; j++) {
1058 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
1059 i /* Level */, &object->surfaces[j][i],pSharedHandle);
1061 if(hr!= D3D_OK) {
1062 /* clean up */
1063 int k;
1064 int l;
1065 for (l = 0; l < j; l++) {
1066 IWineD3DSurface_Release(object->surfaces[j][i]);
1068 for (k = 0; k < i; k++) {
1069 for (l = 0; l < 6; l++) {
1070 IWineD3DSurface_Release(object->surfaces[l][j]);
1074 FIXME("(%p) Failed to create surface\n",object);
1075 HeapFree(GetProcessHeap(),0,object);
1076 *ppCubeTexture = NULL;
1077 return hr;
1079 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IUnknown *)object);
1080 TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1082 tmpW = max(1, tmpW >> 1);
1085 TRACE("(%p) : Created Cube Texture %p\n", This, object);
1086 *ppCubeTexture = (IWineD3DCubeTexture *) object;
1087 return D3D_OK;
1090 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1091 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1092 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1094 if (NULL == ppQuery) {
1095 /* Just a check to see if we support this type of query */
1096 HRESULT hr = D3DERR_NOTAVAILABLE;
1097 /* Lie and say everything is good (we can return ok fake data from a stub) */
1098 switch(Type) {
1099 case WINED3DQUERYTYPE_VCACHE:
1100 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1101 case WINED3DQUERYTYPE_VERTEXSTATS:
1102 case WINED3DQUERYTYPE_EVENT:
1103 case WINED3DQUERYTYPE_TIMESTAMP:
1104 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1105 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1106 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1107 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1108 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1109 case WINED3DQUERYTYPE_PIXELTIMINGS:
1110 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1111 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1112 break;
1113 case WINED3DQUERYTYPE_OCCLUSION:
1114 TRACE("(%p) occlusion query\n", This);
1115 if (GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY))
1116 hr = D3D_OK;
1117 break;
1118 default:
1119 FIXME("(%p) Unhandled query type %d\n",This , Type);
1121 FIXME("(%p) : Stub request for query type %d returned %ld\n", This, Type, hr);
1122 return hr;
1125 D3DCREATEOBJECTINSTANCE(object, Query)
1126 object->type = Type;
1127 /* allocated the 'extended' data based on the type of query requested */
1128 switch(Type){
1129 case D3DQUERYTYPE_OCCLUSION:
1130 if(GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY)) {
1131 TRACE("(%p) Allocating data for an occlusion query\n", This);
1132 object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1133 break;
1135 case D3DQUERYTYPE_VCACHE:
1136 case D3DQUERYTYPE_RESOURCEMANAGER:
1137 case D3DQUERYTYPE_VERTEXSTATS:
1138 case D3DQUERYTYPE_EVENT:
1139 case D3DQUERYTYPE_TIMESTAMP:
1140 case D3DQUERYTYPE_TIMESTAMPDISJOINT:
1141 case D3DQUERYTYPE_TIMESTAMPFREQ:
1142 case D3DQUERYTYPE_PIPELINETIMINGS:
1143 case D3DQUERYTYPE_INTERFACETIMINGS:
1144 case D3DQUERYTYPE_VERTEXTIMINGS:
1145 case D3DQUERYTYPE_PIXELTIMINGS:
1146 case D3DQUERYTYPE_BANDWIDTHTIMINGS:
1147 case D3DQUERYTYPE_CACHEUTILIZATION:
1148 default:
1149 object->extendedData = 0;
1150 FIXME("(%p) Unhandled query type %d\n",This , Type);
1152 TRACE("(%p) : Created Query %p\n", This, object);
1153 return D3D_OK;
1156 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1157 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1158 IUnknown* parent,
1159 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1160 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1161 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1163 HDC hDc;
1164 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1165 int num;
1166 XVisualInfo template;
1167 GLXContext oldContext;
1168 Drawable oldDrawable;
1169 HRESULT hr = D3D_OK;
1171 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1173 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1174 * does a device hold a reference to a swap chain giving them a lifetime of the device
1175 * or does the swap chain notify the device of its destruction.
1176 *******************************/
1178 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1180 /* Initialize other useful values */
1181 object->presentParms.BackBufferCount = 1; /* TODO:? support for gl_aux buffers */
1183 /*********************
1184 * Lookup the window Handle and the relating X window handle
1185 ********************/
1187 /* Setup hwnd we are using, plus which display this equates to */
1188 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1189 if (!object->win_handle) {
1190 object->win_handle = This->createParms.hFocusWindow;
1193 object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window" );
1194 hDc = GetDC(object->win_handle);
1195 object->display = get_display(hDc);
1196 ReleaseDC(object->win_handle, hDc);
1197 TRACE("Using a display of %p %p\n", object->display, hDc);
1199 if (NULL == object->display || NULL == hDc) {
1200 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1201 return D3DERR_NOTAVAILABLE;
1204 if (object->win == 0) {
1205 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1206 return D3DERR_NOTAVAILABLE;
1209 * Create an opengl context for the display visual
1210 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1211 * use different properties after that point in time. FIXME: How to handle when requested format
1212 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1213 * it chooses is identical to the one already being used!
1214 **********************************/
1216 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1217 ENTER_GL();
1219 /* Create a new context for this swapchain */
1220 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1221 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1222 (or the best possible if none is requested) */
1223 TRACE("Found x visual ID : %ld\n", template.visualid);
1225 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1226 if (NULL == object->visInfo) {
1227 ERR("cannot really get XVisual\n");
1228 LEAVE_GL();
1229 return D3DERR_NOTAVAILABLE;
1230 } else {
1231 int n, value;
1232 /* Write out some debug info about the visual/s */
1233 TRACE("Using x visual ID : %ld\n", template.visualid);
1234 TRACE(" visual info: %p\n", object->visInfo);
1235 TRACE(" num items : %d\n", num);
1236 for (n = 0;n < num; n++) {
1237 TRACE("=====item=====: %d\n", n + 1);
1238 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1239 TRACE(" screen : %d\n", object->visInfo[n].screen);
1240 TRACE(" depth : %u\n", object->visInfo[n].depth);
1241 TRACE(" class : %d\n", object->visInfo[n].class);
1242 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1243 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1244 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1245 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1246 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1247 /* log some extra glx info */
1248 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1249 TRACE(" gl_aux_buffers : %d\n", value);
1250 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1251 TRACE(" gl_buffer_size : %d\n", value);
1252 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1253 TRACE(" gl_red_size : %d\n", value);
1254 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1255 TRACE(" gl_green_size : %d\n", value);
1256 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1257 TRACE(" gl_blue_size : %d\n", value);
1258 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1259 TRACE(" gl_alpha_size : %d\n", value);
1260 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1261 TRACE(" gl_depth_size : %d\n", value);
1262 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1263 TRACE(" gl_stencil_size : %d\n", value);
1265 /* Now choose a simila visual ID*/
1267 #ifdef USE_CONTEXT_MANAGER
1269 /** TODO: use a context mamager **/
1270 #endif
1273 IWineD3DSwapChain *implSwapChain;
1274 if (D3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1275 /* The first time around we create the context that is shared with all other swapchains and render targets */
1276 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1277 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1278 } else {
1280 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1281 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1282 /* and create a new context with the implicit swapchains context as the shared context */
1283 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1284 IWineD3DSwapChain_Release(implSwapChain);
1288 /* Cleanup */
1289 XFree(object->visInfo);
1290 object->visInfo = NULL;
1292 if (NULL == object->glCtx) {
1293 ERR("cannot create glxContext\n");
1294 LEAVE_GL();
1295 return D3DERR_NOTAVAILABLE;
1298 LEAVE_GL();
1299 if (object->glCtx == NULL) {
1300 ERR("Error in context creation !\n");
1301 return D3DERR_INVALIDCALL;
1302 } else {
1303 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1304 object->win_handle, object->glCtx, object->win, object->visInfo);
1307 /*********************
1308 * Windowed / Fullscreen
1309 *******************/
1312 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1313 * so we should really check to see if there is a fullscreen swapchain already
1314 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1315 **************************************/
1317 if (!*(pPresentationParameters->Windowed)) {
1319 DEVMODEW devmode;
1320 HDC hdc;
1321 int bpp = 0;
1323 /* Get info on the current display setup */
1324 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1325 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1326 DeleteDC(hdc);
1328 /* Change the display settings */
1329 memset(&devmode, 0, sizeof(DEVMODEW));
1330 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1331 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1332 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1333 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1334 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1335 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1337 /* Make popup window */
1338 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1339 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1340 *(pPresentationParameters->BackBufferWidth),
1341 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1347 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1348 * then the corresponding dimension of the client area of the hDeviceWindow
1349 * (or the focus window, if hDeviceWindow is NULL) is taken.
1350 **********************/
1352 if (*(pPresentationParameters->Windowed) &&
1353 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1354 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1356 RECT Rect;
1357 GetClientRect(object->win_handle, &Rect);
1359 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1360 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1361 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1363 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1364 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1365 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1369 /*********************
1370 * finish off parameter initialization
1371 *******************/
1373 /* Put the correct figures in the presentation parameters */
1374 TRACE("Coppying accross presentaion paraneters\n");
1375 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1376 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1377 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1378 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1379 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1380 object->presentParms.MultiSampleQuality = NULL == pPresentationParameters->MultiSampleQuality ? 0 : *(pPresentationParameters->MultiSampleQuality);
1381 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1382 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1383 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1384 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1385 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1386 object->presentParms.Flags = *(pPresentationParameters->Flags);
1387 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1388 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1391 /*********************
1392 * Create the back, front and stencil buffers
1393 *******************/
1394 TRACE("calling rendertarget CB\n");
1395 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1396 object->presentParms.BackBufferWidth,
1397 object->presentParms.BackBufferHeight,
1398 object->presentParms.BackBufferFormat,
1399 object->presentParms.MultiSampleType,
1400 object->presentParms.MultiSampleQuality,
1401 TRUE /* Lockable */,
1402 &object->frontBuffer,
1403 NULL /* pShared (always null)*/);
1404 if (object->frontBuffer != NULL)
1405 IWineD3DSurface_SetContainer(object->frontBuffer, (IUnknown *)object);
1406 TRACE("calling rendertarget CB\n");
1407 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1408 object->presentParms.BackBufferWidth,
1409 object->presentParms.BackBufferHeight,
1410 object->presentParms.BackBufferFormat,
1411 object->presentParms.MultiSampleType,
1412 object->presentParms.MultiSampleQuality,
1413 TRUE /* Lockable */,
1414 &object->backBuffer,
1415 NULL /* pShared (always null)*/);
1416 if (object->backBuffer != NULL)
1417 IWineD3DSurface_SetContainer(object->backBuffer, (IUnknown *)object);
1419 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1420 if (pPresentationParameters->EnableAutoDepthStencil) {
1421 TRACE("Creating depth stencil buffer\n");
1422 if (This->depthStencilBuffer == NULL ) {
1423 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1424 object->presentParms.BackBufferWidth,
1425 object->presentParms.BackBufferHeight,
1426 object->presentParms.AutoDepthStencilFormat,
1427 object->presentParms.MultiSampleType,
1428 object->presentParms.MultiSampleQuality,
1429 FALSE /* FIXME: Discard */,
1430 &This->depthStencilBuffer,
1431 NULL /* pShared (always null)*/ );
1432 if (This->depthStencilBuffer != NULL)
1433 IWineD3DSurface_SetContainer(This->depthStencilBuffer, (IUnknown *)iface);
1436 /** TODO: A check on width, height and multisample types
1437 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1438 ****************************/
1439 object->wantsDepthStencilBuffer = TRUE;
1440 } else {
1441 object->wantsDepthStencilBuffer = FALSE;
1444 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1447 /*********************
1448 * init the default renderTarget management
1449 *******************/
1450 object->drawable = object->win;
1451 object->render_ctx = object->glCtx;
1453 if (hr == D3D_OK) {
1454 /*********************
1455 * Setup some defaults and clear down the buffers
1456 *******************/
1457 ENTER_GL();
1458 /** save current context and drawable **/
1459 oldContext = glXGetCurrentContext();
1460 oldDrawable = glXGetCurrentDrawable();
1462 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1463 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1464 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1466 checkGLcall("glXMakeCurrent");
1468 TRACE("Setting up the screen\n");
1469 /* Clear the screen */
1470 glClearColor(1.0, 0.0, 0.0, 0.0);
1471 checkGLcall("glClearColor");
1472 glClearIndex(0);
1473 glClearDepth(1);
1474 glClearStencil(0xffff);
1476 checkGLcall("glClear");
1478 glColor3f(1.0, 1.0, 1.0);
1479 checkGLcall("glColor3f");
1481 glEnable(GL_LIGHTING);
1482 checkGLcall("glEnable");
1484 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1485 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1487 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1488 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1490 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1491 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1493 /* switch back to the original context (if there was one)*/
1494 if (This->swapchains != NULL) {
1495 /** TODO: restore the context and drawable **/
1496 glXMakeCurrent(object->display, oldDrawable, oldContext);
1499 LEAVE_GL();
1501 { /* Finally add the swapchain to the end of the devices' swapchain list */
1502 SwapChainList **nextSwapchain;
1503 nextSwapchain = &This->swapchains;
1504 while (*nextSwapchain != NULL) {
1505 nextSwapchain = &((*nextSwapchain)->next);
1507 (*nextSwapchain) = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->swapchains));
1508 (*nextSwapchain)->swapchain = (IWineD3DSwapChain *)object;
1510 TRACE("Set swapchain to %p\n", object);
1511 } else { /* something went wrong so clean up */
1512 IUnknown* bufferParent;
1513 if (object->frontBuffer) {
1515 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1516 IUnknown_Release(bufferParent); /* once for the get parent */
1517 if (IUnknown_Release(bufferParent) > 0) {
1518 FIXME("(%p) Something's still holding the front buffer\n",This);
1521 if (object->backBuffer) {
1522 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1523 IUnknown_Release(bufferParent); /* once for the get parent */
1524 if (IUnknown_Release(bufferParent) > 0) {
1525 FIXME("(%p) Something's still holding the back buffer\n",This);
1528 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1529 /* Clean up the context */
1530 /* check that we are the current context first (we shouldn't be though!) */
1531 if (object->glCtx != 0) {
1532 if(glXGetCurrentContext() == object->glCtx) {
1533 glXMakeCurrent(object->display, None, NULL);
1535 glXDestroyContext(object->display, object->glCtx);
1537 HeapFree(GetProcessHeap(), 0, object);
1541 return hr;
1544 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1545 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1546 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1547 unsigned int numberOfSwapChains = 0;
1548 SwapChainList *swapchain;
1550 swapchain = This->swapchains;
1551 /* itterate through the list to get a count */
1552 while (swapchain != NULL) {
1553 swapchain = swapchain->next;
1554 numberOfSwapChains++;
1557 TRACE("(%p) returning %d\n", This, numberOfSwapChains);
1558 return numberOfSwapChains;
1561 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1562 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1563 SwapChainList *swapchain;
1564 int i = iSwapChain;
1565 HRESULT hr = D3DERR_INVALIDCALL;
1566 swapchain = This->swapchains;
1567 TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1570 TRACE("(%p) Finding swapchain %d\n", This, iSwapChain);
1571 while (i > 0 && swapchain != NULL) {
1572 swapchain = swapchain->next;
1573 --i;
1576 if (i > 0) {
1577 FIXME("(%p) Unable to find swapchain %d\n", This, iSwapChain);
1578 *pSwapChain = NULL;
1579 } else if (swapchain != NULL) {
1580 /** TODO: move off to a linkesList implementation **/
1581 *pSwapChain = swapchain->swapchain;
1582 IWineD3DSwapChain_AddRef(*pSwapChain);
1583 hr = D3D_OK;
1586 TRACE("(%p) returning %p\n", This, *pSwapChain);
1587 return hr;
1590 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
1591 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1593 FIXME("(%p) : Stub\n",This);
1594 return D3D_OK;
1598 /*****
1599 * Vertex Declaration
1600 *****/
1601 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1602 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1603 IWineD3DVertexDeclarationImpl *object = NULL;
1604 HRESULT hr = D3D_OK;
1605 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1606 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1607 object->allFVF = 0;
1609 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1611 return hr;
1614 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1615 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pDeclaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1616 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1617 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1618 HRESULT hr = D3D_OK;
1619 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1621 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1622 hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1624 if (D3D_OK != hr) {
1625 FIXME("(%p) : Failed to set the function, returning D3DERR_INVALIDCALL\n", iface);
1626 IWineD3DVertexShader_Release(*ppVertexShader);
1627 return D3DERR_INVALIDCALL;
1630 #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. */
1631 if(Usage == WINED3DUSAGE_SOFTWAREVERTEXPROCESSING) {
1632 /* Foo */
1633 } else {
1634 /* Bar */
1637 #endif
1640 /* If a vertex declaration has been passed, save it to the vertex shader, this affects d3d8 only. */
1641 if (pDeclaration != NULL) {
1642 IWineD3DVertexDeclaration *vertexDeclaration;
1643 hr = IWineD3DDevice_CreateVertexDeclaration(iface, pDeclaration, &vertexDeclaration ,NULL);
1644 if (D3D_OK == hr) {
1645 TRACE("(%p) : Setting vertex declaration to %p\n", This, vertexDeclaration);
1646 object->vertexDeclaration = vertexDeclaration;
1647 } else {
1648 FIXME("(%p) : Failed to set the declaration, returning D3DERR_INVALIDCALL\n", iface);
1649 IWineD3DVertexShader_Release(*ppVertexShader);
1650 return D3DERR_INVALIDCALL;
1654 return D3D_OK;
1657 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
1658 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1659 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1660 HRESULT hr = D3D_OK;
1662 D3DCREATEOBJECTINSTANCE(object, PixelShader)
1663 hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
1664 if (D3D_OK == hr) {
1665 TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
1666 } else {
1667 WARN("(%p) : Failed to create pixel shader\n", This);
1670 return hr;
1673 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
1674 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1675 *ppD3D= This->wineD3D;
1676 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1677 IWineD3D_AddRef(*ppD3D);
1678 return D3D_OK;
1681 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1682 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1683 * Into the video ram as possible and seeing how many fit
1684 * you can also get the correct initial value from via X and ATI's driver
1685 *******************/
1686 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1687 static BOOL showfixmes = TRUE;
1688 if (showfixmes) {
1689 FIXME("(%p) : stub, emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1690 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1691 showfixmes = FALSE;
1693 TRACE("(%p) : emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1694 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1695 /* videomemory is simulated videomemory + AGP memory left */
1696 return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1701 /*****
1702 * Get / Set FVF
1703 *****/
1704 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1705 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1706 HRESULT hr = D3D_OK;
1708 /* Update the current state block */
1709 This->updateStateBlock->fvf = fvf;
1710 This->updateStateBlock->changed.fvf = TRUE;
1711 This->updateStateBlock->set.fvf = TRUE;
1713 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1715 if (0 != fvf) {
1716 /* clear down the vertex declaration
1717 NOTE: Axis and Allies doesn't work properly otherwise
1718 (may be a stateblock problem though!)
1720 hr = IWineD3DDevice_SetVertexDeclaration(iface, NULL);
1723 return hr;
1727 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1728 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1729 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1730 *pfvf = This->stateBlock->fvf;
1731 return D3D_OK;
1734 /*****
1735 * Get / Set Stream Source
1736 *****/
1737 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1738 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1739 IWineD3DVertexBuffer *oldSrc;
1741 /**TODO: instance and index data, see
1742 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1744 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
1745 **************/
1747 /* D3d9 only, but shouldn't hurt d3d8 */
1748 UINT streamFlags;
1750 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1751 if (streamFlags) {
1752 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1753 FIXME("stream index data not supported\n");
1755 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1756 FIXME("stream instance data not supported\n");
1760 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1762 if (StreamNumber >= MAX_STREAMS) {
1763 WARN("Stream out of range %d\n", StreamNumber);
1764 return D3DERR_INVALIDCALL;
1767 oldSrc = This->stateBlock->streamSource[StreamNumber];
1768 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1770 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
1771 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
1772 This->updateStateBlock->streamStride[StreamNumber] = Stride;
1773 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
1774 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
1775 This->updateStateBlock->streamFlags[StreamNumber] = streamFlags;
1777 /* Handle recording of state blocks */
1778 if (This->isRecordingState) {
1779 TRACE("Recording... not performing anything\n");
1780 return D3D_OK;
1783 /* Not recording... */
1784 /* Need to do a getParent and pass the reffs up */
1785 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
1786 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
1787 so for now, just count internally */
1788 if (pStreamData != NULL) {
1789 IWineD3DVertexBuffer_AddRef(pStreamData);
1791 if (oldSrc != NULL) {
1792 IWineD3DVertexBuffer_Release(oldSrc);
1795 return D3D_OK;
1798 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
1799 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1800 UINT streamFlags;
1802 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
1803 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
1806 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1807 if (streamFlags) {
1808 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1809 FIXME("stream index data not supported\n");
1811 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1812 FIXME("stream instance data not supported\n");
1816 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1818 if (StreamNumber >= MAX_STREAMS) {
1819 WARN("Stream out of range %d\n", StreamNumber);
1820 return D3DERR_INVALIDCALL;
1822 *pStream = This->stateBlock->streamSource[StreamNumber];
1823 *pStride = This->stateBlock->streamStride[StreamNumber];
1824 *pOffset = This->stateBlock->streamOffset[StreamNumber];
1826 if (*pStream == NULL) {
1827 FIXME("Attempting to get an empty stream %d, returning D3DERR_INVALIDCALL\n", StreamNumber);
1828 return D3DERR_INVALIDCALL;
1831 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
1832 return D3D_OK;
1835 /*Should be quite easy, just an extension of vertexdata
1836 ref...
1837 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1839 The divider is a bit odd though
1841 VertexOffset = StartVertex / Divider * StreamStride +
1842 VertexIndex / Divider * StreamStride + StreamOffset
1845 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
1846 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1848 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
1849 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (D3DSTREAMSOURCE_INSTANCEDATA | D3DSTREAMSOURCE_INDEXEDDATA );
1851 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
1852 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
1853 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
1855 if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
1856 FIXME("Stream indexing not fully supported\n");
1859 return D3D_OK;
1862 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
1863 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1865 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
1866 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
1868 TRACE("(%p) : returning %d\n", This, *Divider);
1870 return D3D_OK;
1873 /*****
1874 * Get / Set & Multiply Transform
1875 *****/
1876 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1877 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1879 /* Most of this routine, comments included copied from ddraw tree initially: */
1880 TRACE("(%p) : Transform State=%d\n", This, d3dts);
1882 /* Handle recording of state blocks */
1883 if (This->isRecordingState) {
1884 TRACE("Recording... not performing anything\n");
1885 This->updateStateBlock->changed.transform[d3dts] = TRUE;
1886 This->updateStateBlock->set.transform[d3dts] = TRUE;
1887 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1888 return D3D_OK;
1892 * If the new matrix is the same as the current one,
1893 * we cut off any further processing. this seems to be a reasonable
1894 * optimization because as was noticed, some apps (warcraft3 for example)
1895 * tend towards setting the same matrix repeatedly for some reason.
1897 * From here on we assume that the new matrix is different, wherever it matters.
1899 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1900 TRACE("The app is setting the same matrix over again\n");
1901 return D3D_OK;
1902 } else {
1903 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1907 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1908 where ViewMat = Camera space, WorldMat = world space.
1910 In OpenGL, camera and world space is combined into GL_MODELVIEW
1911 matrix. The Projection matrix stay projection matrix.
1914 /* Capture the times we can just ignore the change for now */
1915 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1916 This->modelview_valid = FALSE;
1917 return D3D_OK;
1919 } else if (d3dts == D3DTS_PROJECTION) {
1920 This->proj_valid = FALSE;
1921 return D3D_OK;
1923 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1924 /* Indexed Vertex Blending Matrices 256 -> 511 */
1925 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1926 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1927 return D3D_OK;
1930 /* Now we really are going to have to change a matrix */
1931 ENTER_GL();
1933 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1934 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
1935 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1936 unsigned int k;
1938 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1939 * NOTE: We have to reset the positions even if the light/plane is not currently
1940 * enabled, since the call to enable it will not reset the position.
1941 * NOTE2: Apparently texture transforms do NOT need reapplying
1944 PLIGHTINFOEL *lightChain = NULL;
1945 This->modelview_valid = FALSE;
1946 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
1948 glMatrixMode(GL_MODELVIEW);
1949 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1950 glPushMatrix();
1951 glLoadMatrixf((float *)lpmatrix);
1952 checkGLcall("glLoadMatrixf(...)");
1954 /* Reset lights */
1955 lightChain = This->stateBlock->lights;
1956 while (lightChain && lightChain->glIndex != -1) {
1957 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1958 checkGLcall("glLightfv posn");
1959 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1960 checkGLcall("glLightfv dirn");
1961 lightChain = lightChain->next;
1964 /* Reset Clipping Planes if clipping is enabled */
1965 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1966 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1967 checkGLcall("glClipPlane");
1969 glPopMatrix();
1971 } else { /* What was requested!?? */
1972 WARN("invalid matrix specified: %i\n", d3dts);
1975 /* Release lock, all done */
1976 LEAVE_GL();
1977 return D3D_OK;
1980 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1981 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1982 TRACE("(%p) : for Transform State %d\n", This, State);
1983 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1984 return D3D_OK;
1987 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1988 D3DMATRIX *mat = NULL;
1989 D3DMATRIX temp;
1991 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1992 * below means it will be recorded in a state block change, but it
1993 * works regardless where it is recorded.
1994 * If this is found to be wrong, change to StateBlock.
1996 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1997 TRACE("(%p) : For state %u\n", This, State);
1999 if (State < HIGHEST_TRANSFORMSTATE)
2001 mat = &This->updateStateBlock->transforms[State];
2002 } else {
2003 FIXME("Unhandled transform state!!\n");
2006 /* Copied from ddraw code: */
2007 temp.u.s._11 = (mat->u.s._11 * pMatrix->u.s._11) + (mat->u.s._21 * pMatrix->u.s._12) +
2008 (mat->u.s._31 * pMatrix->u.s._13) + (mat->u.s._41 * pMatrix->u.s._14);
2009 temp.u.s._21 = (mat->u.s._11 * pMatrix->u.s._21) + (mat->u.s._21 * pMatrix->u.s._22) +
2010 (mat->u.s._31 * pMatrix->u.s._23) + (mat->u.s._41 * pMatrix->u.s._24);
2011 temp.u.s._31 = (mat->u.s._11 * pMatrix->u.s._31) + (mat->u.s._21 * pMatrix->u.s._32) +
2012 (mat->u.s._31 * pMatrix->u.s._33) + (mat->u.s._41 * pMatrix->u.s._34);
2013 temp.u.s._41 = (mat->u.s._11 * pMatrix->u.s._41) + (mat->u.s._21 * pMatrix->u.s._42) +
2014 (mat->u.s._31 * pMatrix->u.s._43) + (mat->u.s._41 * pMatrix->u.s._44);
2016 temp.u.s._12 = (mat->u.s._12 * pMatrix->u.s._11) + (mat->u.s._22 * pMatrix->u.s._12) +
2017 (mat->u.s._32 * pMatrix->u.s._13) + (mat->u.s._42 * pMatrix->u.s._14);
2018 temp.u.s._22 = (mat->u.s._12 * pMatrix->u.s._21) + (mat->u.s._22 * pMatrix->u.s._22) +
2019 (mat->u.s._32 * pMatrix->u.s._23) + (mat->u.s._42 * pMatrix->u.s._24);
2020 temp.u.s._32 = (mat->u.s._12 * pMatrix->u.s._31) + (mat->u.s._22 * pMatrix->u.s._32) +
2021 (mat->u.s._32 * pMatrix->u.s._33) + (mat->u.s._42 * pMatrix->u.s._34);
2022 temp.u.s._42 = (mat->u.s._12 * pMatrix->u.s._41) + (mat->u.s._22 * pMatrix->u.s._42) +
2023 (mat->u.s._32 * pMatrix->u.s._43) + (mat->u.s._42 * pMatrix->u.s._44);
2025 temp.u.s._13 = (mat->u.s._13 * pMatrix->u.s._11) + (mat->u.s._23 * pMatrix->u.s._12) +
2026 (mat->u.s._33 * pMatrix->u.s._13) + (mat->u.s._43 * pMatrix->u.s._14);
2027 temp.u.s._23 = (mat->u.s._13 * pMatrix->u.s._21) + (mat->u.s._23 * pMatrix->u.s._22) +
2028 (mat->u.s._33 * pMatrix->u.s._23) + (mat->u.s._43 * pMatrix->u.s._24);
2029 temp.u.s._33 = (mat->u.s._13 * pMatrix->u.s._31) + (mat->u.s._23 * pMatrix->u.s._32) +
2030 (mat->u.s._33 * pMatrix->u.s._33) + (mat->u.s._43 * pMatrix->u.s._34);
2031 temp.u.s._43 = (mat->u.s._13 * pMatrix->u.s._41) + (mat->u.s._23 * pMatrix->u.s._42) +
2032 (mat->u.s._33 * pMatrix->u.s._43) + (mat->u.s._43 * pMatrix->u.s._44);
2034 temp.u.s._14 = (mat->u.s._14 * pMatrix->u.s._11) + (mat->u.s._24 * pMatrix->u.s._12) +
2035 (mat->u.s._34 * pMatrix->u.s._13) + (mat->u.s._44 * pMatrix->u.s._14);
2036 temp.u.s._24 = (mat->u.s._14 * pMatrix->u.s._21) + (mat->u.s._24 * pMatrix->u.s._22) +
2037 (mat->u.s._34 * pMatrix->u.s._23) + (mat->u.s._44 * pMatrix->u.s._24);
2038 temp.u.s._34 = (mat->u.s._14 * pMatrix->u.s._31) + (mat->u.s._24 * pMatrix->u.s._32) +
2039 (mat->u.s._34 * pMatrix->u.s._33) + (mat->u.s._44 * pMatrix->u.s._34);
2040 temp.u.s._44 = (mat->u.s._14 * pMatrix->u.s._41) + (mat->u.s._24 * pMatrix->u.s._42) +
2041 (mat->u.s._34 * pMatrix->u.s._43) + (mat->u.s._44 * pMatrix->u.s._44);
2043 /* Apply change via set transform - will reapply to eg. lights this way */
2044 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2047 /*****
2048 * Get / Set Light
2049 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
2050 *****/
2051 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2052 you can reference any indexes you want as long as that number max are enabled at any
2053 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2054 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2055 but when recording, just build a chain pretty much of commands to be replayed. */
2057 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2058 float rho;
2059 PLIGHTINFOEL *object, *temp;
2061 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2062 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2064 /* If recording state block, just add to end of lights chain */
2065 if (This->isRecordingState) {
2066 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2067 if (NULL == object) {
2068 return D3DERR_OUTOFVIDEOMEMORY;
2070 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2071 object->OriginalIndex = Index;
2072 object->glIndex = -1;
2073 object->changed = TRUE;
2075 /* Add to the END of the chain of lights changes to be replayed */
2076 if (This->updateStateBlock->lights == NULL) {
2077 This->updateStateBlock->lights = object;
2078 } else {
2079 temp = This->updateStateBlock->lights;
2080 while (temp->next != NULL) temp=temp->next;
2081 temp->next = object;
2083 TRACE("Recording... not performing anything more\n");
2084 return D3D_OK;
2087 /* Ok, not recording any longer so do real work */
2088 object = This->stateBlock->lights;
2089 while (object != NULL && object->OriginalIndex != Index) object = object->next;
2091 /* If we didn't find it in the list of lights, time to add it */
2092 if (object == NULL) {
2093 PLIGHTINFOEL *insertAt,*prevPos;
2095 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2096 if (NULL == object) {
2097 return D3DERR_OUTOFVIDEOMEMORY;
2099 object->OriginalIndex = Index;
2100 object->glIndex = -1;
2102 /* Add it to the front of list with the idea that lights will be changed as needed
2103 BUT after any lights currently assigned GL indexes */
2104 insertAt = This->stateBlock->lights;
2105 prevPos = NULL;
2106 while (insertAt != NULL && insertAt->glIndex != -1) {
2107 prevPos = insertAt;
2108 insertAt = insertAt->next;
2111 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2112 This->stateBlock->lights = object;
2113 } else if (insertAt == NULL) { /* End of list */
2114 prevPos->next = object;
2115 object->prev = prevPos;
2116 } else { /* Middle of chain */
2117 if (prevPos == NULL) {
2118 This->stateBlock->lights = object;
2119 } else {
2120 prevPos->next = object;
2122 object->prev = prevPos;
2123 object->next = insertAt;
2124 insertAt->prev = object;
2128 /* Initialize the object */
2129 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,
2130 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2131 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2132 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2133 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2134 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2135 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2137 /* Save away the information */
2138 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2140 switch (pLight->Type) {
2141 case D3DLIGHT_POINT:
2142 /* Position */
2143 object->lightPosn[0] = pLight->Position.x;
2144 object->lightPosn[1] = pLight->Position.y;
2145 object->lightPosn[2] = pLight->Position.z;
2146 object->lightPosn[3] = 1.0f;
2147 object->cutoff = 180.0f;
2148 /* FIXME: Range */
2149 break;
2151 case D3DLIGHT_DIRECTIONAL:
2152 /* Direction */
2153 object->lightPosn[0] = -pLight->Direction.x;
2154 object->lightPosn[1] = -pLight->Direction.y;
2155 object->lightPosn[2] = -pLight->Direction.z;
2156 object->lightPosn[3] = 0.0;
2157 object->exponent = 0.0f;
2158 object->cutoff = 180.0f;
2159 break;
2161 case D3DLIGHT_SPOT:
2162 /* Position */
2163 object->lightPosn[0] = pLight->Position.x;
2164 object->lightPosn[1] = pLight->Position.y;
2165 object->lightPosn[2] = pLight->Position.z;
2166 object->lightPosn[3] = 1.0;
2168 /* Direction */
2169 object->lightDirn[0] = pLight->Direction.x;
2170 object->lightDirn[1] = pLight->Direction.y;
2171 object->lightDirn[2] = pLight->Direction.z;
2172 object->lightDirn[3] = 1.0;
2175 * opengl-ish and d3d-ish spot lights use too different models for the
2176 * light "intensity" as a function of the angle towards the main light direction,
2177 * so we only can approximate very roughly.
2178 * however spot lights are rather rarely used in games (if ever used at all).
2179 * furthermore if still used, probably nobody pays attention to such details.
2181 if (pLight->Falloff == 0) {
2182 rho = 6.28f;
2183 } else {
2184 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2186 if (rho < 0.0001) rho = 0.0001f;
2187 object->exponent = -0.3/log(cos(rho/2));
2188 object->cutoff = pLight->Phi*90/M_PI;
2190 /* FIXME: Range */
2191 break;
2193 default:
2194 FIXME("Unrecognized light type %d\n", pLight->Type);
2197 /* Update the live definitions if the light is currently assigned a glIndex */
2198 if (object->glIndex != -1) {
2199 setup_light(iface, object->glIndex, object);
2201 return D3D_OK;
2204 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2205 PLIGHTINFOEL *lightInfo = NULL;
2206 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2207 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2209 /* Locate the light in the live lights */
2210 lightInfo = This->stateBlock->lights;
2211 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2213 if (lightInfo == NULL) {
2214 TRACE("Light information requested but light not defined\n");
2215 return D3DERR_INVALIDCALL;
2218 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
2219 return D3D_OK;
2222 /*****
2223 * Get / Set Light Enable
2224 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2225 *****/
2226 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2227 PLIGHTINFOEL *lightInfo = NULL;
2228 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2229 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2231 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2232 if (This->isRecordingState) {
2233 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2234 if (NULL == lightInfo) {
2235 return D3DERR_OUTOFVIDEOMEMORY;
2237 lightInfo->OriginalIndex = Index;
2238 lightInfo->glIndex = -1;
2239 lightInfo->enabledChanged = TRUE;
2241 /* Add to the END of the chain of lights changes to be replayed */
2242 if (This->updateStateBlock->lights == NULL) {
2243 This->updateStateBlock->lights = lightInfo;
2244 } else {
2245 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2246 while (temp->next != NULL) temp=temp->next;
2247 temp->next = lightInfo;
2249 TRACE("Recording... not performing anything more\n");
2250 return D3D_OK;
2253 /* Not recording... So, locate the light in the live lights */
2254 lightInfo = This->stateBlock->lights;
2255 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2257 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2258 if (lightInfo == NULL) {
2259 D3DLIGHT9 lightParms;
2260 /* Warning - untested code :-) Prob safe to change fixme to a trace but
2261 wait until someone confirms it seems to work! */
2262 TRACE("Light enabled requested but light not defined, so defining one!\n");
2263 lightParms.Type = D3DLIGHT_DIRECTIONAL;
2264 lightParms.Diffuse.r = 1.0;
2265 lightParms.Diffuse.g = 1.0;
2266 lightParms.Diffuse.b = 1.0;
2267 lightParms.Diffuse.a = 0.0;
2268 lightParms.Specular.r = 0.0;
2269 lightParms.Specular.g = 0.0;
2270 lightParms.Specular.b = 0.0;
2271 lightParms.Specular.a = 0.0;
2272 lightParms.Ambient.r = 0.0;
2273 lightParms.Ambient.g = 0.0;
2274 lightParms.Ambient.b = 0.0;
2275 lightParms.Ambient.a = 0.0;
2276 lightParms.Position.x = 0.0;
2277 lightParms.Position.y = 0.0;
2278 lightParms.Position.z = 0.0;
2279 lightParms.Direction.x = 0.0;
2280 lightParms.Direction.y = 0.0;
2281 lightParms.Direction.z = 1.0;
2282 lightParms.Range = 0.0;
2283 lightParms.Falloff = 0.0;
2284 lightParms.Attenuation0 = 0.0;
2285 lightParms.Attenuation1 = 0.0;
2286 lightParms.Attenuation2 = 0.0;
2287 lightParms.Theta = 0.0;
2288 lightParms.Phi = 0.0;
2289 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
2291 /* Search for it again! Should be fairly quick as near head of list */
2292 lightInfo = This->stateBlock->lights;
2293 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2294 if (lightInfo == NULL) {
2295 FIXME("Adding default lights has failed dismally\n");
2296 return D3DERR_INVALIDCALL;
2300 /* OK, we now have a light... */
2301 if (Enable == FALSE) {
2303 /* If we are disabling it, check it was enabled, and
2304 still only do something if it has assigned a glIndex (which it should have!) */
2305 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2306 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2307 ENTER_GL();
2308 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2309 checkGLcall("glDisable GL_LIGHT0+Index");
2310 LEAVE_GL();
2311 } else {
2312 TRACE("Nothing to do as light was not enabled\n");
2314 lightInfo->lightEnabled = FALSE;
2315 } else {
2317 /* We are enabling it. If it is enabled, it's really simple */
2318 if (lightInfo->lightEnabled) {
2319 /* nop */
2320 TRACE("Nothing to do as light was enabled\n");
2322 /* If it already has a glIndex, it's still simple */
2323 } else if (lightInfo->glIndex != -1) {
2324 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2325 lightInfo->lightEnabled = TRUE;
2326 ENTER_GL();
2327 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2328 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2329 LEAVE_GL();
2331 /* Otherwise got to find space - lights are ordered gl indexes first */
2332 } else {
2333 PLIGHTINFOEL *bsf = NULL;
2334 PLIGHTINFOEL *pos = This->stateBlock->lights;
2335 PLIGHTINFOEL *prev = NULL;
2336 int Index= 0;
2337 int glIndex = -1;
2339 /* Try to minimize changes as much as possible */
2340 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2342 /* Try to remember which index can be replaced if necessary */
2343 if (bsf==NULL && pos->lightEnabled == FALSE) {
2344 /* Found a light we can replace, save as best replacement */
2345 bsf = pos;
2348 /* Step to next space */
2349 prev = pos;
2350 pos = pos->next;
2351 Index ++;
2354 /* If we have too many active lights, fail the call */
2355 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2356 FIXME("Program requests too many concurrent lights\n");
2357 return D3DERR_INVALIDCALL;
2359 /* If we have allocated all lights, but not all are enabled,
2360 reuse one which is not enabled */
2361 } else if (Index == This->maxConcurrentLights) {
2362 /* use bsf - Simply swap the new light and the BSF one */
2363 PLIGHTINFOEL *bsfNext = bsf->next;
2364 PLIGHTINFOEL *bsfPrev = bsf->prev;
2366 /* Sort out ends */
2367 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2368 if (bsf->prev != NULL) {
2369 bsf->prev->next = lightInfo;
2370 } else {
2371 This->stateBlock->lights = lightInfo;
2374 /* If not side by side, lots of chains to update */
2375 if (bsf->next != lightInfo) {
2376 lightInfo->prev->next = bsf;
2377 bsf->next->prev = lightInfo;
2378 bsf->next = lightInfo->next;
2379 bsf->prev = lightInfo->prev;
2380 lightInfo->next = bsfNext;
2381 lightInfo->prev = bsfPrev;
2383 } else {
2384 /* Simple swaps */
2385 bsf->prev = lightInfo;
2386 bsf->next = lightInfo->next;
2387 lightInfo->next = bsf;
2388 lightInfo->prev = bsfPrev;
2392 /* Update states */
2393 glIndex = bsf->glIndex;
2394 bsf->glIndex = -1;
2395 lightInfo->glIndex = glIndex;
2396 lightInfo->lightEnabled = TRUE;
2398 /* Finally set up the light in gl itself */
2399 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2400 ENTER_GL();
2401 setup_light(iface, glIndex, lightInfo);
2402 glEnable(GL_LIGHT0 + glIndex);
2403 checkGLcall("glEnable GL_LIGHT0 new setup");
2404 LEAVE_GL();
2406 /* If we reached the end of the allocated lights, with space in the
2407 gl lights, setup a new light */
2408 } else if (pos->glIndex == -1) {
2410 /* We reached the end of the allocated gl lights, so already
2411 know the index of the next one! */
2412 glIndex = Index;
2413 lightInfo->glIndex = glIndex;
2414 lightInfo->lightEnabled = TRUE;
2416 /* In an ideal world, it's already in the right place */
2417 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2418 /* No need to move it */
2419 } else {
2420 /* Remove this light from the list */
2421 lightInfo->prev->next = lightInfo->next;
2422 if (lightInfo->next != NULL) {
2423 lightInfo->next->prev = lightInfo->prev;
2426 /* Add in at appropriate place (inbetween prev and pos) */
2427 lightInfo->prev = prev;
2428 lightInfo->next = pos;
2429 if (prev == NULL) {
2430 This->stateBlock->lights = lightInfo;
2431 } else {
2432 prev->next = lightInfo;
2434 if (pos != NULL) {
2435 pos->prev = lightInfo;
2439 /* Finally set up the light in gl itself */
2440 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2441 ENTER_GL();
2442 setup_light(iface, glIndex, lightInfo);
2443 glEnable(GL_LIGHT0 + glIndex);
2444 checkGLcall("glEnable GL_LIGHT0 new setup");
2445 LEAVE_GL();
2450 return D3D_OK;
2453 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2455 PLIGHTINFOEL *lightInfo = NULL;
2456 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2457 TRACE("(%p) : for idx(%ld)\n", This, Index);
2459 /* Locate the light in the live lights */
2460 lightInfo = This->stateBlock->lights;
2461 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2463 if (lightInfo == NULL) {
2464 TRACE("Light enabled state requested but light not defined\n");
2465 return D3DERR_INVALIDCALL;
2467 *pEnable = lightInfo->lightEnabled;
2468 return D3D_OK;
2471 /*****
2472 * Get / Set Clip Planes
2473 *****/
2474 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2475 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2476 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2478 /* Validate Index */
2479 if (Index >= GL_LIMITS(clipplanes)) {
2480 TRACE("Application has requested clipplane this device doesn't support\n");
2481 return D3DERR_INVALIDCALL;
2484 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2485 This->updateStateBlock->set.clipplane[Index] = TRUE;
2486 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2487 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2488 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2489 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2491 /* Handle recording of state blocks */
2492 if (This->isRecordingState) {
2493 TRACE("Recording... not performing anything\n");
2494 return D3D_OK;
2497 /* Apply it */
2499 ENTER_GL();
2501 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2502 glMatrixMode(GL_MODELVIEW);
2503 glPushMatrix();
2504 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2506 TRACE("Clipplane [%f,%f,%f,%f]\n",
2507 This->updateStateBlock->clipplane[Index][0],
2508 This->updateStateBlock->clipplane[Index][1],
2509 This->updateStateBlock->clipplane[Index][2],
2510 This->updateStateBlock->clipplane[Index][3]);
2511 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2512 checkGLcall("glClipPlane");
2514 glPopMatrix();
2515 LEAVE_GL();
2517 return D3D_OK;
2520 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2521 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2522 TRACE("(%p) : for idx %ld\n", This, Index);
2524 /* Validate Index */
2525 if (Index >= GL_LIMITS(clipplanes)) {
2526 TRACE("Application has requested clipplane this device doesn't support\n");
2527 return D3DERR_INVALIDCALL;
2530 pPlane[0] = This->stateBlock->clipplane[Index][0];
2531 pPlane[1] = This->stateBlock->clipplane[Index][1];
2532 pPlane[2] = This->stateBlock->clipplane[Index][2];
2533 pPlane[3] = This->stateBlock->clipplane[Index][3];
2534 return D3D_OK;
2537 /*****
2538 * Get / Set Clip Plane Status
2539 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2540 *****/
2541 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2542 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2543 FIXME("(%p) : stub\n", This);
2544 if (NULL == pClipStatus) {
2545 return D3DERR_INVALIDCALL;
2547 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2548 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2549 return D3D_OK;
2552 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2553 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2554 FIXME("(%p) : stub\n", This);
2555 if (NULL == pClipStatus) {
2556 return D3DERR_INVALIDCALL;
2558 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2559 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2560 return D3D_OK;
2563 /*****
2564 * Get / Set Material
2565 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2566 *****/
2567 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2568 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2570 This->updateStateBlock->changed.material = TRUE;
2571 This->updateStateBlock->set.material = TRUE;
2572 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2574 /* Handle recording of state blocks */
2575 if (This->isRecordingState) {
2576 TRACE("Recording... not performing anything\n");
2577 return D3D_OK;
2580 ENTER_GL();
2581 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2582 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2583 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2584 pMaterial->Ambient.b, pMaterial->Ambient.a);
2585 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2586 pMaterial->Specular.b, pMaterial->Specular.a);
2587 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2588 pMaterial->Emissive.b, pMaterial->Emissive.a);
2589 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2591 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2592 checkGLcall("glMaterialfv(GL_AMBIENT)");
2593 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2594 checkGLcall("glMaterialfv(GL_DIFFUSE)");
2596 /* Only change material color if specular is enabled, otherwise it is set to black */
2597 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2598 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2599 checkGLcall("glMaterialfv(GL_SPECULAR");
2600 } else {
2601 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2602 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2603 checkGLcall("glMaterialfv(GL_SPECULAR");
2605 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2606 checkGLcall("glMaterialfv(GL_EMISSION)");
2607 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2608 checkGLcall("glMaterialf(GL_SHININESS");
2610 LEAVE_GL();
2611 return D3D_OK;
2614 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2615 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2616 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2617 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2618 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2619 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2620 pMaterial->Ambient.b, pMaterial->Ambient.a);
2621 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2622 pMaterial->Specular.b, pMaterial->Specular.a);
2623 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2624 pMaterial->Emissive.b, pMaterial->Emissive.a);
2625 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2627 return D3D_OK;
2630 /*****
2631 * Get / Set Indices
2632 *****/
2633 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2634 UINT BaseVertexIndex) {
2635 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2636 IWineD3DIndexBuffer *oldIdxs;
2638 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2639 oldIdxs = This->updateStateBlock->pIndexData;
2641 This->updateStateBlock->changed.indices = TRUE;
2642 This->updateStateBlock->set.indices = TRUE;
2643 This->updateStateBlock->pIndexData = pIndexData;
2644 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2646 /* Handle recording of state blocks */
2647 if (This->isRecordingState) {
2648 TRACE("Recording... not performing anything\n");
2649 return D3D_OK;
2652 if (NULL != pIndexData) {
2653 IWineD3DIndexBuffer_AddRef(pIndexData);
2655 if (NULL != oldIdxs) {
2656 IWineD3DIndexBuffer_Release(oldIdxs);
2658 return D3D_OK;
2661 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2662 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2664 *ppIndexData = This->stateBlock->pIndexData;
2666 /* up ref count on ppindexdata */
2667 if (*ppIndexData) {
2668 IWineD3DIndexBuffer_AddRef(*ppIndexData);
2669 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2670 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
2671 }else{
2672 TRACE("(%p) No index data set\n", This);
2674 TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
2676 return D3D_OK;
2679 /*****
2680 * Get / Set Viewports
2681 *****/
2682 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2683 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2685 TRACE("(%p)\n", This);
2686 This->updateStateBlock->changed.viewport = TRUE;
2687 This->updateStateBlock->set.viewport = TRUE;
2688 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2690 /* Handle recording of state blocks */
2691 if (This->isRecordingState) {
2692 TRACE("Recording... not performing anything\n");
2693 return D3D_OK;
2696 ENTER_GL();
2698 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2699 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2701 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2702 checkGLcall("glDepthRange");
2703 /* Note: GL requires lower left, DirectX supplies upper left */
2704 /* TODO: replace usage of renderTarget with context management */
2705 glViewport(pViewport->X,
2706 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2707 pViewport->Width, pViewport->Height);
2709 checkGLcall("glViewport");
2711 LEAVE_GL();
2713 return D3D_OK;
2717 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2718 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2719 TRACE("(%p)\n", This);
2720 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2721 return D3D_OK;
2724 /*****
2725 * Get / Set Render States
2726 * TODO: Verify against dx9 definitions
2727 *****/
2728 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2730 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2731 DWORD OldValue = This->stateBlock->renderState[State];
2733 /* Simple way of referring to either a DWORD or a 4 byte float */
2734 union {
2735 DWORD d;
2736 float f;
2737 } tmpvalue;
2739 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2740 This->updateStateBlock->changed.renderState[State] = TRUE;
2741 This->updateStateBlock->set.renderState[State] = TRUE;
2742 This->updateStateBlock->renderState[State] = Value;
2744 /* Handle recording of state blocks */
2745 if (This->isRecordingState) {
2746 TRACE("Recording... not performing anything\n");
2747 return D3D_OK;
2750 ENTER_GL();
2752 switch (State) {
2753 case WINED3DRS_FILLMODE :
2754 switch ((D3DFILLMODE) Value) {
2755 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2756 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2757 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2758 default:
2759 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
2761 checkGLcall("glPolygonMode (fillmode)");
2762 break;
2764 case WINED3DRS_LIGHTING :
2765 if (Value) {
2766 glEnable(GL_LIGHTING);
2767 checkGLcall("glEnable GL_LIGHTING");
2768 } else {
2769 glDisable(GL_LIGHTING);
2770 checkGLcall("glDisable GL_LIGHTING");
2772 break;
2774 case WINED3DRS_ZENABLE :
2775 switch ((D3DZBUFFERTYPE) Value) {
2776 case D3DZB_FALSE:
2777 glDisable(GL_DEPTH_TEST);
2778 checkGLcall("glDisable GL_DEPTH_TEST");
2779 break;
2780 case D3DZB_TRUE:
2781 glEnable(GL_DEPTH_TEST);
2782 checkGLcall("glEnable GL_DEPTH_TEST");
2783 break;
2784 case D3DZB_USEW:
2785 glEnable(GL_DEPTH_TEST);
2786 checkGLcall("glEnable GL_DEPTH_TEST");
2787 FIXME("W buffer is not well handled\n");
2788 break;
2789 default:
2790 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2792 break;
2794 case WINED3DRS_CULLMODE :
2796 /* If we are culling "back faces with clockwise vertices" then
2797 set front faces to be counter clockwise and enable culling
2798 of back faces */
2799 switch ((D3DCULL) Value) {
2800 case D3DCULL_NONE:
2801 glDisable(GL_CULL_FACE);
2802 checkGLcall("glDisable GL_CULL_FACE");
2803 break;
2804 case D3DCULL_CW:
2805 glEnable(GL_CULL_FACE);
2806 checkGLcall("glEnable GL_CULL_FACE");
2807 if (This->renderUpsideDown) {
2808 glFrontFace(GL_CW);
2809 checkGLcall("glFrontFace GL_CW");
2810 } else {
2811 glFrontFace(GL_CCW);
2812 checkGLcall("glFrontFace GL_CCW");
2814 glCullFace(GL_BACK);
2815 break;
2816 case D3DCULL_CCW:
2817 glEnable(GL_CULL_FACE);
2818 checkGLcall("glEnable GL_CULL_FACE");
2819 if (This->renderUpsideDown) {
2820 glFrontFace(GL_CCW);
2821 checkGLcall("glFrontFace GL_CCW");
2822 } else {
2823 glFrontFace(GL_CW);
2824 checkGLcall("glFrontFace GL_CW");
2826 glCullFace(GL_BACK);
2827 break;
2828 default:
2829 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2831 break;
2833 case WINED3DRS_SHADEMODE :
2834 switch ((D3DSHADEMODE) Value) {
2835 case D3DSHADE_FLAT:
2836 glShadeModel(GL_FLAT);
2837 checkGLcall("glShadeModel");
2838 break;
2839 case D3DSHADE_GOURAUD:
2840 glShadeModel(GL_SMOOTH);
2841 checkGLcall("glShadeModel");
2842 break;
2843 case D3DSHADE_PHONG:
2844 FIXME("D3DSHADE_PHONG isn't supported?\n");
2846 LEAVE_GL();
2847 return D3DERR_INVALIDCALL;
2848 default:
2849 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2851 break;
2853 case WINED3DRS_DITHERENABLE :
2854 if (Value) {
2855 glEnable(GL_DITHER);
2856 checkGLcall("glEnable GL_DITHER");
2857 } else {
2858 glDisable(GL_DITHER);
2859 checkGLcall("glDisable GL_DITHER");
2861 break;
2863 case WINED3DRS_ZWRITEENABLE :
2864 if (Value) {
2865 glDepthMask(1);
2866 checkGLcall("glDepthMask");
2867 } else {
2868 glDepthMask(0);
2869 checkGLcall("glDepthMask");
2871 break;
2873 case WINED3DRS_ZFUNC :
2875 int glParm = GL_LESS;
2877 switch ((D3DCMPFUNC) Value) {
2878 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2879 case D3DCMP_LESS: glParm=GL_LESS; break;
2880 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2881 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2882 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2883 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2884 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2885 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2886 default:
2887 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2889 glDepthFunc(glParm);
2890 checkGLcall("glDepthFunc");
2892 break;
2894 case WINED3DRS_AMBIENT :
2896 float col[4];
2897 D3DCOLORTOGLFLOAT4(Value, col);
2898 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2899 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2900 checkGLcall("glLightModel for MODEL_AMBIENT");
2903 break;
2905 case WINED3DRS_ALPHABLENDENABLE :
2906 if (Value) {
2907 glEnable(GL_BLEND);
2908 checkGLcall("glEnable GL_BLEND");
2909 } else {
2910 glDisable(GL_BLEND);
2911 checkGLcall("glDisable GL_BLEND");
2913 break;
2915 case WINED3DRS_SRCBLEND :
2916 case WINED3DRS_DESTBLEND :
2918 int newVal = GL_ZERO;
2919 switch (Value) {
2920 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2921 case D3DBLEND_ONE : newVal = GL_ONE; break;
2922 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2923 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2924 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2925 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2926 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2927 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2928 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2929 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2930 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2932 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2933 This->srcBlend = newVal;
2934 This->dstBlend = newVal;
2935 break;
2937 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2938 This->srcBlend = newVal;
2939 This->dstBlend = newVal;
2940 break;
2941 default:
2942 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2945 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2946 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2947 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2948 glBlendFunc(This->srcBlend, This->dstBlend);
2950 checkGLcall("glBlendFunc");
2952 break;
2954 case WINED3DRS_ALPHATESTENABLE :
2955 if (Value) {
2956 glEnable(GL_ALPHA_TEST);
2957 checkGLcall("glEnable GL_ALPHA_TEST");
2958 } else {
2959 glDisable(GL_ALPHA_TEST);
2960 checkGLcall("glDisable GL_ALPHA_TEST");
2962 break;
2964 case WINED3DRS_ALPHAFUNC :
2966 int glParm = GL_LESS;
2967 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2969 switch ((D3DCMPFUNC) Value) {
2970 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2971 case D3DCMP_LESS: glParm = GL_LESS; break;
2972 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2973 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2974 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2975 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2976 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2977 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2978 default:
2979 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2981 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2982 glAlphaFunc(glParm, ref);
2983 This->alphafunc = glParm;
2984 checkGLcall("glAlphaFunc");
2986 break;
2988 case WINED3DRS_ALPHAREF :
2990 int glParm = This->alphafunc;
2991 float ref = 1.0f;
2993 ref = ((float) Value) / 255.0f;
2994 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2995 glAlphaFunc(glParm, ref);
2996 checkGLcall("glAlphaFunc");
2998 break;
3000 case WINED3DRS_CLIPPLANEENABLE :
3001 case WINED3DRS_CLIPPING :
3003 /* Ensure we only do the changed clip planes */
3004 DWORD enable = 0xFFFFFFFF;
3005 DWORD disable = 0x00000000;
3007 /* If enabling / disabling all */
3008 if (State == WINED3DRS_CLIPPING) {
3009 if (Value) {
3010 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3011 disable = 0x00;
3012 } else {
3013 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3014 enable = 0x00;
3016 } else {
3017 enable = Value & ~OldValue;
3018 disable = ~Value & OldValue;
3021 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
3022 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
3023 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
3024 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
3025 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
3026 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
3028 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
3029 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
3030 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
3031 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
3032 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
3033 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
3035 /** update clipping status */
3036 if (enable) {
3037 This->stateBlock->clip_status.ClipUnion = 0;
3038 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
3039 } else {
3040 This->stateBlock->clip_status.ClipUnion = 0;
3041 This->stateBlock->clip_status.ClipIntersection = 0;
3044 break;
3046 case WINED3DRS_BLENDOP :
3048 int glParm = GL_FUNC_ADD;
3050 switch ((D3DBLENDOP) Value) {
3051 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
3052 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
3053 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3054 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
3055 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
3056 default:
3057 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
3059 TRACE("glBlendEquation(%x)\n", glParm);
3060 glBlendEquation(glParm);
3061 checkGLcall("glBlendEquation");
3063 break;
3065 case WINED3DRS_TEXTUREFACTOR :
3067 unsigned int i;
3069 /* Note the texture color applies to all textures whereas
3070 GL_TEXTURE_ENV_COLOR applies to active only */
3071 float col[4];
3072 D3DCOLORTOGLFLOAT4(Value, col);
3073 /* Set the default alpha blend color */
3074 glBlendColor(col[0], col[1], col[2], col[3]);
3075 checkGLcall("glBlendColor");
3077 /* And now the default texture color as well */
3078 for (i = 0; i < GL_LIMITS(textures); i++) {
3080 /* Note the D3DRS value applies to all textures, but GL has one
3081 per texture, so apply it now ready to be used! */
3082 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3083 GLACTIVETEXTURE(i);
3084 } else if (i>0) {
3085 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3088 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3089 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3092 break;
3094 case WINED3DRS_SPECULARENABLE :
3096 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3097 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3098 specular color. This is wrong:
3099 Separate specular color means the specular colour is maintained separately, whereas
3100 single color means it is merged in. However in both cases they are being used to
3101 some extent.
3102 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3103 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3104 running 1.4 yet!
3106 if (Value) {
3107 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3108 checkGLcall("glMaterialfv");
3109 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3110 glEnable(GL_COLOR_SUM_EXT);
3111 } else {
3112 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3114 checkGLcall("glEnable(GL_COLOR_SUM)");
3115 } else {
3116 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3118 /* for the case of enabled lighting: */
3119 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3120 checkGLcall("glMaterialfv");
3122 /* for the case of disabled lighting: */
3123 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3124 glDisable(GL_COLOR_SUM_EXT);
3125 } else {
3126 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3128 checkGLcall("glDisable(GL_COLOR_SUM)");
3131 break;
3133 case WINED3DRS_STENCILENABLE :
3134 if (Value) {
3135 glEnable(GL_STENCIL_TEST);
3136 checkGLcall("glEnable GL_STENCIL_TEST");
3137 } else {
3138 glDisable(GL_STENCIL_TEST);
3139 checkGLcall("glDisable GL_STENCIL_TEST");
3141 break;
3143 case WINED3DRS_STENCILFUNC :
3145 int glParm = GL_ALWAYS;
3146 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3147 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3149 switch ((D3DCMPFUNC) Value) {
3150 case D3DCMP_NEVER: glParm=GL_NEVER; break;
3151 case D3DCMP_LESS: glParm=GL_LESS; break;
3152 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
3153 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
3154 case D3DCMP_GREATER: glParm=GL_GREATER; break;
3155 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
3156 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
3157 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
3158 default:
3159 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3161 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3162 This->stencilfunc = glParm;
3163 glStencilFunc(glParm, ref, mask);
3164 checkGLcall("glStencilFunc");
3166 break;
3168 case WINED3DRS_STENCILREF :
3170 int glParm = This->stencilfunc;
3171 int ref = 0;
3172 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3174 ref = Value;
3175 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3176 glStencilFunc(glParm, ref, mask);
3177 checkGLcall("glStencilFunc");
3179 break;
3181 case WINED3DRS_STENCILMASK :
3183 int glParm = This->stencilfunc;
3184 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3185 GLuint mask = Value;
3187 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3188 glStencilFunc(glParm, ref, mask);
3189 checkGLcall("glStencilFunc");
3191 break;
3193 case WINED3DRS_STENCILFAIL :
3195 GLenum fail ;
3196 GLint zpass ;
3197 GLint zfail ;
3199 fail = StencilOp(Value);
3200 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
3201 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
3202 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
3203 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
3205 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3206 glStencilOp(fail, zfail, zpass);
3207 checkGLcall("glStencilOp(fail, zfail, zpass);");
3209 break;
3210 case WINED3DRS_STENCILZFAIL :
3212 GLint fail ;
3213 GLint zpass ;
3214 GLenum zfail ;
3216 glGetIntegerv(GL_STENCIL_FAIL, &fail);
3217 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
3218 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
3219 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
3220 zfail = StencilOp(Value);
3222 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3223 glStencilOp(fail, zfail, zpass);
3224 checkGLcall("glStencilOp(fail, zfail, zpass);");
3226 break;
3227 case WINED3DRS_STENCILPASS :
3229 GLint fail ;
3230 GLenum zpass ;
3231 GLint zfail ;
3233 glGetIntegerv(GL_STENCIL_FAIL, &fail);
3234 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
3235 zpass = StencilOp(Value);
3236 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
3237 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
3239 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3240 glStencilOp(fail, zfail, zpass);
3241 checkGLcall("glStencilOp(fail, zfail, zpass);");
3243 break;
3245 case WINED3DRS_STENCILWRITEMASK :
3247 glStencilMask(Value);
3248 TRACE("glStencilMask(%lu)\n", Value);
3249 checkGLcall("glStencilMask");
3251 break;
3253 case WINED3DRS_FOGENABLE :
3255 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
3256 glEnable(GL_FOG);
3257 checkGLcall("glEnable GL_FOG");
3258 } else {
3259 glDisable(GL_FOG);
3260 checkGLcall("glDisable GL_FOG");
3263 break;
3265 case WINED3DRS_RANGEFOGENABLE :
3267 if (Value) {
3268 TRACE("Enabled RANGEFOG");
3269 } else {
3270 TRACE("Disabled RANGEFOG");
3273 break;
3275 case WINED3DRS_FOGCOLOR :
3277 float col[4];
3278 D3DCOLORTOGLFLOAT4(Value, col);
3279 /* Set the default alpha blend color */
3280 glFogfv(GL_FOG_COLOR, &col[0]);
3281 checkGLcall("glFog GL_FOG_COLOR");
3283 break;
3285 case WINED3DRS_FOGTABLEMODE :
3287 glHint(GL_FOG_HINT, GL_NICEST);
3288 switch (Value) {
3289 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3290 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3291 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3292 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3293 default:
3294 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3296 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3297 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3300 break;
3302 case WINED3DRS_FOGVERTEXMODE :
3304 glHint(GL_FOG_HINT, GL_FASTEST);
3305 switch (Value) {
3306 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3307 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3308 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3309 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3310 default:
3311 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3313 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3314 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
3317 break;
3319 case WINED3DRS_FOGSTART :
3321 tmpvalue.d = Value;
3322 glFogfv(GL_FOG_START, &tmpvalue.f);
3323 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3324 TRACE("Fog Start == %f\n", tmpvalue.f);
3326 break;
3328 case WINED3DRS_FOGEND :
3330 tmpvalue.d = Value;
3331 glFogfv(GL_FOG_END, &tmpvalue.f);
3332 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3333 TRACE("Fog End == %f\n", tmpvalue.f);
3335 break;
3337 case WINED3DRS_FOGDENSITY :
3339 tmpvalue.d = Value;
3340 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3341 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3343 break;
3345 case WINED3DRS_VERTEXBLEND :
3347 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3348 TRACE("Vertex Blending state to %ld\n", Value);
3350 break;
3352 case WINED3DRS_TWEENFACTOR :
3354 tmpvalue.d = Value;
3355 This->updateStateBlock->tween_factor = tmpvalue.f;
3356 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3358 break;
3360 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
3362 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3364 break;
3366 case WINED3DRS_COLORVERTEX :
3367 case WINED3DRS_DIFFUSEMATERIALSOURCE :
3368 case WINED3DRS_SPECULARMATERIALSOURCE :
3369 case WINED3DRS_AMBIENTMATERIALSOURCE :
3370 case WINED3DRS_EMISSIVEMATERIALSOURCE :
3372 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3374 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3375 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3376 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3377 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3378 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3379 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3381 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3382 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3383 Parm = GL_AMBIENT_AND_DIFFUSE;
3384 } else {
3385 Parm = GL_DIFFUSE;
3387 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3388 Parm = GL_AMBIENT;
3389 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3390 Parm = GL_EMISSION;
3391 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3392 Parm = GL_SPECULAR;
3393 } else {
3394 Parm = -1;
3397 if (Parm == -1) {
3398 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3399 } else {
3400 This->tracking_color = NEEDS_TRACKING;
3401 This->tracking_parm = Parm;
3404 } else {
3405 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3408 break;
3410 case WINED3DRS_LINEPATTERN :
3412 union {
3413 DWORD d;
3414 D3DLINEPATTERN lp;
3415 } tmppattern;
3416 tmppattern.d = Value;
3418 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3420 if (tmppattern.lp.wRepeatFactor) {
3421 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3422 checkGLcall("glLineStipple(repeat, linepattern)");
3423 glEnable(GL_LINE_STIPPLE);
3424 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3425 } else {
3426 glDisable(GL_LINE_STIPPLE);
3427 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3430 break;
3432 case WINED3DRS_ZBIAS : /* D3D8 only */
3434 if (Value) {
3435 tmpvalue.d = Value;
3436 TRACE("ZBias value %f\n", tmpvalue.f);
3437 glPolygonOffset(0, -tmpvalue.f);
3438 checkGLcall("glPolygonOffset(0, -Value)");
3439 glEnable(GL_POLYGON_OFFSET_FILL);
3440 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3441 glEnable(GL_POLYGON_OFFSET_LINE);
3442 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3443 glEnable(GL_POLYGON_OFFSET_POINT);
3444 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3445 } else {
3446 glDisable(GL_POLYGON_OFFSET_FILL);
3447 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3448 glDisable(GL_POLYGON_OFFSET_LINE);
3449 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3450 glDisable(GL_POLYGON_OFFSET_POINT);
3451 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3454 break;
3456 case WINED3DRS_NORMALIZENORMALS :
3457 if (Value) {
3458 glEnable(GL_NORMALIZE);
3459 checkGLcall("glEnable(GL_NORMALIZE);");
3460 } else {
3461 glDisable(GL_NORMALIZE);
3462 checkGLcall("glDisable(GL_NORMALIZE);");
3464 break;
3466 case WINED3DRS_POINTSIZE :
3467 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
3468 tmpvalue.d = Value;
3469 TRACE("Set point size to %f\n", tmpvalue.f);
3470 glPointSize(tmpvalue.f);
3471 checkGLcall("glPointSize(...);");
3472 break;
3474 case WINED3DRS_POINTSIZE_MIN :
3475 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3476 tmpvalue.d = Value;
3477 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3478 checkGLcall("glPointParameterfEXT(...);");
3479 } else {
3480 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3482 break;
3484 case WINED3DRS_POINTSIZE_MAX :
3485 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3486 tmpvalue.d = Value;
3487 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3488 checkGLcall("glPointParameterfEXT(...);");
3489 } else {
3490 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3492 break;
3494 case WINED3DRS_POINTSCALE_A :
3495 case WINED3DRS_POINTSCALE_B :
3496 case WINED3DRS_POINTSCALE_C :
3497 case WINED3DRS_POINTSCALEENABLE :
3499 /* If enabled, supply the parameters, otherwise fall back to defaults */
3500 if (This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3501 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3502 /* TODO: Correct the scaling (this hack seems to be good enough for every demo that uses point sprites!) */
3503 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A])/ This->stateBlock->viewport.Width;
3504 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B])/ This->stateBlock->viewport.Height;
3505 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) *
3506 2.0f /(This->stateBlock->viewport.Width * This->stateBlock->viewport.Height);
3508 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3509 TRACE("glPointParameterfvARB %f %f %f\n", att[0], att[1], att[2]);
3510 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3511 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3512 } else {
3513 TRACE("WINED3DRS_POINTSCALEENABLE not supported on this opengl\n");
3515 } else {
3516 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3517 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3518 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3519 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3520 } else {
3521 TRACE("WINED3DRS_POINTSCALEENABLE not supported, but not on either\n");
3524 break;
3527 case WINED3DRS_COLORWRITEENABLE :
3529 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3530 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3531 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3532 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3533 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3534 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3535 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3536 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3537 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3538 checkGLcall("glColorMask(...)");
3540 break;
3542 case WINED3DRS_LOCALVIEWER :
3544 GLint state = (Value) ? 1 : 0;
3545 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3546 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3548 break;
3550 case WINED3DRS_LASTPIXEL :
3552 if (Value) {
3553 TRACE("Last Pixel Drawing Enabled\n");
3554 } else {
3555 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3558 break;
3560 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3562 if (Value) {
3563 TRACE("Software Processing Enabled\n");
3564 } else {
3565 TRACE("Software Processing Disabled\n");
3568 break;
3570 /** not supported */
3571 case WINED3DRS_ZVISIBLE :
3573 LEAVE_GL();
3574 return D3DERR_INVALIDCALL;
3576 case WINED3DRS_POINTSPRITEENABLE :
3577 /* TODO: NV_POINT_SPRITE */
3578 if (GL_SUPPORT(ARB_POINT_SPRITE)) {
3579 if (Value != FALSE) {
3580 /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
3581 glDisable(GL_POINT_SMOOTH);
3582 /* Centre the texture on the vertex */
3583 VTRACE("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
3584 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
3586 VTRACE("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
3587 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
3588 checkGLcall("glTexEnvf(...)");
3589 VTRACE("glEnable( GL_POINT_SPRITE_ARB )\n");
3590 glEnable( GL_POINT_SPRITE_ARB );
3591 checkGLcall("glEnable(...)");
3592 } else {
3593 VTRACE("glDisable( GL_POINT_SPRITE_ARB )\n");
3594 glDisable( GL_POINT_SPRITE_ARB );
3595 checkGLcall("glEnable(...)");
3598 break;
3599 /* Unhandled yet...! */
3600 case WINED3DRS_EDGEANTIALIAS :
3601 case WINED3DRS_WRAP0 :
3602 case WINED3DRS_WRAP1 :
3603 case WINED3DRS_WRAP2 :
3604 case WINED3DRS_WRAP3 :
3605 case WINED3DRS_WRAP4 :
3606 case WINED3DRS_WRAP5 :
3607 case WINED3DRS_WRAP6 :
3608 case WINED3DRS_WRAP7 :
3610 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
3611 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
3612 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
3613 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
3614 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
3616 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
3618 TRACE("(%p)->(%d,%ld) Texture wraping not yet supported\n",This, State, Value);
3619 break;
3620 case WINED3DRS_MULTISAMPLEANTIALIAS :
3621 case WINED3DRS_MULTISAMPLEMASK :
3622 case WINED3DRS_PATCHEDGESTYLE :
3623 case WINED3DRS_PATCHSEGMENTS :
3624 case WINED3DRS_DEBUGMONITORTOKEN :
3625 case WINED3DRS_POSITIONORDER :
3626 case WINED3DRS_NORMALORDER :
3627 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3628 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3629 break;
3630 default:
3631 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3634 LEAVE_GL();
3636 return D3D_OK;
3639 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3640 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3641 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3642 *pValue = This->stateBlock->renderState[State];
3643 return D3D_OK;
3646 /*****
3647 * Get / Set Sampler States
3648 * TODO: Verify against dx9 definitions
3649 *****/
3651 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3652 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3654 * SetSampler is designed to allow for more than the standard up to 8 textures
3655 * and Geforce has stopped supporting more than 6 standard textures in openGL.
3656 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3658 * http://developer.nvidia.com/object/General_FAQ.html#t6
3660 * There are two new settings for GForce
3661 * the sampler one:
3662 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3663 * and the texture one:
3664 * GL_MAX_TEXTURE_COORDS_ARB.
3665 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3666 ******************/
3667 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
3668 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
3670 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
3671 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE, Sampler, Type);
3672 return D3DERR_INVALIDCALL;
3674 TRACE("Setting sampler %ld %d to %ld\n", Sampler, Type, Value);
3675 This->updateStateBlock->samplerState[Sampler][Type] = Value;
3676 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
3677 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
3679 /* Handle recording of state blocks */
3680 if (This->isRecordingState) {
3681 TRACE("Recording... not performing anything\n");
3682 return D3D_OK;
3685 return D3D_OK;
3688 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3689 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3690 /** TODO: check that sampler is in range **/
3691 *Value = This->updateStateBlock->samplerState[Sampler][Type];
3692 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
3694 return D3D_OK;
3697 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3698 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3699 ENTER_GL();
3701 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3702 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3703 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3704 LEAVE_GL();
3706 return D3D_OK;
3709 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3710 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3711 GLint scissorBox[4];
3713 ENTER_GL();
3714 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3715 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
3716 pRect->left = scissorBox[1];
3717 pRect->top = scissorBox[2];
3718 pRect->right = scissorBox[1] + scissorBox[3];
3719 pRect->bottom = scissorBox[2] + scissorBox[4];
3720 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3721 LEAVE_GL();
3722 return D3D_OK;
3725 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3726 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3728 TRACE("(%p) : pDecl=%p\n", This, pDecl);
3730 This->updateStateBlock->vertexDecl = pDecl;
3731 This->updateStateBlock->changed.vertexDecl = TRUE;
3732 This->updateStateBlock->set.vertexDecl = TRUE;
3734 if (This->isRecordingState) {
3735 TRACE("Recording... not performing anything\n");
3736 return D3D_OK;
3739 if (NULL != pDecl) {
3740 IWineD3DVertexDeclaration_AddRef(pDecl);
3742 if (NULL != This->updateStateBlock->vertexDecl) {
3743 IWineD3DVertexDeclaration_Release(This->updateStateBlock->vertexDecl);
3745 return D3D_OK;
3748 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3749 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3751 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3753 *ppDecl = This->stateBlock->vertexDecl;
3754 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3755 return D3D_OK;
3758 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
3759 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3760 IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
3762 This->updateStateBlock->vertexShader = pShader;
3763 This->updateStateBlock->changed.vertexShader = TRUE;
3764 This->updateStateBlock->set.vertexShader = TRUE;
3766 if (This->isRecordingState) {
3767 TRACE("Recording... not performing anything\n");
3768 return D3D_OK;
3771 if (NULL != pShader) {
3772 IWineD3DVertexShader_AddRef(pShader);
3774 if (NULL != oldShader) {
3775 IWineD3DVertexShader_Release(oldShader);
3778 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3780 * TODO: merge HAL shaders context switching from prototype
3782 return D3D_OK;
3785 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
3786 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3788 if (NULL == ppShader) {
3789 return D3DERR_INVALIDCALL;
3791 *ppShader = This->stateBlock->vertexShader;
3792 if( NULL != *ppShader)
3793 IWineD3DVertexShader_AddRef(*ppShader);
3795 TRACE("(%p) : returning %p\n", This, *ppShader);
3796 return D3D_OK;
3799 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
3800 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3802 int i;
3803 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
3805 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
3806 iface, dstData, srcData, type, start, count, registersize);
3808 if (type != WINESHADERCNST_NONE) {
3809 if (srcData == NULL || cnt < 0) {
3810 return D3DERR_INVALIDCALL;
3813 CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
3816 for (i = start; i < cnt + start; ++i) {
3817 This->updateStateBlock->changed.vertexShaderConstants[i] = TRUE;
3818 This->updateStateBlock->set.vertexShaderConstants[i] = TRUE;
3819 This->updateStateBlock->vertexShaderConstantT[i] = type;
3822 return D3D_OK;
3825 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
3826 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3828 int i;
3829 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
3831 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
3832 iface, dstData, srcData, type, start, count, registersize);
3834 /* Verify that the requested shader constant was populated with the correct type */
3835 for (i = start; i < cnt + start; ++i) {
3836 if (This->updateStateBlock->vertexShaderConstantT[i] != type) {
3837 TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning D3DERR_INVALIDCALL\n",
3838 This, type, This->updateStateBlock->vertexShaderConstantT[i]);
3839 return D3DERR_INVALIDCALL;
3843 if (dstData == NULL || cnt < 0) {
3844 return D3DERR_INVALIDCALL;
3847 CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
3849 return D3D_OK;
3852 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
3853 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3855 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
3856 This->updateStateBlock->vertexShaderConstantB,
3857 pConstantData,
3858 WINESHADERCNST_BOOL,
3859 StartRegister,
3860 BoolCount,
3861 sizeof(*pConstantData));
3864 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
3865 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3867 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
3868 pConstantData,
3869 This->updateStateBlock->vertexShaderConstantB,
3870 WINESHADERCNST_BOOL,
3871 StartRegister,
3872 BoolCount,
3873 sizeof(*pConstantData));
3876 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
3877 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3879 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
3880 This->updateStateBlock->vertexShaderConstantI,
3881 pConstantData,
3882 WINESHADERCNST_INTEGER,
3883 StartRegister,
3884 Vector4iCount,
3885 4 * sizeof(*pConstantData));
3888 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
3889 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3891 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
3892 pConstantData,
3893 This->updateStateBlock->vertexShaderConstantI,
3894 WINESHADERCNST_INTEGER,
3895 StartRegister,
3896 Vector4iCount,
3897 4 * sizeof(*pConstantData));
3901 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
3902 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3904 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
3905 This->updateStateBlock->vertexShaderConstantF,
3906 pConstantData,
3907 WINESHADERCNST_FLOAT,
3908 StartRegister,
3909 Vector4fCount,
3910 4 * sizeof(*pConstantData));
3913 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
3914 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3916 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
3917 pConstantData,
3918 This->updateStateBlock->vertexShaderConstantF,
3919 WINESHADERCNST_FLOAT,
3920 StartRegister,
3921 Vector4fCount,
3922 4 * sizeof(*pConstantData));
3925 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
3926 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
3927 NULL,
3928 NULL,
3929 WINESHADERCNST_NONE,
3930 StartRegister,
3931 VectorNCount,
3935 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
3936 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3937 IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader;
3938 This->updateStateBlock->pixelShader = pShader;
3939 This->updateStateBlock->changed.pixelShader = TRUE;
3940 This->updateStateBlock->set.pixelShader = TRUE;
3942 /* Handle recording of state blocks */
3943 if (This->isRecordingState) {
3944 TRACE("Recording... not performing anything\n");
3945 return D3D_OK;
3948 if (NULL != pShader) {
3949 IWineD3DPixelShader_AddRef(pShader);
3951 if (NULL != oldShader) {
3952 IWineD3DPixelShader_Release(oldShader);
3955 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3957 * TODO: merge HAL shaders context switching from prototype
3959 return D3D_OK;
3962 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3963 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3965 if (NULL == ppShader) {
3966 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
3967 return D3DERR_INVALIDCALL;
3970 *ppShader = This->updateStateBlock->pixelShader;
3971 if (NULL != ppShader) {
3972 IWineD3DPixelShader_AddRef(*ppShader);
3974 TRACE("(%p) : returning %p\n", This, *ppShader);
3975 return D3D_OK;
3978 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
3979 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3981 int i;
3982 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
3984 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
3985 iface, dstData, srcData, type, start, count, registersize);
3987 if (type != WINESHADERCNST_NONE) {
3988 if (srcData == NULL || cnt < 0) {
3989 return D3DERR_INVALIDCALL;
3992 CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
3995 for (i = start; i < cnt + start; ++i) {
3996 This->updateStateBlock->changed.pixelShaderConstants[i] = TRUE;
3997 This->updateStateBlock->set.pixelShaderConstants[i] = TRUE;
3998 This->updateStateBlock->pixelShaderConstantT[i] = type;
4001 return D3D_OK;
4004 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4005 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4007 int i;
4008 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4010 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4011 iface, dstData, srcData, type, start, count, registersize);
4013 /* Verify that the requested shader constant was populated with the correct type */
4014 for (i = start; i < cnt + start; ++i) {
4015 if (This->updateStateBlock->pixelShaderConstantT[i] != type) {
4016 TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning D3DERR_INVALIDCALL\n",
4017 This, type, This->updateStateBlock->pixelShaderConstantT[i]);
4018 return D3DERR_INVALIDCALL;
4022 if (dstData == NULL || cnt < 0) {
4023 return D3DERR_INVALIDCALL;
4026 CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
4028 return D3D_OK;
4031 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
4032 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4034 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4035 This->updateStateBlock->pixelShaderConstantB,
4036 pConstantData,
4037 WINESHADERCNST_BOOL,
4038 StartRegister,
4039 BoolCount,
4040 sizeof(*pConstantData));
4043 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
4044 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4046 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4047 pConstantData,
4048 This->updateStateBlock->pixelShaderConstantB,
4049 WINESHADERCNST_BOOL,
4050 StartRegister,
4051 BoolCount,
4052 sizeof(*pConstantData));
4055 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
4056 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4058 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4059 This->updateStateBlock->pixelShaderConstantI,
4060 pConstantData,
4061 WINESHADERCNST_INTEGER,
4062 StartRegister,
4063 Vector4iCount,
4064 4 * sizeof(*pConstantData));
4067 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
4068 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4070 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4071 pConstantData,
4072 This->updateStateBlock->pixelShaderConstantI,
4073 WINESHADERCNST_INTEGER,
4074 StartRegister,
4075 Vector4iCount,
4076 4 * sizeof(*pConstantData));
4079 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
4080 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4082 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4083 This->updateStateBlock->pixelShaderConstantF,
4084 pConstantData,
4085 WINESHADERCNST_FLOAT,
4086 StartRegister,
4087 Vector4fCount,
4088 4 * sizeof(*pConstantData));
4091 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
4092 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4094 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4095 pConstantData,
4096 This->updateStateBlock->pixelShaderConstantF,
4097 WINESHADERCNST_FLOAT,
4098 StartRegister,
4099 Vector4fCount,
4100 4 * sizeof(*pConstantData));
4103 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
4104 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4105 NULL,
4106 NULL,
4107 WINESHADERCNST_NONE,
4108 StartRegister,
4109 VectorNCount,
4113 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
4114 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4115 FIXME("(%p) : stub\n", This);
4116 return D3D_OK;
4119 /*****
4120 * Apply / Get / Set Texture Stage States
4121 * TODO: Verify against dx9 definitions
4122 *****/
4124 /* 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 */
4125 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
4126 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4127 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
4128 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4130 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4132 /* Check that the stage is within limits */
4133 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4134 TRACE("Attempt to access invalid texture rejected\n");
4135 return;
4138 ENTER_GL();
4140 switch (Type) {
4141 case WINED3DTSS_ALPHAOP :
4142 case WINED3DTSS_COLOROP :
4143 /* nothing to do as moved to drawprim for now */
4144 break;
4145 case WINED3DTSS_ADDRESSW :
4146 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
4147 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
4148 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
4150 } else {
4151 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
4152 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
4153 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
4154 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
4156 #endif
4157 case WINED3DTSS_TEXCOORDINDEX :
4159 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
4161 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
4162 one flag, you can still specify an index value, which the system uses to
4163 determine the texture wrapping mode.
4164 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
4165 means use the vertex position (camera-space) as the input texture coordinates
4166 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
4167 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
4168 to the TEXCOORDINDEX value */
4171 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
4173 switch (Value & 0xFFFF0000) {
4174 case D3DTSS_TCI_PASSTHRU:
4175 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
4176 glDisable(GL_TEXTURE_GEN_S);
4177 glDisable(GL_TEXTURE_GEN_T);
4178 glDisable(GL_TEXTURE_GEN_R);
4179 glDisable(GL_TEXTURE_GEN_Q);
4180 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
4181 break;
4183 case D3DTSS_TCI_CAMERASPACEPOSITION:
4184 /* CameraSpacePosition means use the vertex position, transformed to camera space,
4185 as the input texture coordinates for this stage's texture transformation. This
4186 equates roughly to EYE_LINEAR */
4188 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4189 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4190 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4191 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4192 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4194 glMatrixMode(GL_MODELVIEW);
4195 glPushMatrix();
4196 glLoadIdentity();
4197 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4198 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4199 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4200 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4201 glPopMatrix();
4203 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
4204 glEnable(GL_TEXTURE_GEN_S);
4205 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4206 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4207 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4208 glEnable(GL_TEXTURE_GEN_T);
4209 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4210 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4211 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4212 glEnable(GL_TEXTURE_GEN_R);
4213 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4214 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4215 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4217 break;
4219 case D3DTSS_TCI_CAMERASPACENORMAL:
4221 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4222 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4223 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4224 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4225 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4226 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
4228 glMatrixMode(GL_MODELVIEW);
4229 glPushMatrix();
4230 glLoadIdentity();
4231 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4232 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4233 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4234 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4235 glPopMatrix();
4237 glEnable(GL_TEXTURE_GEN_S);
4238 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4239 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4240 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4241 glEnable(GL_TEXTURE_GEN_T);
4242 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4243 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4244 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4245 glEnable(GL_TEXTURE_GEN_R);
4246 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4247 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4248 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4251 break;
4253 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
4255 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4256 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4257 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4258 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4259 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4260 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
4262 glMatrixMode(GL_MODELVIEW);
4263 glPushMatrix();
4264 glLoadIdentity();
4265 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4266 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4267 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4268 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4269 glPopMatrix();
4271 glEnable(GL_TEXTURE_GEN_S);
4272 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4273 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4274 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4275 glEnable(GL_TEXTURE_GEN_T);
4276 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4277 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4278 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4279 glEnable(GL_TEXTURE_GEN_R);
4280 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4281 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4282 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4285 break;
4287 /* Unhandled types: */
4288 default:
4289 /* Todo: */
4290 /* ? disable GL_TEXTURE_GEN_n ? */
4291 glDisable(GL_TEXTURE_GEN_S);
4292 glDisable(GL_TEXTURE_GEN_T);
4293 glDisable(GL_TEXTURE_GEN_R);
4294 glDisable(GL_TEXTURE_GEN_Q);
4295 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
4296 break;
4299 break;
4301 /* Unhandled */
4302 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
4303 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);
4304 break;
4306 case WINED3DTSS_BUMPENVMAT00 :
4307 case WINED3DTSS_BUMPENVMAT01 :
4308 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
4309 break;
4310 case WINED3DTSS_BUMPENVMAT10 :
4311 case WINED3DTSS_BUMPENVMAT11 :
4312 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
4313 break;
4315 case WINED3DTSS_BUMPENVLSCALE :
4316 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4317 break;
4319 case WINED3DTSS_BUMPENVLOFFSET :
4320 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4321 break;
4323 case WINED3DTSS_RESULTARG :
4324 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4325 break;
4327 default:
4328 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
4329 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4332 LEAVE_GL();
4334 return;
4337 /*****
4338 * Get / Set Texture Stage States
4339 * TODO: Verify against dx9 definitions
4340 *****/
4341 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
4342 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4344 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4346 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4348 /* Reject invalid texture units */
4349 if (Stage >= GL_LIMITS(textures)) {
4350 TRACE("Attempt to access invalid texture rejected\n");
4351 return D3DERR_INVALIDCALL;
4354 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
4355 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
4356 This->updateStateBlock->textureState[Stage][Type] = Value;
4358 return D3D_OK;
4361 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4362 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4363 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4364 *pValue = This->updateStateBlock->textureState[Stage][Type];
4365 return D3D_OK;
4368 /*****
4369 * Get / Set Texture
4370 *****/
4371 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4373 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4374 IWineD3DBaseTexture *oldTexture;
4376 oldTexture = This->updateStateBlock->textures[Stage];
4377 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
4379 #if 0 /* TODO: check so vertex textures */
4380 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
4381 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
4382 return D3D_OK;
4384 #endif
4386 /* Reject invalid texture units */
4387 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4388 WARN("Attempt to access invalid texture rejected\n");
4389 return D3DERR_INVALIDCALL;
4392 oldTexture = This->updateStateBlock->textures[Stage];
4393 TRACE("GL_LIMITS %d\n",GL_LIMITS(textures));
4394 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
4396 This->updateStateBlock->set.textures[Stage] = TRUE;
4397 This->updateStateBlock->changed.textures[Stage] = TRUE;
4398 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
4399 This->updateStateBlock->textures[Stage] = pTexture;
4401 /* Handle recording of state blocks */
4402 if (This->isRecordingState) {
4403 TRACE("Recording... not performing anything\n");
4404 return D3D_OK;
4407 /** NOTE: MSDN says that setTexture increases the reference count,
4408 * and the the application nust set the texture back to null (or have a leaky application),
4409 * This means we should pass the refcount up to the parent
4410 *******************************/
4411 if (NULL != This->updateStateBlock->textures[Stage]) {
4412 IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
4415 if (NULL != oldTexture) {
4416 IWineD3DBaseTexture_Release(oldTexture);
4419 return D3D_OK;
4422 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4423 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4424 TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
4426 /* Reject invalid texture units */
4427 if (Stage >= GL_LIMITS(textures)) {
4428 TRACE("Attempt to access invalid texture rejected\n");
4429 return D3DERR_INVALIDCALL;
4431 *ppTexture=This->updateStateBlock->textures[Stage];
4432 if (*ppTexture)
4433 IWineD3DBaseTexture_AddRef(*ppTexture);
4434 else
4435 return D3DERR_INVALIDCALL;
4436 return D3D_OK;
4439 /*****
4440 * Get Back Buffer
4441 *****/
4442 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type,
4443 IWineD3DSurface **ppBackBuffer) {
4444 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4445 IWineD3DSwapChain *swapChain;
4446 HRESULT hr;
4448 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4450 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4451 if (hr == D3D_OK) {
4452 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4453 IWineD3DSwapChain_Release(swapChain);
4454 } else {
4455 *ppBackBuffer = NULL;
4457 return hr;
4460 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4461 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4462 WARN("(%p) : stub, calling idirect3d for now\n", This);
4463 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4466 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
4467 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4468 IWineD3DSwapChain *swapChain;
4469 HRESULT hr;
4471 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4472 if (hr == D3D_OK) {
4473 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4474 IWineD3DSwapChain_Release(swapChain);
4475 } else {
4476 FIXME("(%p) Error getting display mode\n", This);
4478 return hr;
4480 /*****
4481 * Stateblock related functions
4482 *****/
4484 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4485 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4486 IWineD3DStateBlockImpl *object;
4487 TRACE("(%p)", This);
4489 if (This->isRecordingState) {
4490 return D3DERR_INVALIDCALL;
4493 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4494 if (NULL == object ) {
4495 FIXME("(%p)Error allocating memory for stateblock\n", This);
4496 return E_OUTOFMEMORY;
4498 TRACE("(%p) creted object %p\n", This, object);
4499 object->wineD3DDevice= This;
4500 /** FIXME: object->parent = parent; **/
4501 object->parent = NULL;
4502 object->blockType = WINED3DSBT_ALL;
4503 object->ref = 1;
4504 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
4506 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4507 This->updateStateBlock = object;
4508 This->isRecordingState = TRUE;
4510 TRACE("(%p) recording stateblock %p\n",This , object);
4511 return D3D_OK;
4514 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4515 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4517 if (!This->isRecordingState) {
4518 FIXME("(%p) not recording! returning error\n", This);
4519 *ppStateBlock = NULL;
4520 return D3DERR_INVALIDCALL;
4523 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4524 This->isRecordingState = FALSE;
4525 This->updateStateBlock = This->stateBlock;
4526 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4527 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4528 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4529 return D3D_OK;
4532 /*****
4533 * Scene related functions
4534 *****/
4535 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4536 /* At the moment we have no need for any functionality at the beginning
4537 of a scene */
4538 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4539 TRACE("(%p) : stub\n", This);
4540 return D3D_OK;
4543 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4544 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4545 TRACE("(%p)\n", This);
4546 ENTER_GL();
4547 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4548 glFlush();
4549 checkGLcall("glFlush");
4551 TRACE("End Scene\n");
4552 if(This->renderTarget != NULL) {
4554 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4555 IUnknown *targetContainer = NULL;
4556 if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
4557 || D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
4558 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
4559 /** always dirtify for now. we must find a better way to see that surface have been modified
4560 (Modifications should will only occur via draw-primitive, but we do need better locking
4561 switching to render-to-texture should remove the overhead though.
4563 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4564 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
4565 IWineD3DSurface_PreLoad(This->renderTarget);
4566 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4567 IUnknown_Release(targetContainer);
4570 This->sceneEnded = TRUE;
4571 LEAVE_GL();
4572 return D3D_OK;
4575 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4576 CONST RECT* pSourceRect, CONST RECT* pDestRect,
4577 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4578 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4579 IWineD3DSwapChain *swapChain = NULL;
4580 int i;
4581 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4583 TRACE("(%p) Presenting the frame\n", This);
4585 for(i = 0 ; i < swapchains ; i ++) {
4587 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4588 TRACE("presentinng chain %d, %p\n", i, swapChain);
4589 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4590 IWineD3DSwapChain_Release(swapChain);
4593 return D3D_OK;
4596 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4597 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4598 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4600 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4601 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4602 when the depth-buffer format does not contain stencil buffer information, this method fails. */
4603 GLbitfield glMask = 0;
4604 GLboolean old_ztest;
4605 GLfloat old_z_clear_value;
4606 GLint old_stencil_clear_value;
4607 GLfloat old_color_clear_value[4];
4608 unsigned int i;
4609 CONST D3DRECT* curRect;
4611 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4612 Count, pRects, Flags, Z, Stencil);
4614 ENTER_GL();
4616 glEnable(GL_SCISSOR_TEST);
4617 checkGLcall("glEnable GL_SCISSOR_TEST");
4619 if (Count > 0 && pRects) {
4620 curRect = pRects;
4621 } else {
4622 curRect = NULL;
4625 /* Only set the values up once, as they are not changing */
4626 if (Flags & D3DCLEAR_STENCIL) {
4627 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4628 glClearStencil(Stencil);
4629 checkGLcall("glClearStencil");
4630 glMask = glMask | GL_STENCIL_BUFFER_BIT;
4631 glStencilMask(0xFFFFFFFF);
4634 if (Flags & D3DCLEAR_ZBUFFER) {
4635 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4636 glDepthMask(GL_TRUE);
4637 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4638 glClearDepth(Z);
4639 checkGLcall("glClearDepth");
4640 glMask = glMask | GL_DEPTH_BUFFER_BIT;
4643 if (Flags & D3DCLEAR_TARGET) {
4644 TRACE("Clearing screen with glClear to color %lx\n", Color);
4645 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4646 glClearColor(D3DCOLOR_R(Color),
4647 D3DCOLOR_G(Color),
4648 D3DCOLOR_B(Color),
4649 D3DCOLOR_A(Color));
4650 checkGLcall("glClearColor");
4652 /* Clear ALL colors! */
4653 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4654 glMask = glMask | GL_COLOR_BUFFER_BIT;
4657 /* Now process each rect in turn */
4658 for (i = 0; i < Count || i == 0; i++) {
4660 if (curRect) {
4661 /* Note gl uses lower left, width/height */
4662 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4663 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4664 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4665 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4666 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4667 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4668 checkGLcall("glScissor");
4669 } else {
4670 glScissor(This->stateBlock->viewport.X,
4671 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
4672 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4673 This->stateBlock->viewport.Width,
4674 This->stateBlock->viewport.Height);
4675 checkGLcall("glScissor");
4678 /* Clear the selected rectangle (or full screen) */
4679 glClear(glMask);
4680 checkGLcall("glClear");
4682 /* Step to the next rectangle */
4683 if (curRect) curRect = curRect + sizeof(D3DRECT);
4686 /* Restore the old values (why..?) */
4687 if (Flags & D3DCLEAR_STENCIL) {
4688 glClearStencil(old_stencil_clear_value);
4689 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4691 if (Flags & D3DCLEAR_ZBUFFER) {
4692 glDepthMask(old_ztest);
4693 glClearDepth(old_z_clear_value);
4695 if (Flags & D3DCLEAR_TARGET) {
4696 glClearColor(old_color_clear_value[0],
4697 old_color_clear_value[1],
4698 old_color_clear_value[2],
4699 old_color_clear_value[3]);
4700 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4701 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4702 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4703 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4706 glDisable(GL_SCISSOR_TEST);
4707 checkGLcall("glDisable");
4708 LEAVE_GL();
4710 return D3D_OK;
4713 /*****
4714 * Drawing functions
4715 *****/
4716 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4717 UINT PrimitiveCount) {
4719 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4720 This->stateBlock->streamIsUP = FALSE;
4722 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4723 debug_d3dprimitivetype(PrimitiveType),
4724 StartVertex, PrimitiveCount);
4725 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
4726 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
4729 return D3D_OK;
4732 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4733 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4734 D3DPRIMITIVETYPE PrimitiveType,
4735 INT baseVIndex, UINT minIndex,
4736 UINT NumVertices, UINT startIndex, UINT primCount) {
4738 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4739 UINT idxStride = 2;
4740 IWineD3DIndexBuffer *pIB;
4741 D3DINDEXBUFFER_DESC IdxBufDsc;
4743 pIB = This->stateBlock->pIndexData;
4744 This->stateBlock->streamIsUP = FALSE;
4746 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
4747 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4748 minIndex, NumVertices, startIndex, baseVIndex, primCount);
4750 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4751 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4752 idxStride = 2;
4753 } else {
4754 idxStride = 4;
4757 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
4758 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
4760 return D3D_OK;
4763 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4764 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4765 UINT VertexStreamZeroStride) {
4766 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4768 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4769 debug_d3dprimitivetype(PrimitiveType),
4770 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4772 /* release the stream source */
4773 if (This->stateBlock->streamSource[0] != NULL) {
4774 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
4777 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4778 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4779 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4780 This->stateBlock->streamIsUP = TRUE;
4782 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
4783 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
4784 /* stream zero settings set to null at end, as per the msdn
4785 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
4787 This->stateBlock->streamStride[0] = 0;
4788 This->stateBlock->streamSource[0] = NULL;
4790 /*stream zero settings set to null at end, as per the msdn */
4791 return D3D_OK;
4794 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4795 UINT MinVertexIndex, UINT NumVertices,
4796 UINT PrimitiveCount, CONST void* pIndexData,
4797 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4798 UINT VertexStreamZeroStride) {
4799 int idxStride;
4800 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4802 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4803 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4804 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
4805 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4807 if (IndexDataFormat == WINED3DFMT_INDEX16) {
4808 idxStride = 2;
4809 } else {
4810 idxStride = 4;
4813 /* release the stream and index data */
4814 if (This->stateBlock->streamSource[0] != NULL) {
4815 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
4817 if (This->stateBlock->pIndexData) {
4818 IWineD3DIndexBuffer_Release(This->stateBlock->pIndexData);
4821 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4822 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4823 This->stateBlock->streamIsUP = TRUE;
4824 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4826 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
4827 /* stream zero settings set to null at end as per the msdn
4828 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
4831 /* stream zero settings set to null at end as per the msdn */
4832 This->stateBlock->streamSource[0] = NULL;
4833 This->stateBlock->streamStride[0] = 0;
4835 return D3D_OK;
4838 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4839 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
4840 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4841 HRESULT hr = D3D_OK;
4842 D3DRESOURCETYPE sourceType;
4843 D3DRESOURCETYPE destinationType;
4844 int i ,levels;
4846 /* TODO: think about moving the code into IWineD3DBaseTexture */
4848 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
4850 /* verify that the source and destination textures aren't NULL */
4851 if (NULL == pSourceTexture || NULL == pDestinationTexture) {
4852 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning D3DERR_INVALIDCALL\n",
4853 This, pSourceTexture, pDestinationTexture);
4854 hr = D3DERR_INVALIDCALL;
4857 if (pSourceTexture == pDestinationTexture) {
4858 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning D3DERR_INVALIDCALL\n",
4859 This, pSourceTexture, pDestinationTexture);
4860 hr = D3DERR_INVALIDCALL;
4862 /* Verify that the source and destination textures are the same type */
4863 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
4864 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
4866 if (sourceType != destinationType) {
4867 WARN("(%p) Sorce and destination types must match, returning D3DERR_INVALIDCALL\n",
4868 This);
4869 hr = D3DERR_INVALIDCALL;
4872 /* check that both textures have the identical numbers of levels */
4873 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
4874 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning D3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
4875 hr = D3DERR_INVALIDCALL;
4878 if (D3D_OK == hr) {
4880 /* Make sure that the destination texture is loaded */
4881 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
4883 /* Update every surface level of the texture */
4884 levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
4886 switch (sourceType) {
4887 case D3DRTYPE_TEXTURE:
4889 IWineD3DSurface *srcSurface;
4890 IWineD3DSurface *destSurface;
4892 for (i = 0 ; i < levels ; ++i) {
4893 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture, i, &srcSurface);
4894 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
4895 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4896 IWineD3DSurface_Release(srcSurface);
4897 IWineD3DSurface_Release(destSurface);
4898 if (D3D_OK != hr) {
4899 WARN("(%p) : Call to update surface failed\n", This);
4900 return hr;
4904 break;
4905 case D3DRTYPE_CUBETEXTURE:
4907 IWineD3DSurface *srcSurface;
4908 IWineD3DSurface *destSurface;
4909 D3DCUBEMAP_FACES faceType;
4911 for (i = 0 ; i < levels ; ++i) {
4912 /* Update each cube face */
4913 for (faceType = D3DCUBEMAP_FACE_POSITIVE_X; faceType <= D3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
4914 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture, faceType, i, &srcSurface);
4915 if (D3D_OK != hr) {
4916 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4917 } else {
4918 TRACE("Got srcSurface %p\n", srcSurface);
4920 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
4921 if (D3D_OK != hr) {
4922 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4923 } else {
4924 TRACE("Got desrSurface %p\n", destSurface);
4926 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4927 IWineD3DSurface_Release(srcSurface);
4928 IWineD3DSurface_Release(destSurface);
4929 if (D3D_OK != hr) {
4930 WARN("(%p) : Call to update surface failed\n", This);
4931 return hr;
4936 break;
4937 #if 0 /* TODO: Add support for volume textures */
4938 case D3DRTYPE_VOLUMETEXTURE:
4940 IWineD3DVolume srcVolume = NULL;
4941 IWineD3DSurface destVolume = NULL;
4943 for (i = 0 ; i < levels ; ++i) {
4944 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture, i, &srcVolume);
4945 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
4946 hr = IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
4947 IWineD3DVolume_Release(srcSurface);
4948 IWineD3DVolume_Release(destSurface);
4949 if (D3D_OK != hr) {
4950 WARN("(%p) : Call to update volume failed\n", This);
4951 return hr;
4955 break;
4956 #endif
4957 default:
4958 FIXME("(%p) : Unsupported source and destination type\n", This);
4959 hr = D3DERR_INVALIDCALL;
4963 return hr;
4966 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
4967 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
4968 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
4969 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4971 TRACE("(%p) : stub\n", This);
4972 return D3D_OK;
4974 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
4975 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4976 /** TODO: remove remove casts to IWineD3DSurfaceImpl *
4977 * NOTE It may be best to move the code into surface to occomplish this
4978 ****************************************/
4980 WINED3DSURFACE_DESC surfaceDesc;
4981 unsigned int surfaceWidth, surfaceHeight;
4982 glDescriptor *targetGlDescription = NULL;
4983 glDescriptor *surfaceGlDescription = NULL;
4984 IWineD3DSwapChainImpl *container = NULL;
4986 IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
4987 IWineD3DSurface_GetGlDesc(pSurface, &surfaceGlDescription);
4988 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
4990 surfaceDesc.Width = &surfaceWidth;
4991 surfaceDesc.Height = &surfaceHeight;
4992 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
4993 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
4995 /* Ok, I may need to setup some kind of active swapchain reference on the device */
4996 IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
4997 ENTER_GL();
4998 /* TODO: opengl Context switching for swapchains etc... */
4999 if (NULL != container || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
5000 if (NULL != container && (pRenderTarget == container->backBuffer)) {
5001 glReadBuffer(GL_BACK);
5002 vcheckGLcall("glReadBuffer(GL_BACK)");
5003 } else if ((NULL != container && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
5004 glReadBuffer(GL_FRONT);
5005 vcheckGLcall("glReadBuffer(GL_FRONT)");
5006 } else if (pRenderTarget == This->depthStencilBuffer) {
5007 FIXME("Reading of depthstencil not yet supported\n");
5010 glReadPixels(surfaceGlDescription->target,
5011 surfaceGlDescription->level,
5012 surfaceWidth,
5013 surfaceHeight,
5014 surfaceGlDescription->glFormat,
5015 surfaceGlDescription->glType,
5016 (void *)IWineD3DSurface_GetData(pSurface));
5017 vcheckGLcall("glReadPixels(...)");
5018 if(NULL != container ){
5019 IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
5021 } else {
5022 IWineD3DBaseTexture *container;
5023 GLenum textureDimensions = GL_TEXTURE_2D;
5025 if (D3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
5026 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
5027 IWineD3DBaseTexture_Release(container);
5029 /* TODO: 2D -> Cube surface coppies etc.. */
5030 if (surfaceGlDescription->target != textureDimensions) {
5031 FIXME("(%p) : Texture dimension mismatch\n", This);
5033 glEnable(textureDimensions);
5034 vcheckGLcall("glEnable(GL_TEXTURE_...)");
5035 /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
5036 glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
5037 vcheckGLcall("glBindTexture");
5038 glGetTexImage(surfaceGlDescription->target,
5039 surfaceGlDescription->level,
5040 surfaceGlDescription->glFormat,
5041 surfaceGlDescription->glType,
5042 (void *)IWineD3DSurface_GetData(pSurface));
5043 glDisable(textureDimensions);
5044 vcheckGLcall("glDisable(GL_TEXTURE_...)");
5047 LEAVE_GL();
5048 return D3D_OK;
5051 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
5052 IWineD3DSwapChain *swapChain;
5053 HRESULT hr;
5054 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5055 if(hr == D3D_OK) {
5056 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
5057 IWineD3DSwapChain_Release(swapChain);
5059 return hr;
5062 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5063 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5064 /* return a sensible default */
5065 *pNumPasses = 1;
5066 /* TODO: If the window is minimized then validate device should return something other than d3d_ok */
5067 FIXME("(%p) : stub\n", This);
5068 return D3D_OK;
5071 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5072 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5073 int j;
5074 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5075 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5076 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5077 return D3DERR_INVALIDCALL;
5079 for (j = 0; j < 256; ++j) {
5080 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
5081 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5082 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
5083 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5085 TRACE("(%p) : returning\n", This);
5086 return D3D_OK;
5089 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5090 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5091 int j;
5092 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5093 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5094 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5095 return D3DERR_INVALIDCALL;
5097 for (j = 0; j < 256; ++j) {
5098 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
5099 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5100 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
5101 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5103 TRACE("(%p) : returning\n", This);
5104 return D3D_OK;
5107 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5108 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5109 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5110 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5111 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5112 return D3DERR_INVALIDCALL;
5114 /*TODO: stateblocks */
5115 This->currentPalette = PaletteNumber;
5116 TRACE("(%p) : returning\n", This);
5117 return D3D_OK;
5120 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
5121 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5122 if (PaletteNumber == NULL) {
5123 WARN("(%p) : returning Invalid Call\n", This);
5124 return D3DERR_INVALIDCALL;
5126 /*TODO: stateblocks */
5127 *PaletteNumber = This->currentPalette;
5128 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
5129 return D3D_OK;
5132 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
5133 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5134 static BOOL showFixmes = TRUE;
5135 if (showFixmes) {
5136 FIXME("(%p) : stub\n", This);
5137 showFixmes = FALSE;
5140 This->softwareVertexProcessing = bSoftware;
5141 return D3D_OK;
5145 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
5146 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5147 static BOOL showFixmes = TRUE;
5148 if (showFixmes) {
5149 FIXME("(%p) : stub\n", This);
5150 showFixmes = FALSE;
5152 return This->softwareVertexProcessing;
5156 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
5157 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5158 IWineD3DSwapChain *swapChain;
5159 HRESULT hr;
5161 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
5163 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5164 if(hr == D3D_OK){
5165 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
5166 IWineD3DSwapChain_Release(swapChain);
5167 }else{
5168 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
5170 return hr;
5174 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
5175 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5176 static BOOL showfixmes = TRUE;
5177 if(nSegments != 0.0f) {
5178 if( showfixmes) {
5179 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
5180 showfixmes = FALSE;
5183 return D3D_OK;
5186 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
5187 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5188 static BOOL showfixmes = TRUE;
5189 if( showfixmes) {
5190 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
5191 showfixmes = FALSE;
5193 return 0.0f;
5196 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
5197 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5198 /** TODO: remove casts to IWineD3DSurfaceImpl
5199 * NOTE: move code to surface to accomplish this
5200 ****************************************/
5201 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
5202 int srcWidth, srcHeight;
5203 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
5204 WINED3DFORMAT destFormat, srcFormat;
5205 UINT destSize;
5206 int destLeft, destTop;
5207 D3DPOOL srcPool, destPool;
5208 int offset = 0;
5209 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
5210 glDescriptor *glDescription = NULL;
5211 GLenum textureDimensions = GL_TEXTURE_2D;
5212 IWineD3DBaseTexture *baseTexture;
5214 WINED3DSURFACE_DESC winedesc;
5216 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
5217 memset(&winedesc, 0, sizeof(winedesc));
5218 winedesc.Width = &srcSurfaceWidth;
5219 winedesc.Height = &srcSurfaceHeight;
5220 winedesc.Pool = &srcPool;
5221 winedesc.Format = &srcFormat;
5223 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5225 winedesc.Width = &destSurfaceWidth;
5226 winedesc.Height = &destSurfaceHeight;
5227 winedesc.Pool = &destPool;
5228 winedesc.Format = &destFormat;
5229 winedesc.Size = &destSize;
5231 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5233 if(srcPool != D3DPOOL_SYSTEMMEM || destPool != D3DPOOL_DEFAULT){
5234 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning D3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
5235 return D3DERR_INVALIDCALL;
5238 if (destFormat == WINED3DFMT_UNKNOWN) {
5239 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5240 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5242 /* Get the update surface description */
5243 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5246 /* Make sure the surface is loaded and up to date */
5247 IWineD3DSurface_PreLoad(pDestinationSurface);
5249 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
5251 ENTER_GL();
5253 /* this needs to be done in lines if the sourceRect != the sourceWidth */
5254 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
5255 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
5256 destLeft = pDestPoint ? pDestPoint->x : 0;
5257 destTop = pDestPoint ? pDestPoint->y : 0;
5260 /* This function doesn't support compressed textures
5261 the pitch is just bytesPerPixel * width */
5262 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
5263 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
5264 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
5265 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
5267 /* TODO DXT formats */
5269 if(pSourceRect != NULL && pSourceRect->top != 0){
5270 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
5272 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
5273 ,This
5274 ,glDescription->level
5275 ,destLeft
5276 ,destTop
5277 ,srcWidth
5278 ,srcHeight
5279 ,glDescription->glFormat
5280 ,glDescription->glType
5281 ,IWineD3DSurface_GetData(pSourceSurface)
5284 /* Sanity check */
5285 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
5287 /* need to lock the surface to get the data */
5288 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5291 /* TODO: Cube and volume support */
5292 if(rowoffset != 0){
5293 /* not a whole row so we have to do it a line at a time */
5294 int j;
5296 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
5297 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5299 for(j = destTop ; j < (srcHeight + destTop) ; j++){
5301 glTexSubImage2D(glDescription->target
5302 ,glDescription->level
5303 ,destLeft
5305 ,srcWidth
5307 ,glDescription->glFormat
5308 ,glDescription->glType
5309 ,data /* could be quicker using */
5311 data += rowoffset;
5314 } else { /* Full width, so just write out the whole texture */
5316 if (WINED3DFMT_DXT1 == destFormat ||
5317 WINED3DFMT_DXT2 == destFormat ||
5318 WINED3DFMT_DXT3 == destFormat ||
5319 WINED3DFMT_DXT4 == destFormat ||
5320 WINED3DFMT_DXT5 == destFormat) {
5321 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
5322 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
5323 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
5324 FIXME("Updating part of a compressed texture is not supported at the moment\n");
5325 } if (destFormat != srcFormat) {
5326 FIXME("Updating mixed format compressed texture is not curretly support\n");
5327 } else {
5328 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
5329 glDescription->level,
5330 glDescription->glFormatInternal,
5331 srcWidth,
5332 srcHeight,
5334 destSize,
5335 IWineD3DSurface_GetData(pSourceSurface));
5337 } else {
5338 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
5342 } else {
5343 if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
5345 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
5346 to repack the data from pow2Width/Height to expected Width,Height, this makes the
5347 data returned by GetData non-power2 width/height with hardware non-power2
5348 pow2Width/height are set to surface width height, repacking isn't needed so it
5349 doesn't matter which function gets called. */
5350 glTexSubImage2D(glDescription->target
5351 ,glDescription->level
5352 ,destLeft
5353 ,destTop
5354 ,srcWidth
5355 ,srcHeight
5356 ,glDescription->glFormat
5357 ,glDescription->glType
5358 ,IWineD3DSurface_GetData(pSourceSurface)
5360 } else {
5362 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
5363 glTexSubImage2D(glDescription->target
5364 ,glDescription->level
5365 ,destLeft
5366 ,destTop
5367 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
5368 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
5369 ,glDescription->glFormat
5370 ,glDescription->glType
5371 ,IWineD3DSurface_GetData(pSourceSurface)
5377 checkGLcall("glTexSubImage2D");
5379 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
5380 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
5381 * surface bigger than it needs to be hmm.. */
5382 if (D3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
5383 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
5384 IWineD3DBaseTexture_Release(baseTexture);
5387 glDisable(textureDimensions); /* This needs to be managed better.... */
5388 LEAVE_GL();
5390 return D3D_OK;
5393 /* Implementation details at http://developer.nvidia.com/attach/6494
5395 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
5396 hmm.. no longer supported use
5397 OpenGL evaluators or tessellate surfaces within your application.
5400 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
5401 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
5402 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5403 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
5404 FIXME("(%p) : Stub\n", This);
5405 return D3D_OK;
5409 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
5410 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
5411 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5412 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
5413 FIXME("(%p) : Stub\n", This);
5414 return D3D_OK;
5417 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5418 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5419 TRACE("(%p) Handle(%d)\n", This, Handle);
5420 FIXME("(%p) : Stub\n", This);
5421 return D3D_OK;
5424 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
5425 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
5426 fill a surface with a block of color! */
5427 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5428 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
5429 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
5430 IWineD3DSwapChainImpl *container = NULL;
5431 BOOL isRenderTarget = FALSE;
5432 unsigned int width, height;
5433 unsigned int top, left;
5434 unsigned int u, v;
5435 DWORD *data;
5436 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
5438 if (surface->resource.pool != D3DPOOL_DEFAULT) {
5439 FIXME("call to colorfill with non D3DPOOL_DEFAULT surface\n");
5440 return D3DERR_INVALIDCALL;
5443 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
5444 if (D3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
5445 if (D3DUSAGE_RENDERTARGET & surface->resource.usage) {
5446 /* TODO: make sure we set everything back to the way it was, and context management!
5447 glGetIntegerv(GL_READ_BUFFER, &prev_read);
5448 vcheckGLcall("glIntegerv");
5449 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
5450 vcheckGLcall("glIntegerv");
5452 TRACE("Color fill to render targets may cause some graphics issues\n");
5453 if (pSurface == container->frontBuffer) {
5454 glDrawBuffer(GL_FRONT);
5455 } else {
5456 glDrawBuffer(GL_BACK);
5458 } else {
5459 if (D3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
5460 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld\n", surface, surface->resource.usage);
5461 } else {
5462 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
5464 if (container != NULL) {
5465 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5467 /* we can use GL_STENCIL_INDEX etc...*/
5468 return D3D_OK;
5470 if (container != NULL) {
5471 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5473 isRenderTarget = TRUE;
5475 /* TODO: drawing to GL_FRONT and GL_BACK */
5476 /* TODO: see if things can be speeded up by using the correct
5477 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
5478 if (pRect == NULL) {
5479 top = 0;
5480 left = 0;
5481 width = surface->currentDesc.Width;
5482 height = surface->currentDesc.Height;
5483 } else {
5484 left = pRect->x1;
5485 top = pRect->y1;
5486 width = pRect->x2 - left;
5487 height = pRect->y2 - top;
5490 data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
5491 /* Create a 'line' of color color, in the correct format for the surface */
5492 for (u = 0 ; u < width ; u ++) {
5493 data[u] = color;
5496 ENTER_GL();
5497 if (isRenderTarget == FALSE) {
5498 glDescriptor *glDesc;
5499 IWineD3DSurface_PreLoad(pSurface);
5501 /* draw a block of the coloured line on the sufrace */
5502 IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
5503 for (v = 0 ; v< height;v++) {
5504 glTexSubImage2D(glDesc->target
5505 ,glDesc->level /* level */
5506 ,left
5507 ,top + v
5508 ,width
5509 ,1 /* height */
5510 ,GL_RGBA
5511 ,GL_UNSIGNED_BYTE
5512 ,data
5515 checkGLcall("glTexSubImage2D");
5516 /* clean up */
5517 glDisable(glDesc->target);
5518 } else {
5519 /** FIXME: Using GLClear may be faster **/
5520 glRasterPos2i(left, top);
5521 glPixelZoom((float)width ,(float)height);
5522 glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
5523 checkGLcall("glDrawPixels");
5525 HeapFree(GetProcessHeap(), 0, data);
5526 LEAVE_GL();
5527 return D3D_OK;
5531 /* rendertarget and deptth stencil functions */
5532 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
5533 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5535 /* FIXME: Implelent RenderTargetIndex >0 */
5536 if(RenderTargetIndex > 0)
5537 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
5539 *ppRenderTarget = This->renderTarget;
5540 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
5541 /* Note inc ref on returned surface */
5542 if(*ppRenderTarget != NULL)
5543 IWineD3DSurface_AddRef(*ppRenderTarget);
5544 return D3D_OK;
5547 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5548 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5549 *ppZStencilSurface = This->depthStencilBuffer;
5550 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
5552 if(*ppZStencilSurface != NULL) {
5553 /* Note inc ref on returned surface */
5554 IWineD3DSurface_AddRef(*ppZStencilSurface);
5556 return D3D_OK;
5559 /* internal static helper functions */
5560 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5561 IWineD3DSurface *RenderSurface);
5563 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5564 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5565 HRESULT hr = D3D_OK;
5566 WINED3DVIEWPORT viewport;
5568 TRACE("(%p) Swapping rendertarget\n",This);
5569 if (RenderTargetIndex > 0) {
5570 FIXME("(%p) Render targets other than the first are not supported\n",This);
5571 RenderTargetIndex = 0;
5574 /* MSDN says that null disables the render target
5575 but a device must always be associated with a render target
5576 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5578 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5579 for more details
5581 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5582 FIXME("Trying to set render target 0 to NULL\n");
5583 return D3DERR_INVALIDCALL;
5585 /* TODO: replace Impl* usage with interface usage */
5586 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & D3DUSAGE_RENDERTARGET) {
5587 FIXME("(%p)Trying to set the render target to a surface(%p) that wasn't created with a usage of D3DUSAGE_RENDERTARGET\n",This ,pRenderTarget);
5588 return D3DERR_INVALIDCALL;
5590 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
5591 * builds, but I think wine counts as a 'debug' build for now.
5592 ******************************/
5593 /* If we are trying to set what we already have, don't bother */
5594 if (pRenderTarget == This->renderTarget) {
5595 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5596 } else {
5597 /* Otherwise, set the render target up */
5599 if (FALSE == This->sceneEnded) {
5600 IWineD3DDevice_EndScene(iface);
5602 TRACE("clearing renderer\n");
5603 /* IWineD3DDeviceImpl_CleanRender(iface); */
5604 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5605 depending on the renter target implementation being used.
5606 A shared context implementation will share all buffers between all rendertargets (including swapchains),
5607 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5608 stencil buffer and incure an extra memory overhead */
5609 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
5612 if (SUCCEEDED(hr)) {
5613 /* Finally, reset the viewport as the MSDN states. */
5614 /* TODO: Replace impl usage */
5615 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
5616 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
5617 viewport.X = 0;
5618 viewport.Y = 0;
5619 viewport.MaxZ = 1.0f;
5620 viewport.MinZ = 0.0f;
5621 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
5622 } else {
5623 FIXME("Unknown error setting the render target\n");
5625 This->sceneEnded = FALSE;
5626 return hr;
5629 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
5630 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5631 HRESULT hr = D3D_OK;
5632 IWineD3DSurface *tmp;
5634 TRACE("(%p) Swapping z-buffer\n",This);
5636 if (pNewZStencil == This->stencilBufferTarget) {
5637 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5638 } else {
5639 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5640 * depending on the renter target implementation being used.
5641 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5642 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5643 * stencil buffer and incure an extra memory overhead
5644 ******************************************************/
5647 tmp = This->stencilBufferTarget;
5648 This->stencilBufferTarget = pNewZStencil;
5649 /* should we be calling the parent or the wined3d surface? */
5650 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
5651 if (NULL != tmp) IWineD3DSurface_Release(tmp);
5652 hr = D3D_OK;
5653 /** TODO: glEnable/glDisable on depth/stencil depending on
5654 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
5655 **********************************************************/
5658 return hr;
5662 #ifdef GL_VERSION_1_3
5663 /* Internal functions not in DirectX */
5664 /** TODO: move this off to the opengl context manager
5665 *(the swapchain doesn't need to know anything about offscreen rendering!)
5666 ****************************************************/
5668 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
5670 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5672 TRACE("(%p), %p\n", This, swapchain);
5674 if (swapchain->win != swapchain->drawable) {
5675 /* Set everything back the way it ws */
5676 swapchain->render_ctx = swapchain->glCtx;
5677 swapchain->drawable = swapchain->win;
5679 return D3D_OK;
5682 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
5683 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
5684 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5685 int i;
5686 unsigned int width;
5687 unsigned int height;
5688 WINED3DFORMAT format;
5689 WINED3DSURFACE_DESC surfaceDesc;
5690 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5691 surfaceDesc.Width = &width;
5692 surfaceDesc.Height = &height;
5693 surfaceDesc.Format = &format;
5694 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5695 *context = NULL;
5696 /* I need a get width/height function (and should do something with the format) */
5697 for (i = 0; i < CONTEXT_CACHE; ++i) {
5698 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
5699 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
5700 the pSurface can be set to 0 allowing it to be reused from cache **/
5701 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
5702 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
5703 *context = &This->contextCache[i];
5704 break;
5706 if (This->contextCache[i].Width == 0) {
5707 This->contextCache[i].pSurface = pSurface;
5708 This->contextCache[i].Width = width;
5709 This->contextCache[i].Height = height;
5710 *context = &This->contextCache[i];
5711 break;
5714 if (i == CONTEXT_CACHE) {
5715 int minUsage = 0x7FFFFFFF; /* MAX_INT */
5716 glContext *dropContext = 0;
5717 for (i = 0; i < CONTEXT_CACHE; i++) {
5718 if (This->contextCache[i].usedcount < minUsage) {
5719 dropContext = &This->contextCache[i];
5720 minUsage = This->contextCache[i].usedcount;
5723 /* clean up the context (this doesn't work for ATI at the moment */
5724 #if 0
5725 glXDestroyContext(swapchain->display, dropContext->context);
5726 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
5727 #endif
5728 FIXME("Leak\n");
5729 dropContext->Width = 0;
5730 dropContext->pSurface = pSurface;
5731 *context = dropContext;
5732 } else {
5733 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
5734 for (i = 0; i < CONTEXT_CACHE; i++) {
5735 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
5739 if (*context != NULL)
5740 return D3D_OK;
5741 else
5742 return E_OUTOFMEMORY;
5744 #endif
5746 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
5747 * the functionality needs splitting up so that we don't do more than we should do.
5748 * this only seems to impact performance a little.
5749 ******************************/
5750 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5751 IWineD3DSurface *RenderSurface) {
5752 HRESULT ret = D3DERR_INVALIDCALL;
5755 * Currently only active for GLX >= 1.3
5756 * for others versions we'll have to use GLXPixmaps
5758 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
5759 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
5760 * so only check OpenGL version
5761 * ..........................
5762 * I don't believe that it is a problem with NVidia headers,
5763 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
5764 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
5765 * ATI Note:
5766 * Your application will report GLX version 1.2 on glXQueryVersion.
5767 * However, it is safe to call the GLX 1.3 functions as described below.
5769 #if defined(GL_VERSION_1_3)
5771 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5772 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
5773 IWineD3DSurface *tmp;
5774 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
5775 GLXFBConfig* cfgs = NULL;
5776 int nCfgs = 0;
5777 int attribs[256];
5778 int nAttribs = 0;
5779 IWineD3DSwapChain *currentSwapchain;
5780 IWineD3DSwapChainImpl *swapchain;
5781 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
5782 * but switch them off if the StencilSurface is set to NULL
5783 ** *********************************************************/
5784 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
5785 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
5787 /**TODO:
5788 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
5789 it StencilSurface != NULL && zBufferTarget == NULL switch it on
5792 #define PUSH1(att) attribs[nAttribs++] = (att);
5793 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
5795 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
5797 /** TODO: remove the reff to Impl (context manager should fix this!) **/
5798 IWineD3DSwapChainImpl *impSwapChain;
5799 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
5800 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
5801 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
5804 ENTER_GL();
5806 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
5807 PUSH2(GLX_X_RENDERABLE, TRUE);
5808 PUSH2(GLX_DOUBLEBUFFER, TRUE);
5809 TRACE("calling makeglcfg\n");
5810 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
5811 PUSH1(None);
5813 TRACE("calling chooseFGConfig\n");
5814 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5815 attribs, &nCfgs);
5817 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
5818 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
5819 why we failed and only show this message once! */
5820 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"); /**/
5821 nAttribs = 0;
5822 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
5823 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
5824 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
5825 PUSH2(GLX_DOUBLEBUFFER, FALSE);
5826 TRACE("calling makeglcfg\n");
5827 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
5828 PUSH1(None);
5829 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5830 attribs, &nCfgs);
5833 if (NULL != cfgs) {
5834 #ifdef EXTRA_TRACES
5835 int i;
5836 for (i = 0; i < nCfgs; ++i) {
5837 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
5838 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
5839 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
5842 if (NULL != This->renderTarget) {
5843 glFlush();
5844 vcheckGLcall("glFlush");
5845 /** This is only useful if the old render target was a swapchain,
5846 * we need to supercede this with a function that displays
5847 * the current buffer on the screen. This is easy to do in glx1.3 but
5848 * we need to do copy-write pixels in glx 1.2.
5849 ************************************************/
5850 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
5852 printf("Hit Enter to get next frame ...\n");
5853 getchar();
5855 #endif
5858 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&currentSwapchain) != D3D_OK) {
5859 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
5860 IWineD3DDevice_GetSwapChain(iface, 0, &currentSwapchain);
5864 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
5865 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
5866 **********************************************************************/
5867 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == D3D_OK) {
5868 /* We also need to make sure that the lights &co are also in the context of the swapchains */
5869 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
5870 TRACE("making swapchain active\n");
5871 if (RenderSurface != This->renderTarget) {
5872 if (RenderSurface == swapchain->backBuffer) {
5873 } else {
5874 /* This could be flagged so that some operations work directly with the front buffer */
5875 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
5877 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
5878 == False) {
5879 TRACE("Error in setting current context: context %p drawable %ld !\n",
5880 impSwapChain->glCtx, impSwapChain->win);
5883 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5885 checkGLcall("glXMakeContextCurrent");
5887 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5889 else if (pbuffer_support == TRUE && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
5891 /** ********************************************************************
5892 * This is a quickly hacked out implementation of offscreen textures.
5893 * It will work in most cases but there may be problems if the client
5894 * modifies the texture directly, or expects the contents of the rendertarget
5895 * to be persistent.
5897 * There are some real speed vs compatibility issues here:
5898 * we should really use a new context for every texture, but that eats ram.
5899 * we should also be restoring the texture to the pbuffer but that eats CPU
5900 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
5901 * but if this means reusing the display backbuffer then we need to make sure that
5902 * states are correctly preserved.
5903 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
5904 * and gain a good performance increase at the cost of compatibility.
5905 * I would suggest that, when this is the case, a user configurable flag be made
5906 * available, allowing the user to choose the best emulated experience for them.
5907 *********************************************************************/
5909 XVisualInfo *visinfo;
5910 glContext *newContext;
5912 /* Here were using a shared context model */
5913 if (D3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
5914 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5917 /* If the context doesn't exist then create a new one */
5918 /* TODO: This should really be part of findGlContext */
5919 if (NULL == newContext->context) {
5921 TRACE("making new buffer\n");
5922 nAttribs = 0;
5923 PUSH2(GLX_PBUFFER_WIDTH, newContext->Width);
5924 PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
5925 PUSH1(None);
5927 newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
5929 /** ****************************************
5930 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
5931 *they note:
5932 * In future releases, we may provide the calls glXCreateNewContext,
5933 * glXQueryDrawable and glXMakeContextCurrent.
5934 * so until then we have to use glXGetVisualFromFBConfig &co..
5935 ********************************************/
5938 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
5939 if (!visinfo) {
5940 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
5941 } else {
5942 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
5943 XFree(visinfo);
5946 if (NULL == newContext || NULL == newContext->context) {
5947 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5948 } else {
5949 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
5950 if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
5951 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
5954 /* Clean up the old context */
5955 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5956 /* Set the current context of the swapchain to the new context */
5957 impSwapChain->drawable = newContext->drawable;
5958 impSwapChain->render_ctx = newContext->context;
5962 #if 1 /* Apply the stateblock to the new context
5963 FIXME: This is a bit of a hack, each context should know it's own state,
5964 the directX current directX state should then be applied to the context */
5966 BOOL oldRecording;
5967 IWineD3DStateBlockImpl *oldUpdateStateBlock;
5968 oldUpdateStateBlock = This->updateStateBlock;
5969 oldRecording= This->isRecordingState;
5970 This->isRecordingState = FALSE;
5971 This->updateStateBlock = This->stateBlock;
5972 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
5974 This->isRecordingState = oldRecording;
5975 This->updateStateBlock = oldUpdateStateBlock;
5977 #endif
5980 /* clean up the current rendertargets swapchain (if it belonged to one) */
5981 if (currentSwapchain != NULL) {
5982 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
5985 /* Were done with the opengl context management, setup the rendertargets */
5987 tmp = This->renderTarget;
5988 This->renderTarget = RenderSurface;
5989 IWineD3DSurface_AddRef(This->renderTarget);
5990 IWineD3DSurface_Release(tmp);
5995 DWORD value;
5996 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
5997 /* Check that the container is not a swapchain member */
5999 IWineD3DSwapChain *tmpSwapChain;
6000 if (D3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
6001 This->renderUpsideDown = TRUE;
6002 }else{
6003 This->renderUpsideDown = FALSE;
6004 IWineD3DSwapChain_Release(tmpSwapChain);
6006 /* Force updating the cull mode */
6007 TRACE("setting render state\n");
6008 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
6009 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
6011 /* Force updating projection matrix */
6012 This->last_was_rhw = FALSE;
6013 This->proj_valid = FALSE;
6016 ret = D3D_OK;
6018 if (cfgs != NULL) {
6019 XFree(cfgs);
6020 } else {
6021 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
6022 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
6025 #undef PUSH1
6026 #undef PUSH2
6027 if ( NULL != impSwapChain) {
6028 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
6030 LEAVE_GL();
6032 #endif
6033 return ret;
6036 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
6037 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
6038 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6039 /* TODO: the use of Impl is deprecated. */
6040 /* some basic validation checks */
6041 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
6043 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
6045 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
6046 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
6047 return D3DERR_INVALIDCALL;
6049 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
6050 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
6051 return D3DERR_INVALIDCALL;
6053 /* TODO: make the cursor 'real' */
6055 This->xHotSpot = XHotSpot;
6056 This->yHotSpot = YHotSpot;
6058 return D3D_OK;
6061 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
6062 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6063 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
6065 This->xScreenSpace = XScreenSpace;
6066 This->yScreenSpace = YScreenSpace;
6068 return;
6072 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
6073 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6074 TRACE("(%p) : visible(%d)\n", This, bShow);
6076 This->bCursorVisible = bShow;
6078 return D3D_OK;
6081 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
6082 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6083 TRACE("(%p) : state (%lu)\n", This, This->state);
6084 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
6085 switch (This->state) {
6086 case D3D_OK:
6087 return D3D_OK;
6088 case D3DERR_DEVICELOST:
6090 ResourceList *resourceList = This->resources;
6091 while (NULL != resourceList) {
6092 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == D3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
6093 return D3DERR_DEVICENOTRESET;
6094 resourceList = resourceList->next;
6096 return D3DERR_DEVICELOST;
6098 case D3DERR_DRIVERINTERNALERROR:
6099 return D3DERR_DRIVERINTERNALERROR;
6102 /* Unknown state */
6103 return D3DERR_DRIVERINTERNALERROR;
6107 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
6108 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6109 /** FIXME: Resource tracking needs to be done,
6110 * The closes we can do to this is set the priorities of all managed textures low
6111 * and then reset them.
6112 ***********************************************************/
6113 FIXME("(%p) : stub\n", This);
6114 return D3D_OK;
6117 HRESULT WINAPI IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
6118 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6119 /** FIXME: Resource trascking needs to be done.
6120 * in effect this pulls all non only default
6121 * textures out of video memory and deletes all glTextures (glDeleteTextures)
6122 * and should clear down the context and set it up according to pPresentationParameters
6123 ***********************************************************/
6124 FIXME("(%p) : stub\n", This);
6125 return D3D_OK;
6128 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
6129 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6130 /** FIXME: always true at the moment **/
6131 if(bEnableDialogs == FALSE) {
6132 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
6134 return D3D_OK;
6138 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
6139 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6141 FIXME("(%p) : stub\n", This);
6142 /* Setup some reasonable defaults */
6143 pParameters->AdapterOrdinal = 0; /* always for now */
6144 pParameters->DeviceType = D3DDEVTYPE_HAL; /* always for now */
6145 pParameters->hFocusWindow = 0;
6146 pParameters->BehaviorFlags =0;
6147 return D3D_OK;
6150 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
6151 IWineD3DSwapChain *swapchain;
6152 HRESULT hrc = D3D_OK;
6154 TRACE("Relaying to swapchain\n");
6156 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
6157 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (D3DGAMMARAMP *)pRamp);
6158 IWineD3DSwapChain_Release(swapchain);
6160 return;
6163 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
6164 IWineD3DSwapChain *swapchain;
6165 HRESULT hrc = D3D_OK;
6167 TRACE("Relaying to swapchain\n");
6169 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
6170 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
6171 IWineD3DSwapChain_Release(swapchain);
6173 return;
6177 /** ********************************************************
6178 * Notification functions
6179 ** ********************************************************/
6180 /** This function must be called in the release of a resource when ref == 0,
6181 * the contents of resource must still be correct,
6182 * any handels to other resource held by the caller must be closed
6183 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
6184 *****************************************************/
6185 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6186 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6187 ResourceList* resourceList;
6189 TRACE("(%p) : resource %p\n", This, resource);
6190 #if 0
6191 EnterCriticalSection(&resourceStoreCriticalSection);
6192 #endif
6193 /* add a new texture to the frot of the linked list */
6194 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
6195 resourceList->resource = resource;
6197 /* Get the old head */
6198 resourceList->next = This->resources;
6200 This->resources = resourceList;
6201 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
6203 #if 0
6204 LeaveCriticalSection(&resourceStoreCriticalSection);
6205 #endif
6206 return;
6209 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6210 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6211 ResourceList* resourceList = NULL;
6212 ResourceList* previousResourceList = NULL;
6214 TRACE("(%p) : resource %p\n", This, resource);
6216 #if 0
6217 EnterCriticalSection(&resourceStoreCriticalSection);
6218 #endif
6219 resourceList = This->resources;
6221 while (resourceList != NULL) {
6222 if(resourceList->resource == resource) break;
6223 previousResourceList = resourceList;
6224 resourceList = resourceList->next;
6227 if (resourceList == NULL) {
6228 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
6229 #if 0
6230 LeaveCriticalSection(&resourceStoreCriticalSection);
6231 #endif
6232 return;
6233 } else {
6234 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
6236 /* make sure we don't leave a hole in the list */
6237 if (previousResourceList != NULL) {
6238 previousResourceList->next = resourceList->next;
6239 } else {
6240 This->resources = resourceList->next;
6243 #if 0
6244 LeaveCriticalSection(&resourceStoreCriticalSection);
6245 #endif
6246 return;
6250 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
6251 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6252 int counter;
6254 TRACE("(%p) : resource %p\n", This, resource);
6255 switch(IWineD3DResource_GetType(resource)){
6256 case D3DRTYPE_SURFACE:
6257 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
6258 break;
6259 case D3DRTYPE_TEXTURE:
6260 case D3DRTYPE_CUBETEXTURE:
6261 case D3DRTYPE_VOLUMETEXTURE:
6262 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
6263 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6264 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6265 This->stateBlock->textures[counter] = NULL;
6267 if (This->updateStateBlock != This->stateBlock ){
6268 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6269 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6270 This->updateStateBlock->textures[counter] = NULL;
6274 break;
6275 case D3DRTYPE_VOLUME:
6276 /* TODO: nothing really? */
6277 break;
6278 case D3DRTYPE_VERTEXBUFFER:
6279 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
6281 int streamNumber;
6282 TRACE("Cleaning up stream pointers\n");
6284 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
6285 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
6286 FINDOUT: should changes.streamSource[StreamNumber] be set ?
6288 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6289 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
6290 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
6291 This->updateStateBlock->streamSource[streamNumber] = 0;
6292 /* Set changed flag? */
6295 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) */
6296 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
6297 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
6298 This->stateBlock->streamSource[streamNumber] = 0;
6301 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
6302 else { /* This shouldn't happen */
6303 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
6305 #endif
6309 break;
6310 case D3DRTYPE_INDEXBUFFER:
6311 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
6312 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6313 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6314 This->updateStateBlock->pIndexData = NULL;
6317 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
6318 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6319 This->stateBlock->pIndexData = NULL;
6323 break;
6324 default:
6325 FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
6326 break;
6330 /* Remove the resoruce from the resourceStore */
6331 IWineD3DDeviceImpl_RemoveResource(iface, resource);
6333 TRACE("Resource released\n");
6338 /** This function is to be called by the swapchain when it is released and it's ref = 0
6339 *****************************************************/
6340 void WINAPI IWineD3DDeviceImpl_SwapChainReleased(IWineD3DDevice *iface, IWineD3DSwapChain *swapChain){
6341 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6342 SwapChainList **nextSwapchain;
6343 nextSwapchain = &This->swapchains;
6345 /* Check to see if the swapchian is being used as the render target */
6346 if (This->renderTarget != NULL) {
6347 IWineD3DSurface *swapchainBackBuffer;
6349 IWineD3DSwapChain_GetBackBuffer(swapChain, 0 ,( D3DBACKBUFFER_TYPE) 0, &swapchainBackBuffer);
6350 if (This->renderTarget == swapchainBackBuffer) {
6351 /* Don't know what to do, so warn and carry on as usual (which in this case leaves the renderterget in limbo) */
6352 FIXME("Atempting to release a swapchain that is currently beuing used as a render target, behaviour is undefined\n");
6356 /* Go through the swapchain list and try to find the swapchain being released */
6357 while(*nextSwapchain != NULL && (*nextSwapchain)->swapchain != swapChain) {
6358 nextSwapchain = &(*nextSwapchain)->next;
6361 /* Check to see if we found the swapchain */
6362 if (NULL != *nextSwapchain) {
6363 /* We found the swapchain so remove it from the list */
6364 TRACE("(%p) releasing swapchain(%p)\n", iface, swapChain);
6365 HeapFree(GetProcessHeap(), 0 , *nextSwapchain);
6366 *nextSwapchain = (*nextSwapchain)->next;
6367 } else {
6368 /* We didn't find the swapchain on the list, this can only heppen because of a programming error in wined3d */
6369 FIXME("(%p) Attempting to release a swapchain (%p) that hasn't been stored\n", iface, swapChain);
6372 TRACE("swapchain (%p) released\n", swapChain);
6373 return;
6376 /**********************************************************
6377 * IWineD3DDevice VTbl follows
6378 **********************************************************/
6380 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
6382 /*** IUnknown methods ***/
6383 IWineD3DDeviceImpl_QueryInterface,
6384 IWineD3DDeviceImpl_AddRef,
6385 IWineD3DDeviceImpl_Release,
6386 /*** IWineD3DDevice methods ***/
6387 IWineD3DDeviceImpl_GetParent,
6388 /*** Creation methods**/
6389 IWineD3DDeviceImpl_CreateVertexBuffer,
6390 IWineD3DDeviceImpl_CreateIndexBuffer,
6391 IWineD3DDeviceImpl_CreateStateBlock,
6392 IWineD3DDeviceImpl_CreateSurface,
6393 IWineD3DDeviceImpl_CreateTexture,
6394 IWineD3DDeviceImpl_CreateVolumeTexture,
6395 IWineD3DDeviceImpl_CreateVolume,
6396 IWineD3DDeviceImpl_CreateCubeTexture,
6397 IWineD3DDeviceImpl_CreateQuery,
6398 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
6399 IWineD3DDeviceImpl_CreateVertexDeclaration,
6400 IWineD3DDeviceImpl_CreateVertexShader,
6401 IWineD3DDeviceImpl_CreatePixelShader,
6402 /*** Odd functions **/
6403 IWineD3DDeviceImpl_EvictManagedResources,
6404 IWineD3DDeviceImpl_GetAvailableTextureMem,
6405 IWineD3DDeviceImpl_GetBackBuffer,
6406 IWineD3DDeviceImpl_GetCreationParameters,
6407 IWineD3DDeviceImpl_GetDeviceCaps,
6408 IWineD3DDeviceImpl_GetDirect3D,
6409 IWineD3DDeviceImpl_GetDisplayMode,
6410 IWineD3DDeviceImpl_GetNumberOfSwapChains,
6411 IWineD3DDeviceImpl_GetRasterStatus,
6412 IWineD3DDeviceImpl_GetSwapChain,
6413 IWineD3DDeviceImpl_Reset,
6414 IWineD3DDeviceImpl_SetDialogBoxMode,
6415 IWineD3DDeviceImpl_SetCursorProperties,
6416 IWineD3DDeviceImpl_SetCursorPosition,
6417 IWineD3DDeviceImpl_ShowCursor,
6418 IWineD3DDeviceImpl_TestCooperativeLevel,
6419 /*** Getters and setters **/
6420 IWineD3DDeviceImpl_SetClipPlane,
6421 IWineD3DDeviceImpl_GetClipPlane,
6422 IWineD3DDeviceImpl_SetClipStatus,
6423 IWineD3DDeviceImpl_GetClipStatus,
6424 IWineD3DDeviceImpl_SetCurrentTexturePalette,
6425 IWineD3DDeviceImpl_GetCurrentTexturePalette,
6426 IWineD3DDeviceImpl_SetDepthStencilSurface,
6427 IWineD3DDeviceImpl_GetDepthStencilSurface,
6428 IWineD3DDeviceImpl_SetFVF,
6429 IWineD3DDeviceImpl_GetFVF,
6430 IWineD3DDeviceImpl_SetGammaRamp,
6431 IWineD3DDeviceImpl_GetGammaRamp,
6432 IWineD3DDeviceImpl_SetIndices,
6433 IWineD3DDeviceImpl_GetIndices,
6434 IWineD3DDeviceImpl_SetLight,
6435 IWineD3DDeviceImpl_GetLight,
6436 IWineD3DDeviceImpl_SetLightEnable,
6437 IWineD3DDeviceImpl_GetLightEnable,
6438 IWineD3DDeviceImpl_SetMaterial,
6439 IWineD3DDeviceImpl_GetMaterial,
6440 IWineD3DDeviceImpl_SetNPatchMode,
6441 IWineD3DDeviceImpl_GetNPatchMode,
6442 IWineD3DDeviceImpl_SetPaletteEntries,
6443 IWineD3DDeviceImpl_GetPaletteEntries,
6444 IWineD3DDeviceImpl_SetPixelShader,
6445 IWineD3DDeviceImpl_GetPixelShader,
6446 IWineD3DDeviceImpl_SetPixelShaderConstant,
6447 IWineD3DDeviceImpl_GetPixelShaderConstant,
6448 IWineD3DDeviceImpl_SetPixelShaderConstantB,
6449 IWineD3DDeviceImpl_GetPixelShaderConstantB,
6450 IWineD3DDeviceImpl_SetPixelShaderConstantI,
6451 IWineD3DDeviceImpl_GetPixelShaderConstantI,
6452 IWineD3DDeviceImpl_SetPixelShaderConstantF,
6453 IWineD3DDeviceImpl_GetPixelShaderConstantF,
6454 IWineD3DDeviceImpl_SetPixelShaderConstantN,
6455 IWineD3DDeviceImpl_SetRenderState,
6456 IWineD3DDeviceImpl_GetRenderState,
6457 IWineD3DDeviceImpl_SetRenderTarget,
6458 IWineD3DDeviceImpl_GetRenderTarget,
6459 IWineD3DDeviceImpl_SetSamplerState,
6460 IWineD3DDeviceImpl_GetSamplerState,
6461 IWineD3DDeviceImpl_SetScissorRect,
6462 IWineD3DDeviceImpl_GetScissorRect,
6463 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
6464 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
6465 IWineD3DDeviceImpl_SetStreamSource,
6466 IWineD3DDeviceImpl_GetStreamSource,
6467 IWineD3DDeviceImpl_SetStreamSourceFreq,
6468 IWineD3DDeviceImpl_GetStreamSourceFreq,
6469 IWineD3DDeviceImpl_SetTexture,
6470 IWineD3DDeviceImpl_GetTexture,
6471 IWineD3DDeviceImpl_SetTextureStageState,
6472 IWineD3DDeviceImpl_GetTextureStageState,
6473 IWineD3DDeviceImpl_SetTransform,
6474 IWineD3DDeviceImpl_GetTransform,
6475 IWineD3DDeviceImpl_SetVertexDeclaration,
6476 IWineD3DDeviceImpl_GetVertexDeclaration,
6477 IWineD3DDeviceImpl_SetVertexShader,
6478 IWineD3DDeviceImpl_GetVertexShader,
6479 IWineD3DDeviceImpl_SetVertexShaderConstant,
6480 IWineD3DDeviceImpl_GetVertexShaderConstant,
6481 IWineD3DDeviceImpl_SetVertexShaderConstantB,
6482 IWineD3DDeviceImpl_GetVertexShaderConstantB,
6483 IWineD3DDeviceImpl_SetVertexShaderConstantI,
6484 IWineD3DDeviceImpl_GetVertexShaderConstantI,
6485 IWineD3DDeviceImpl_SetVertexShaderConstantF,
6486 IWineD3DDeviceImpl_GetVertexShaderConstantF,
6487 IWineD3DDeviceImpl_SetVertexShaderConstantN,
6488 IWineD3DDeviceImpl_SetViewport,
6489 IWineD3DDeviceImpl_GetViewport,
6490 IWineD3DDeviceImpl_MultiplyTransform,
6491 IWineD3DDeviceImpl_ValidateDevice,
6492 IWineD3DDeviceImpl_ProcessVertices,
6493 /*** State block ***/
6494 IWineD3DDeviceImpl_BeginStateBlock,
6495 IWineD3DDeviceImpl_EndStateBlock,
6496 /*** Scene management ***/
6497 IWineD3DDeviceImpl_BeginScene,
6498 IWineD3DDeviceImpl_EndScene,
6499 IWineD3DDeviceImpl_Present,
6500 IWineD3DDeviceImpl_Clear,
6501 /*** Drawing ***/
6502 IWineD3DDeviceImpl_DrawPrimitive,
6503 IWineD3DDeviceImpl_DrawIndexedPrimitive,
6504 IWineD3DDeviceImpl_DrawPrimitiveUP,
6505 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
6506 IWineD3DDeviceImpl_DrawRectPatch,
6507 IWineD3DDeviceImpl_DrawTriPatch,
6508 IWineD3DDeviceImpl_DeletePatch,
6509 IWineD3DDeviceImpl_ColorFill,
6510 IWineD3DDeviceImpl_UpdateTexture,
6511 IWineD3DDeviceImpl_UpdateSurface,
6512 IWineD3DDeviceImpl_StretchRect,
6513 IWineD3DDeviceImpl_GetRenderTargetData,
6514 IWineD3DDeviceImpl_GetFrontBufferData,
6515 /*** Internal use IWineD3DDevice methods ***/
6516 IWineD3DDeviceImpl_SetupTextureStates,
6517 /*** object tracking ***/
6518 IWineD3DDeviceImpl_SwapChainReleased,
6519 IWineD3DDeviceImpl_ResourceReleased
6523 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
6524 WINED3DRS_ALPHABLENDENABLE ,
6525 WINED3DRS_ALPHAFUNC ,
6526 WINED3DRS_ALPHAREF ,
6527 WINED3DRS_ALPHATESTENABLE ,
6528 WINED3DRS_BLENDOP ,
6529 WINED3DRS_COLORWRITEENABLE ,
6530 WINED3DRS_DESTBLEND ,
6531 WINED3DRS_DITHERENABLE ,
6532 WINED3DRS_FILLMODE ,
6533 WINED3DRS_FOGDENSITY ,
6534 WINED3DRS_FOGEND ,
6535 WINED3DRS_FOGSTART ,
6536 WINED3DRS_LASTPIXEL ,
6537 WINED3DRS_SHADEMODE ,
6538 WINED3DRS_SRCBLEND ,
6539 WINED3DRS_STENCILENABLE ,
6540 WINED3DRS_STENCILFAIL ,
6541 WINED3DRS_STENCILFUNC ,
6542 WINED3DRS_STENCILMASK ,
6543 WINED3DRS_STENCILPASS ,
6544 WINED3DRS_STENCILREF ,
6545 WINED3DRS_STENCILWRITEMASK ,
6546 WINED3DRS_STENCILZFAIL ,
6547 WINED3DRS_TEXTUREFACTOR ,
6548 WINED3DRS_WRAP0 ,
6549 WINED3DRS_WRAP1 ,
6550 WINED3DRS_WRAP2 ,
6551 WINED3DRS_WRAP3 ,
6552 WINED3DRS_WRAP4 ,
6553 WINED3DRS_WRAP5 ,
6554 WINED3DRS_WRAP6 ,
6555 WINED3DRS_WRAP7 ,
6556 WINED3DRS_ZENABLE ,
6557 WINED3DRS_ZFUNC ,
6558 WINED3DRS_ZWRITEENABLE
6561 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
6562 WINED3DTSS_ADDRESSW ,
6563 WINED3DTSS_ALPHAARG0 ,
6564 WINED3DTSS_ALPHAARG1 ,
6565 WINED3DTSS_ALPHAARG2 ,
6566 WINED3DTSS_ALPHAOP ,
6567 WINED3DTSS_BUMPENVLOFFSET ,
6568 WINED3DTSS_BUMPENVLSCALE ,
6569 WINED3DTSS_BUMPENVMAT00 ,
6570 WINED3DTSS_BUMPENVMAT01 ,
6571 WINED3DTSS_BUMPENVMAT10 ,
6572 WINED3DTSS_BUMPENVMAT11 ,
6573 WINED3DTSS_COLORARG0 ,
6574 WINED3DTSS_COLORARG1 ,
6575 WINED3DTSS_COLORARG2 ,
6576 WINED3DTSS_COLOROP ,
6577 WINED3DTSS_RESULTARG ,
6578 WINED3DTSS_TEXCOORDINDEX ,
6579 WINED3DTSS_TEXTURETRANSFORMFLAGS
6582 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
6583 WINED3DSAMP_ADDRESSU ,
6584 WINED3DSAMP_ADDRESSV ,
6585 WINED3DSAMP_ADDRESSW ,
6586 WINED3DSAMP_BORDERCOLOR ,
6587 WINED3DSAMP_MAGFILTER ,
6588 WINED3DSAMP_MINFILTER ,
6589 WINED3DSAMP_MIPFILTER ,
6590 WINED3DSAMP_MIPMAPLODBIAS ,
6591 WINED3DSAMP_MAXMIPLEVEL ,
6592 WINED3DSAMP_MAXANISOTROPY ,
6593 WINED3DSAMP_SRGBTEXTURE ,
6594 WINED3DSAMP_ELEMENTINDEX
6597 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
6598 WINED3DRS_AMBIENT ,
6599 WINED3DRS_AMBIENTMATERIALSOURCE ,
6600 WINED3DRS_CLIPPING ,
6601 WINED3DRS_CLIPPLANEENABLE ,
6602 WINED3DRS_COLORVERTEX ,
6603 WINED3DRS_DIFFUSEMATERIALSOURCE ,
6604 WINED3DRS_EMISSIVEMATERIALSOURCE ,
6605 WINED3DRS_FOGDENSITY ,
6606 WINED3DRS_FOGEND ,
6607 WINED3DRS_FOGSTART ,
6608 WINED3DRS_FOGTABLEMODE ,
6609 WINED3DRS_FOGVERTEXMODE ,
6610 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
6611 WINED3DRS_LIGHTING ,
6612 WINED3DRS_LOCALVIEWER ,
6613 WINED3DRS_MULTISAMPLEANTIALIAS ,
6614 WINED3DRS_MULTISAMPLEMASK ,
6615 WINED3DRS_NORMALIZENORMALS ,
6616 WINED3DRS_PATCHEDGESTYLE ,
6617 WINED3DRS_POINTSCALE_A ,
6618 WINED3DRS_POINTSCALE_B ,
6619 WINED3DRS_POINTSCALE_C ,
6620 WINED3DRS_POINTSCALEENABLE ,
6621 WINED3DRS_POINTSIZE ,
6622 WINED3DRS_POINTSIZE_MAX ,
6623 WINED3DRS_POINTSIZE_MIN ,
6624 WINED3DRS_POINTSPRITEENABLE ,
6625 WINED3DRS_RANGEFOGENABLE ,
6626 WINED3DRS_SPECULARMATERIALSOURCE ,
6627 WINED3DRS_TWEENFACTOR ,
6628 WINED3DRS_VERTEXBLEND
6631 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
6632 WINED3DTSS_TEXCOORDINDEX ,
6633 WINED3DTSS_TEXTURETRANSFORMFLAGS
6636 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
6637 WINED3DSAMP_DMAPOFFSET