- defined D3DCOLOR_B macros to access byte values of D3DCOLOR
[wine/wine-kai.git] / dlls / wined3d / device.c
blobcc4c58d4e6f1a099f83720cb75525468391a3615
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 D3DINITILIZEBASETEXTURE(_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 the and initilise 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 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, D3DRTYPE_TEXTURE, 0);
833 D3DINITILIZEBASETEXTURE(object->baseTexture);
834 object->width = Width;
835 object->height = Height;
837 /** Non-power2 support **/
838 /* Find the nearest pow2 match */
839 pow2Width = pow2Height = 1;
840 while (pow2Width < Width) pow2Width <<= 1;
841 while (pow2Height < Height) pow2Height <<= 1;
843 /** FIXME: add support for real non-power-two if it's provided by the video card **/
844 /* Precalculated scaling for 'faked' non power of two texture coords */
845 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
846 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
847 TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
849 /* Calculate levels for mip mapping */
850 if (Levels == 0) {
851 TRACE("calculating levels %d\n", object->baseTexture.levels);
852 object->baseTexture.levels++;
853 tmpW = Width;
854 tmpH = Height;
855 while (tmpW > 1 && tmpH > 1) {
856 tmpW = max(1, tmpW >> 1);
857 tmpH = max(1, tmpH >> 1);
858 object->baseTexture.levels++;
860 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
863 /* Generate all the surfaces */
864 tmpW = Width;
865 tmpH = Height;
866 for (i = 0; i < object->baseTexture.levels; i++)
868 /* use the callback to create the texture surface */
869 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
870 if (hr!= D3D_OK) {
871 int j;
872 FIXME("Failed to create surface %p\n", object);
873 /* clean up */
874 for (j = 0 ; j < i ; j++) {
875 IWineD3DSurface_Release(object->surfaces[j]);
877 /* heap free object */
878 HeapFree(GetProcessHeap(), 0, object);
880 *ppTexture = NULL;
881 return hr;
884 IWineD3DSurface_SetContainer(object->surfaces[i], (IUnknown *)object);
885 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
886 /* calculate the next mipmap level */
887 tmpW = max(1, tmpW >> 1);
888 tmpH = max(1, tmpH >> 1);
891 TRACE("(%p) : Created texture %p\n", This, object);
892 return D3D_OK;
895 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
896 UINT Width, UINT Height, UINT Depth,
897 UINT Levels, DWORD Usage,
898 WINED3DFORMAT Format, D3DPOOL Pool,
899 IWineD3DVolumeTexture **ppVolumeTexture,
900 HANDLE *pSharedHandle, IUnknown *parent,
901 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
903 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
904 IWineD3DVolumeTextureImpl *object;
905 unsigned int i;
906 UINT tmpW;
907 UINT tmpH;
908 UINT tmpD;
910 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, D3DRTYPE_VOLUMETEXTURE, 0);
911 D3DINITILIZEBASETEXTURE(object->baseTexture);
913 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
914 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
916 object->width = Width;
917 object->height = Height;
918 object->depth = Depth;
920 /* Calculate levels for mip mapping */
921 if (Levels == 0) {
922 object->baseTexture.levels++;
923 tmpW = Width;
924 tmpH = Height;
925 tmpD = Depth;
926 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
927 tmpW = max(1, tmpW >> 1);
928 tmpH = max(1, tmpH >> 1);
929 tmpD = max(1, tmpD >> 1);
930 object->baseTexture.levels++;
932 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
935 /* Generate all the surfaces */
936 tmpW = Width;
937 tmpH = Height;
938 tmpD = Depth;
940 for (i = 0; i < object->baseTexture.levels; i++)
942 /* Create the volume */
943 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
944 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
946 /* Set it's container to this object */
947 IWineD3DVolume_SetContainer(object->volumes[i], (IUnknown *)object);
949 /* calcualte the next mipmap level */
950 tmpW = max(1, tmpW >> 1);
951 tmpH = max(1, tmpH >> 1);
952 tmpD = max(1, tmpD >> 1);
955 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
956 TRACE("(%p) : Created volume texture %p\n", This, object);
957 return D3D_OK;
960 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
961 UINT Width, UINT Height, UINT Depth,
962 DWORD Usage,
963 WINED3DFORMAT Format, D3DPOOL Pool,
964 IWineD3DVolume** ppVolume,
965 HANDLE* pSharedHandle, IUnknown *parent) {
967 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
968 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
970 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, D3DRTYPE_VOLUME, ((Width * D3DFmtGetBpp(This, Format)) * Height * Depth))
972 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
973 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
975 object->currentDesc.Width = Width;
976 object->currentDesc.Height = Height;
977 object->currentDesc.Depth = Depth;
978 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
980 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
981 object->lockable = TRUE;
982 object->locked = FALSE;
983 memset(&object->lockedBox, 0, sizeof(D3DBOX));
984 object->dirty = TRUE;
986 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
989 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
990 UINT Levels, DWORD Usage,
991 WINED3DFORMAT Format, D3DPOOL Pool,
992 IWineD3DCubeTexture **ppCubeTexture,
993 HANDLE *pSharedHandle, IUnknown *parent,
994 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
996 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
997 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
998 unsigned int i, j;
999 UINT tmpW;
1000 HRESULT hr;
1001 unsigned int pow2EdgeLength = EdgeLength;
1003 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, D3DRTYPE_CUBETEXTURE, 0);
1004 D3DINITILIZEBASETEXTURE(object->baseTexture);
1006 TRACE("(%p) Create Cube Texture\n", This);
1008 /** Non-power2 support **/
1010 /* Find the nearest pow2 match */
1011 pow2EdgeLength = 1;
1012 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
1014 object->edgeLength = EdgeLength;
1015 /* TODO: support for native non-power 2 */
1016 /* Precalculated scaling for 'faked' non power of two texture coords */
1017 object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
1019 /* Calculate levels for mip mapping */
1020 if (Levels == 0) {
1021 object->baseTexture.levels++;
1022 tmpW = EdgeLength;
1023 while (tmpW > 1) {
1024 tmpW = max(1, tmpW >> 1);
1025 object->baseTexture.levels++;
1027 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1030 /* Generate all the surfaces */
1031 tmpW = EdgeLength;
1032 for (i = 0; i < object->baseTexture.levels; i++) {
1034 /* Create the 6 faces */
1035 for (j = 0; j < 6; j++) {
1037 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
1038 i /* Level */, &object->surfaces[j][i],pSharedHandle);
1040 if(hr!= D3D_OK) {
1041 /* clean up */
1042 int k;
1043 int l;
1044 for (l = 0; l < j; l++) {
1045 IWineD3DSurface_Release(object->surfaces[j][i]);
1047 for (k = 0; k < i; k++) {
1048 for (l = 0; l < 6; l++) {
1049 IWineD3DSurface_Release(object->surfaces[l][j]);
1053 FIXME("(%p) Failed to create surface\n",object);
1054 HeapFree(GetProcessHeap(),0,object);
1055 *ppCubeTexture = NULL;
1056 return hr;
1058 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IUnknown *)object);
1059 TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1061 tmpW = max(1, tmpW >> 1);
1064 TRACE("(%p) : Created Cube Texture %p\n", This, object);
1065 *ppCubeTexture = (IWineD3DCubeTexture *) object;
1066 return D3D_OK;
1069 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1070 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1071 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1073 if (NULL == ppQuery) {
1074 /* Just a check to see if we support this type of query */
1075 HRESULT hr = D3DERR_NOTAVAILABLE;
1076 /* Lie and say everything is good (we can return ok fake data from a stub) */
1077 switch(Type) {
1078 case WINED3DQUERYTYPE_VCACHE:
1079 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1080 case WINED3DQUERYTYPE_VERTEXSTATS:
1081 case WINED3DQUERYTYPE_EVENT:
1082 case WINED3DQUERYTYPE_TIMESTAMP:
1083 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1084 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1085 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1086 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1087 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1088 case WINED3DQUERYTYPE_PIXELTIMINGS:
1089 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1090 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1091 break;
1092 case WINED3DQUERYTYPE_OCCLUSION:
1093 TRACE("(%p) occlusion query\n", This);
1094 if (GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY))
1095 hr = D3D_OK;
1096 break;
1097 default:
1098 FIXME("(%p) Unhandled query type %d\n",This , Type);
1100 FIXME("(%p) : Stub request for query type %d returned %ld\n", This, Type, hr);
1101 return hr;
1104 D3DCREATEOBJECTINSTANCE(object, Query)
1105 object->type = Type;
1106 /* allocated the 'extended' data based on the type of query requested */
1107 switch(Type){
1108 case D3DQUERYTYPE_OCCLUSION:
1109 if(GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY)) {
1110 TRACE("(%p) Allocating data for an occlusion query\n", This);
1111 object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1112 break;
1114 case D3DQUERYTYPE_VCACHE:
1115 case D3DQUERYTYPE_RESOURCEMANAGER:
1116 case D3DQUERYTYPE_VERTEXSTATS:
1117 case D3DQUERYTYPE_EVENT:
1118 case D3DQUERYTYPE_TIMESTAMP:
1119 case D3DQUERYTYPE_TIMESTAMPDISJOINT:
1120 case D3DQUERYTYPE_TIMESTAMPFREQ:
1121 case D3DQUERYTYPE_PIPELINETIMINGS:
1122 case D3DQUERYTYPE_INTERFACETIMINGS:
1123 case D3DQUERYTYPE_VERTEXTIMINGS:
1124 case D3DQUERYTYPE_PIXELTIMINGS:
1125 case D3DQUERYTYPE_BANDWIDTHTIMINGS:
1126 case D3DQUERYTYPE_CACHEUTILIZATION:
1127 default:
1128 object->extendedData = 0;
1129 FIXME("(%p) Unhandled query type %d\n",This , Type);
1131 TRACE("(%p) : Created Query %p\n", This, object);
1132 return D3D_OK;
1135 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1136 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1137 IUnknown* parent,
1138 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1139 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1140 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1142 HDC hDc;
1143 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1144 int num;
1145 XVisualInfo template;
1146 GLXContext oldContext;
1147 Drawable oldDrawable;
1148 HRESULT hr = D3D_OK;
1150 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1152 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1153 * does a device hold a reference to a swap chain giving them a lifetime of the device
1154 * or does the swap chain notify the device of it'd destruction.
1155 *******************************/
1157 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1159 /* Initialize other useful values */
1160 object->presentParms.BackBufferCount = 1; /* TODO:? support for gl_aux buffers */
1162 /*********************
1163 * Lookup the window Handle and the relating X window handle
1164 ********************/
1166 /* Setup hwnd we are using, plus which display this equates to */
1167 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1168 if (!object->win_handle) {
1169 object->win_handle = This->createParms.hFocusWindow;
1172 object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window" );
1173 hDc = GetDC(object->win_handle);
1174 object->display = get_display(hDc);
1175 ReleaseDC(object->win_handle, hDc);
1176 TRACE("Using a display of %p %p\n", object->display, hDc);
1178 if (NULL == object->display || NULL == hDc) {
1179 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1180 return D3DERR_NOTAVAILABLE;
1183 if (object->win == 0) {
1184 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1185 return D3DERR_NOTAVAILABLE;
1188 * Create an opengl context for the display visual
1189 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1190 * use different properties after that point in time. FIXME: How to handle when requested format
1191 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1192 * it chooses is identical to the one already being used!
1193 **********************************/
1195 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1196 ENTER_GL();
1198 /* Create a new context for this swapchain */
1199 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1200 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1201 (or the best possible if none is requested) */
1202 TRACE("Found x visual ID : %ld\n", template.visualid);
1204 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1205 if (NULL == object->visInfo) {
1206 ERR("cannot really get XVisual\n");
1207 LEAVE_GL();
1208 return D3DERR_NOTAVAILABLE;
1209 } else {
1210 int n, value;
1211 /* Write out some debug info about the visual/s */
1212 TRACE("Using x visual ID : %ld\n", template.visualid);
1213 TRACE(" visual info: %p\n", object->visInfo);
1214 TRACE(" num items : %d\n", num);
1215 for (n = 0;n < num; n++) {
1216 TRACE("=====item=====: %d\n", n + 1);
1217 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1218 TRACE(" screen : %d\n", object->visInfo[n].screen);
1219 TRACE(" depth : %u\n", object->visInfo[n].depth);
1220 TRACE(" class : %d\n", object->visInfo[n].class);
1221 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1222 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1223 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1224 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1225 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1226 /* log some extra glx info */
1227 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1228 TRACE(" gl_aux_buffers : %d\n", value);
1229 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1230 TRACE(" gl_buffer_size : %d\n", value);
1231 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1232 TRACE(" gl_red_size : %d\n", value);
1233 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1234 TRACE(" gl_green_size : %d\n", value);
1235 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1236 TRACE(" gl_blue_size : %d\n", value);
1237 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1238 TRACE(" gl_alpha_size : %d\n", value);
1239 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1240 TRACE(" gl_depth_size : %d\n", value);
1241 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1242 TRACE(" gl_stencil_size : %d\n", value);
1244 /* Now choose a simila visual ID*/
1246 #ifdef USE_CONTEXT_MANAGER
1248 /** TODO: use a context mamager **/
1249 #endif
1252 IWineD3DSwapChain *implSwapChain;
1253 if (D3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1254 /* The first time around we create the context that is shared with all other swapchains and render targets */
1255 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1256 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1257 } else {
1259 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1260 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1261 /* and create a new context with the implicit swapchains context as the shared context */
1262 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1263 IWineD3DSwapChain_Release(implSwapChain);
1267 /* Cleanup */
1268 XFree(object->visInfo);
1269 object->visInfo = NULL;
1271 if (NULL == object->glCtx) {
1272 ERR("cannot create glxContext\n");
1273 LEAVE_GL();
1274 return D3DERR_NOTAVAILABLE;
1277 LEAVE_GL();
1278 if (object->glCtx == NULL) {
1279 ERR("Error in context creation !\n");
1280 return D3DERR_INVALIDCALL;
1281 } else {
1282 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1283 object->win_handle, object->glCtx, object->win, object->visInfo);
1286 /*********************
1287 * Windowed / Fullscreen
1288 *******************/
1291 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1292 * so we should really check to see if their is a fullscreen swapchain already
1293 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1294 **************************************/
1296 if (!*(pPresentationParameters->Windowed)) {
1298 DEVMODEW devmode;
1299 HDC hdc;
1300 int bpp = 0;
1302 /* Get info on the current display setup */
1303 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1304 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1305 DeleteDC(hdc);
1307 /* Change the display settings */
1308 memset(&devmode, 0, sizeof(DEVMODEW));
1309 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1310 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1311 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1312 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1313 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1314 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1316 /* Make popup window */
1317 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1318 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1319 *(pPresentationParameters->BackBufferWidth),
1320 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1326 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1327 * then the corresponding dimension of the client area of the hDeviceWindow
1328 * (or the focus window, if hDeviceWindow is NULL) is taken.
1329 **********************/
1331 if (*(pPresentationParameters->Windowed) &&
1332 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1333 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1335 RECT Rect;
1336 GetClientRect(object->win_handle, &Rect);
1338 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1339 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1340 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1342 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1343 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1344 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1348 /*********************
1349 * finish off parameter initialization
1350 *******************/
1352 /* Put the correct figures in the presentation parameters */
1353 TRACE("Coppying accross presentaion paraneters\n");
1354 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1355 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1356 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1357 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1358 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1359 object->presentParms.MultiSampleQuality = *(pPresentationParameters->MultiSampleQuality);
1360 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1361 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1362 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1363 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1364 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1365 object->presentParms.Flags = *(pPresentationParameters->Flags);
1366 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1367 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1370 /*********************
1371 * Create the back, front and stencil buffers
1372 *******************/
1373 TRACE("calling rendertarget CB\n");
1374 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1375 object->presentParms.BackBufferWidth,
1376 object->presentParms.BackBufferHeight,
1377 object->presentParms.BackBufferFormat,
1378 object->presentParms.MultiSampleType,
1379 object->presentParms.MultiSampleQuality,
1380 TRUE /* Lockable */,
1381 &object->frontBuffer,
1382 NULL /* pShared (always null)*/);
1383 if (object->frontBuffer != NULL)
1384 IWineD3DSurface_SetContainer(object->frontBuffer, (IUnknown *)object);
1385 TRACE("calling rendertarget CB\n");
1386 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1387 object->presentParms.BackBufferWidth,
1388 object->presentParms.BackBufferHeight,
1389 object->presentParms.BackBufferFormat,
1390 object->presentParms.MultiSampleType,
1391 object->presentParms.MultiSampleQuality,
1392 TRUE /* Lockable */,
1393 &object->backBuffer,
1394 NULL /* pShared (always null)*/);
1395 if (object->backBuffer != NULL)
1396 IWineD3DSurface_SetContainer(object->backBuffer, (IUnknown *)object);
1398 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1399 if (pPresentationParameters->EnableAutoDepthStencil) {
1400 TRACE("Creating depth stencil buffer\n");
1401 if (This->depthStencilBuffer == NULL ) {
1402 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1403 object->presentParms.BackBufferWidth,
1404 object->presentParms.BackBufferHeight,
1405 object->presentParms.AutoDepthStencilFormat,
1406 object->presentParms.MultiSampleType,
1407 object->presentParms.MultiSampleQuality,
1408 FALSE /* FIXME: Discard */,
1409 &This->depthStencilBuffer,
1410 NULL /* pShared (always null)*/ );
1411 if (This->depthStencilBuffer != NULL)
1412 IWineD3DSurface_SetContainer(This->depthStencilBuffer, (IUnknown *)iface);
1415 /** TODO: A check on width, height and multisample types
1416 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1417 ****************************/
1418 object->wantsDepthStencilBuffer = TRUE;
1419 } else {
1420 object->wantsDepthStencilBuffer = FALSE;
1423 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1426 /*********************
1427 * init the default renderTarget management
1428 *******************/
1429 object->drawable = object->win;
1430 object->render_ctx = object->glCtx;
1432 if (hr == D3D_OK) {
1433 /*********************
1434 * Setup some defaults and clear down the buffers
1435 *******************/
1436 ENTER_GL();
1437 /** save current context and drawable **/
1438 oldContext = glXGetCurrentContext();
1439 oldDrawable = glXGetCurrentDrawable();
1441 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1442 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1443 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1445 checkGLcall("glXMakeCurrent");
1447 TRACE("Setting up the screen\n");
1448 /* Clear the screen */
1449 glClearColor(1.0, 0.0, 0.0, 0.0);
1450 checkGLcall("glClearColor");
1451 glClearIndex(0);
1452 glClearDepth(1);
1453 glClearStencil(0xffff);
1455 checkGLcall("glClear");
1457 glColor3f(1.0, 1.0, 1.0);
1458 checkGLcall("glColor3f");
1460 glEnable(GL_LIGHTING);
1461 checkGLcall("glEnable");
1463 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1464 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1466 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1467 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1469 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1470 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1472 /* switch back to the original context (if there was one)*/
1473 if (This->swapchains != NULL) {
1474 /** TODO: restore the context and drawable **/
1475 glXMakeCurrent(object->display, oldDrawable, oldContext);
1478 LEAVE_GL();
1480 { /* Finally add the swapchain to the end of the devices' swapchain list */
1481 SwapChainList **nextSwapchain;
1482 nextSwapchain = &This->swapchains;
1483 while (*nextSwapchain != NULL) {
1484 nextSwapchain = &((*nextSwapchain)->next);
1486 (*nextSwapchain) = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->swapchains));
1487 (*nextSwapchain)->swapchain = (IWineD3DSwapChain *)object;
1489 TRACE("Set swapchain to %p\n", object);
1490 } else { /* something went wrong so clean up */
1491 IUnknown* bufferParent;
1492 if (object->frontBuffer) {
1493 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1494 IUnknown_Release(bufferParent); /* once for the get parent */
1495 if (IUnknown_Release(bufferParent) > 0) {
1496 FIXME("(%p) Something's still holding the front buffer\n",This);
1499 if (object->backBuffer) {
1500 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1501 IUnknown_Release(bufferParent); /* once for the get parent */
1502 if (IUnknown_Release(bufferParent) > 0) {
1503 FIXME("(%p) Something's still holding the back buffer\n",This);
1506 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1507 /* Clean up the context */
1508 /* check that we are the current context first (we shouldn't be though!) */
1509 if (object->glCtx != 0) {
1510 if(glXGetCurrentContext() == object->glCtx) {
1511 glXMakeCurrent(object->display, None, NULL);
1513 glXDestroyContext(object->display, object->glCtx);
1515 HeapFree(GetProcessHeap(), 0, object);
1519 return hr;
1522 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1523 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1524 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1525 unsigned int numberOfSwapChains = 0;
1526 SwapChainList *swapchain;
1528 swapchain = This->swapchains;
1529 /* itterate through the list to get a count */
1530 while (swapchain != NULL) {
1531 swapchain = swapchain->next;
1532 numberOfSwapChains++;
1535 TRACE("(%p) returning %d\n", This, numberOfSwapChains);
1536 return numberOfSwapChains;
1539 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1540 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1541 SwapChainList *swapchain;
1542 HRESULT hr = D3DERR_INVALIDCALL;
1543 swapchain = This->swapchains;
1544 TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1547 TRACE("(%p) Finding swapchain %d\n", This, iSwapChain);
1548 while (iSwapChain > 0 && swapchain != NULL) {
1549 swapchain = swapchain->next;
1550 iSwapChain--;
1553 if (iSwapChain > 0 || swapchain == NULL) {
1554 FIXME("(%p) Unable to find swapchain %d\n", This, iSwapChain);
1555 *pSwapChain = NULL;
1556 } else {
1557 /** TODO: move off to a linkesList implementation **/
1558 *pSwapChain = swapchain->swapchain;
1559 IWineD3DSwapChain_AddRef(*pSwapChain);
1560 hr = D3D_OK;
1563 TRACE("(%p) returning %p\n", This, *pSwapChain);
1564 return hr;
1567 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
1568 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1570 FIXME("(%p) : Stub\n",This);
1571 return D3D_OK;
1575 /*****
1576 * Vertex Declaration
1577 *****/
1578 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1579 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1580 IWineD3DVertexDeclarationImpl *object = NULL;
1581 HRESULT hr = D3D_OK;
1582 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1583 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1584 object->allFVF = 0;
1586 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1588 return hr;
1591 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1592 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DVertexShader** ppVertexShader, IUnknown *parent) {
1593 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1594 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1595 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1597 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1598 IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1600 return D3D_OK;
1603 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DPixelShader** ppPixelShader, IUnknown *parent) {
1604 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1605 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1607 D3DCREATEOBJECTINSTANCE(object, PixelShader)
1608 #if 1
1609 object->function = pFunction;
1610 #else /* TODO: pixel shader set function */
1611 IWineD3DPixelShaderImpl_SetFuction(*ppPixelShader, pFunction);
1612 #endif
1613 FIXME("(%p) : STUB: Created Pixel shader %p\n", This, ppPixelShader);
1614 return D3D_OK;
1619 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice* iface, IWineD3D** ppD3D) {
1620 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1621 *ppD3D= This->wineD3D;
1622 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1623 IWineD3D_AddRef(*ppD3D);
1624 return D3D_OK;
1627 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1628 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1629 * Into the video ram as possible and seeing how many fit
1630 * you can also get the correct initial value from via X and ATI's driver
1631 *******************/
1632 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1633 static BOOL showfixmes = TRUE;
1634 if (showfixmes) {
1635 FIXME("(%p) : stub, emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1636 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1637 showfixmes = FALSE;
1639 TRACE("(%p) : emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1640 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1641 /* videomemory is simulated videomemory + AGP memory left */
1642 return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1647 /*****
1648 * Get / Set FVF
1649 *****/
1650 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1651 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1652 HRESULT hr = D3D_OK;
1654 /* Update the current state block */
1655 This->updateStateBlock->fvf = fvf;
1656 This->updateStateBlock->changed.fvf = TRUE;
1657 This->updateStateBlock->set.fvf = TRUE;
1659 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1661 if (0 != fvf) {
1662 /* clear down the vertex declaration
1663 NOTE: Axis and Allies doesn't work properly otherwise
1664 (may be a stateblock problem though!)
1666 hr = IWineD3DDevice_SetVertexDeclaration(iface, NULL);
1669 return hr;
1673 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1674 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1675 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1676 *pfvf = This->stateBlock->fvf;
1677 return D3D_OK;
1680 /*****
1681 * Get / Set Stream Source
1682 *****/
1683 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1684 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1685 IWineD3DVertexBuffer *oldSrc;
1687 /**TODO: instance and index data, see
1688 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1690 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
1691 **************/
1693 /* D3d9 only, but shouldn't hurt d3d8 */
1694 UINT streamFlags;
1696 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1697 if (streamFlags) {
1698 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1699 FIXME("stream index data not supported\n");
1701 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1702 FIXME("stream instance data not supported\n");
1706 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1708 if (StreamNumber >= MAX_STREAMS) {
1709 WARN("Stream out of range %d\n", StreamNumber);
1710 return D3DERR_INVALIDCALL;
1713 oldSrc = This->stateBlock->streamSource[StreamNumber];
1714 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1716 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
1717 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
1718 This->updateStateBlock->streamStride[StreamNumber] = Stride;
1719 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
1720 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
1721 This->updateStateBlock->streamFlags[StreamNumber] = streamFlags;
1723 /* Handle recording of state blocks */
1724 if (This->isRecordingState) {
1725 TRACE("Recording... not performing anything\n");
1726 return D3D_OK;
1729 /* Not recording... */
1730 /* Need to do a getParent and pass the reffs up */
1731 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
1732 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
1733 so for now, just count internally */
1734 if (pStreamData != NULL) {
1735 IUnknown *newVertexBufferParent;
1736 /* GetParent will add a ref, so leave it hanging until the vertex buffer is cleared */
1737 IWineD3DVertexBuffer_GetParent(pStreamData, &newVertexBufferParent);
1739 if (oldSrc != NULL) {
1740 IUnknown *oldVertexBufferParent;
1741 IWineD3DVertexBuffer_GetParent(oldSrc, &oldVertexBufferParent);
1742 IUnknown_Release(oldVertexBufferParent);
1743 IUnknown_Release(oldVertexBufferParent);
1746 return D3D_OK;
1749 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
1750 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1751 UINT streamFlags;
1753 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
1754 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
1757 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1758 if (streamFlags) {
1759 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1760 FIXME("stream index data not supported\n");
1762 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1763 FIXME("stream instance data not supported\n");
1767 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1769 if (StreamNumber >= MAX_STREAMS) {
1770 WARN("Stream out of range %d\n", StreamNumber);
1771 return D3DERR_INVALIDCALL;
1773 *pStream = This->stateBlock->streamSource[StreamNumber];
1774 *pStride = This->stateBlock->streamStride[StreamNumber];
1775 *pOffset = This->stateBlock->streamOffset[StreamNumber];
1777 if (*pStream == NULL) {
1778 FIXME("Attempting to get an empty stream %d, returning D3DERR_INVALIDCALL\n", StreamNumber);
1779 return D3DERR_INVALIDCALL;
1782 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
1783 return D3D_OK;
1786 /*Should be quite easy, just an extension of vertexdata
1787 ref...
1788 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1790 The divider is a bit odd though
1792 VertexOffset = StartVertex / Divider * StreamStride +
1793 VertexIndex / Divider * StreamStride + StreamOffset
1796 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
1797 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1799 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
1800 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (D3DSTREAMSOURCE_INSTANCEDATA | D3DSTREAMSOURCE_INDEXEDDATA );
1802 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
1803 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
1804 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
1806 if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
1807 FIXME("Stream indexing not fully supported\n");
1810 return D3D_OK;
1813 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
1814 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1816 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
1817 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
1819 TRACE("(%p) : returning %d\n", This, *Divider);
1821 return D3D_OK;
1824 /*****
1825 * Get / Set & Multiply Transform
1826 *****/
1827 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1828 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1830 /* Most of this routine, comments included copied from ddraw tree initially: */
1831 TRACE("(%p) : Transform State=%d\n", This, d3dts);
1833 /* Handle recording of state blocks */
1834 if (This->isRecordingState) {
1835 TRACE("Recording... not performing anything\n");
1836 This->updateStateBlock->changed.transform[d3dts] = TRUE;
1837 This->updateStateBlock->set.transform[d3dts] = TRUE;
1838 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1839 return D3D_OK;
1843 * If the new matrix is the same as the current one,
1844 * we cut off any further processing. this seems to be a reasonable
1845 * optimization because as was noticed, some apps (warcraft3 for example)
1846 * tend towards setting the same matrix repeatedly for some reason.
1848 * From here on we assume that the new matrix is different, wherever it matters.
1850 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1851 TRACE("The app is setting the same matrix over again\n");
1852 return D3D_OK;
1853 } else {
1854 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1858 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1859 where ViewMat = Camera space, WorldMat = world space.
1861 In OpenGL, camera and world space is combined into GL_MODELVIEW
1862 matrix. The Projection matrix stay projection matrix.
1865 /* Capture the times we can just ignore the change for now */
1866 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1867 This->modelview_valid = FALSE;
1868 return D3D_OK;
1870 } else if (d3dts == D3DTS_PROJECTION) {
1871 This->proj_valid = FALSE;
1872 return D3D_OK;
1874 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1875 /* Indexed Vertex Blending Matrices 256 -> 511 */
1876 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1877 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1878 return D3D_OK;
1881 /* Now we really are going to have to change a matrix */
1882 ENTER_GL();
1884 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1885 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
1886 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1887 unsigned int k;
1889 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1890 * NOTE: We have to reset the positions even if the light/plane is not currently
1891 * enabled, since the call to enable it will not reset the position.
1892 * NOTE2: Apparently texture transforms do NOT need reapplying
1895 PLIGHTINFOEL *lightChain = NULL;
1896 This->modelview_valid = FALSE;
1897 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
1899 glMatrixMode(GL_MODELVIEW);
1900 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1901 glPushMatrix();
1902 glLoadMatrixf((float *)lpmatrix);
1903 checkGLcall("glLoadMatrixf(...)");
1905 /* Reset lights */
1906 lightChain = This->stateBlock->lights;
1907 while (lightChain && lightChain->glIndex != -1) {
1908 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1909 checkGLcall("glLightfv posn");
1910 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1911 checkGLcall("glLightfv dirn");
1912 lightChain = lightChain->next;
1915 /* Reset Clipping Planes if clipping is enabled */
1916 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1917 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1918 checkGLcall("glClipPlane");
1920 glPopMatrix();
1922 } else { /* What was requested!?? */
1923 WARN("invalid matrix specified: %i\n", d3dts);
1926 /* Release lock, all done */
1927 LEAVE_GL();
1928 return D3D_OK;
1931 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1932 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1933 TRACE("(%p) : for Transform State %d\n", This, State);
1934 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1935 return D3D_OK;
1938 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1939 D3DMATRIX *mat = NULL;
1940 D3DMATRIX temp;
1942 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1943 * below means it will be recorded in a state block change, but it
1944 * works regardless where it is recorded.
1945 * If this is found to be wrong, change to StateBlock.
1947 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1948 TRACE("(%p) : For state %u\n", This, State);
1950 if (State < HIGHEST_TRANSFORMSTATE)
1952 mat = &This->updateStateBlock->transforms[State];
1953 } else {
1954 FIXME("Unhandled transform state!!\n");
1957 /* Copied from ddraw code: */
1958 temp.u.s._11 = (mat->u.s._11 * pMatrix->u.s._11) + (mat->u.s._21 * pMatrix->u.s._12) +
1959 (mat->u.s._31 * pMatrix->u.s._13) + (mat->u.s._41 * pMatrix->u.s._14);
1960 temp.u.s._21 = (mat->u.s._11 * pMatrix->u.s._21) + (mat->u.s._21 * pMatrix->u.s._22) +
1961 (mat->u.s._31 * pMatrix->u.s._23) + (mat->u.s._41 * pMatrix->u.s._24);
1962 temp.u.s._31 = (mat->u.s._11 * pMatrix->u.s._31) + (mat->u.s._21 * pMatrix->u.s._32) +
1963 (mat->u.s._31 * pMatrix->u.s._33) + (mat->u.s._41 * pMatrix->u.s._34);
1964 temp.u.s._41 = (mat->u.s._11 * pMatrix->u.s._41) + (mat->u.s._21 * pMatrix->u.s._42) +
1965 (mat->u.s._31 * pMatrix->u.s._43) + (mat->u.s._41 * pMatrix->u.s._44);
1967 temp.u.s._12 = (mat->u.s._12 * pMatrix->u.s._11) + (mat->u.s._22 * pMatrix->u.s._12) +
1968 (mat->u.s._32 * pMatrix->u.s._13) + (mat->u.s._42 * pMatrix->u.s._14);
1969 temp.u.s._22 = (mat->u.s._12 * pMatrix->u.s._21) + (mat->u.s._22 * pMatrix->u.s._22) +
1970 (mat->u.s._32 * pMatrix->u.s._23) + (mat->u.s._42 * pMatrix->u.s._24);
1971 temp.u.s._32 = (mat->u.s._12 * pMatrix->u.s._31) + (mat->u.s._22 * pMatrix->u.s._32) +
1972 (mat->u.s._32 * pMatrix->u.s._33) + (mat->u.s._42 * pMatrix->u.s._34);
1973 temp.u.s._42 = (mat->u.s._12 * pMatrix->u.s._41) + (mat->u.s._22 * pMatrix->u.s._42) +
1974 (mat->u.s._32 * pMatrix->u.s._43) + (mat->u.s._42 * pMatrix->u.s._44);
1976 temp.u.s._13 = (mat->u.s._13 * pMatrix->u.s._11) + (mat->u.s._23 * pMatrix->u.s._12) +
1977 (mat->u.s._33 * pMatrix->u.s._13) + (mat->u.s._43 * pMatrix->u.s._14);
1978 temp.u.s._23 = (mat->u.s._13 * pMatrix->u.s._21) + (mat->u.s._23 * pMatrix->u.s._22) +
1979 (mat->u.s._33 * pMatrix->u.s._23) + (mat->u.s._43 * pMatrix->u.s._24);
1980 temp.u.s._33 = (mat->u.s._13 * pMatrix->u.s._31) + (mat->u.s._23 * pMatrix->u.s._32) +
1981 (mat->u.s._33 * pMatrix->u.s._33) + (mat->u.s._43 * pMatrix->u.s._34);
1982 temp.u.s._43 = (mat->u.s._13 * pMatrix->u.s._41) + (mat->u.s._23 * pMatrix->u.s._42) +
1983 (mat->u.s._33 * pMatrix->u.s._43) + (mat->u.s._43 * pMatrix->u.s._44);
1985 temp.u.s._14 = (mat->u.s._14 * pMatrix->u.s._11) + (mat->u.s._24 * pMatrix->u.s._12) +
1986 (mat->u.s._34 * pMatrix->u.s._13) + (mat->u.s._44 * pMatrix->u.s._14);
1987 temp.u.s._24 = (mat->u.s._14 * pMatrix->u.s._21) + (mat->u.s._24 * pMatrix->u.s._22) +
1988 (mat->u.s._34 * pMatrix->u.s._23) + (mat->u.s._44 * pMatrix->u.s._24);
1989 temp.u.s._34 = (mat->u.s._14 * pMatrix->u.s._31) + (mat->u.s._24 * pMatrix->u.s._32) +
1990 (mat->u.s._34 * pMatrix->u.s._33) + (mat->u.s._44 * pMatrix->u.s._34);
1991 temp.u.s._44 = (mat->u.s._14 * pMatrix->u.s._41) + (mat->u.s._24 * pMatrix->u.s._42) +
1992 (mat->u.s._34 * pMatrix->u.s._43) + (mat->u.s._44 * pMatrix->u.s._44);
1994 /* Apply change via set transform - will reapply to eg. lights this way */
1995 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
1998 /*****
1999 * Get / Set Light
2000 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
2001 *****/
2002 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2003 you can reference any indexes you want as long as that number max are enabled at any
2004 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2005 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2006 but when recording, just build a chain pretty much of commands to be replayed. */
2008 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2009 float rho;
2010 PLIGHTINFOEL *object, *temp;
2012 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2013 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2015 /* If recording state block, just add to end of lights chain */
2016 if (This->isRecordingState) {
2017 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2018 if (NULL == object) {
2019 return D3DERR_OUTOFVIDEOMEMORY;
2021 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2022 object->OriginalIndex = Index;
2023 object->glIndex = -1;
2024 object->changed = TRUE;
2026 /* Add to the END of the chain of lights changes to be replayed */
2027 if (This->updateStateBlock->lights == NULL) {
2028 This->updateStateBlock->lights = object;
2029 } else {
2030 temp = This->updateStateBlock->lights;
2031 while (temp->next != NULL) temp=temp->next;
2032 temp->next = object;
2034 TRACE("Recording... not performing anything more\n");
2035 return D3D_OK;
2038 /* Ok, not recording any longer so do real work */
2039 object = This->stateBlock->lights;
2040 while (object != NULL && object->OriginalIndex != Index) object = object->next;
2042 /* If we didn't find it in the list of lights, time to add it */
2043 if (object == NULL) {
2044 PLIGHTINFOEL *insertAt,*prevPos;
2046 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2047 if (NULL == object) {
2048 return D3DERR_OUTOFVIDEOMEMORY;
2050 object->OriginalIndex = Index;
2051 object->glIndex = -1;
2053 /* Add it to the front of list with the idea that lights will be changed as needed
2054 BUT after any lights currently assigned GL indexes */
2055 insertAt = This->stateBlock->lights;
2056 prevPos = NULL;
2057 while (insertAt != NULL && insertAt->glIndex != -1) {
2058 prevPos = insertAt;
2059 insertAt = insertAt->next;
2062 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2063 This->stateBlock->lights = object;
2064 } else if (insertAt == NULL) { /* End of list */
2065 prevPos->next = object;
2066 object->prev = prevPos;
2067 } else { /* Middle of chain */
2068 if (prevPos == NULL) {
2069 This->stateBlock->lights = object;
2070 } else {
2071 prevPos->next = object;
2073 object->prev = prevPos;
2074 object->next = insertAt;
2075 insertAt->prev = object;
2079 /* Initialze the object */
2080 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,
2081 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2082 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2083 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2084 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2085 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2086 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2088 /* Save away the information */
2089 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2091 switch (pLight->Type) {
2092 case D3DLIGHT_POINT:
2093 /* Position */
2094 object->lightPosn[0] = pLight->Position.x;
2095 object->lightPosn[1] = pLight->Position.y;
2096 object->lightPosn[2] = pLight->Position.z;
2097 object->lightPosn[3] = 1.0f;
2098 object->cutoff = 180.0f;
2099 /* FIXME: Range */
2100 break;
2102 case D3DLIGHT_DIRECTIONAL:
2103 /* Direction */
2104 object->lightPosn[0] = -pLight->Direction.x;
2105 object->lightPosn[1] = -pLight->Direction.y;
2106 object->lightPosn[2] = -pLight->Direction.z;
2107 object->lightPosn[3] = 0.0;
2108 object->exponent = 0.0f;
2109 object->cutoff = 180.0f;
2110 break;
2112 case D3DLIGHT_SPOT:
2113 /* Position */
2114 object->lightPosn[0] = pLight->Position.x;
2115 object->lightPosn[1] = pLight->Position.y;
2116 object->lightPosn[2] = pLight->Position.z;
2117 object->lightPosn[3] = 1.0;
2119 /* Direction */
2120 object->lightDirn[0] = pLight->Direction.x;
2121 object->lightDirn[1] = pLight->Direction.y;
2122 object->lightDirn[2] = pLight->Direction.z;
2123 object->lightDirn[3] = 1.0;
2126 * opengl-ish and d3d-ish spot lights use too different models for the
2127 * light "intensity" as a function of the angle towards the main light direction,
2128 * so we only can approximate very roughly.
2129 * however spot lights are rather rarely used in games (if ever used at all).
2130 * furthermore if still used, probably nobody pays attention to such details.
2132 if (pLight->Falloff == 0) {
2133 rho = 6.28f;
2134 } else {
2135 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2137 if (rho < 0.0001) rho = 0.0001f;
2138 object->exponent = -0.3/log(cos(rho/2));
2139 object->cutoff = pLight->Phi*90/M_PI;
2141 /* FIXME: Range */
2142 break;
2144 default:
2145 FIXME("Unrecognized light type %d\n", pLight->Type);
2148 /* Update the live definitions if the light is currently assigned a glIndex */
2149 if (object->glIndex != -1) {
2150 setup_light(iface, object->glIndex, object);
2152 return D3D_OK;
2155 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2156 PLIGHTINFOEL *lightInfo = NULL;
2157 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2158 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2160 /* Locate the light in the live lights */
2161 lightInfo = This->stateBlock->lights;
2162 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2164 if (lightInfo == NULL) {
2165 TRACE("Light information requested but light not defined\n");
2166 return D3DERR_INVALIDCALL;
2169 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
2170 return D3D_OK;
2173 /*****
2174 * Get / Set Light Enable
2175 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2176 *****/
2177 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2178 PLIGHTINFOEL *lightInfo = NULL;
2179 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2180 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2182 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2183 if (This->isRecordingState) {
2184 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2185 if (NULL == lightInfo) {
2186 return D3DERR_OUTOFVIDEOMEMORY;
2188 lightInfo->OriginalIndex = Index;
2189 lightInfo->glIndex = -1;
2190 lightInfo->enabledChanged = TRUE;
2192 /* Add to the END of the chain of lights changes to be replayed */
2193 if (This->updateStateBlock->lights == NULL) {
2194 This->updateStateBlock->lights = lightInfo;
2195 } else {
2196 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2197 while (temp->next != NULL) temp=temp->next;
2198 temp->next = lightInfo;
2200 TRACE("Recording... not performing anything more\n");
2201 return D3D_OK;
2204 /* Not recording... So, locate the light in the live lights */
2205 lightInfo = This->stateBlock->lights;
2206 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2208 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2209 if (lightInfo == NULL) {
2210 D3DLIGHT9 lightParms;
2211 /* Warning - untested code :-) Prob safe to change fixme to a trace but
2212 wait until someone confirms it seems to work! */
2213 TRACE("Light enabled requested but light not defined, so defining one!\n");
2214 lightParms.Type = D3DLIGHT_DIRECTIONAL;
2215 lightParms.Diffuse.r = 1.0;
2216 lightParms.Diffuse.g = 1.0;
2217 lightParms.Diffuse.b = 1.0;
2218 lightParms.Diffuse.a = 0.0;
2219 lightParms.Specular.r = 0.0;
2220 lightParms.Specular.g = 0.0;
2221 lightParms.Specular.b = 0.0;
2222 lightParms.Specular.a = 0.0;
2223 lightParms.Ambient.r = 0.0;
2224 lightParms.Ambient.g = 0.0;
2225 lightParms.Ambient.b = 0.0;
2226 lightParms.Ambient.a = 0.0;
2227 lightParms.Position.x = 0.0;
2228 lightParms.Position.y = 0.0;
2229 lightParms.Position.z = 0.0;
2230 lightParms.Direction.x = 0.0;
2231 lightParms.Direction.y = 0.0;
2232 lightParms.Direction.z = 1.0;
2233 lightParms.Range = 0.0;
2234 lightParms.Falloff = 0.0;
2235 lightParms.Attenuation0 = 0.0;
2236 lightParms.Attenuation1 = 0.0;
2237 lightParms.Attenuation2 = 0.0;
2238 lightParms.Theta = 0.0;
2239 lightParms.Phi = 0.0;
2240 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
2242 /* Search for it again! Should be fairly quick as near head of list */
2243 lightInfo = This->stateBlock->lights;
2244 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2245 if (lightInfo == NULL) {
2246 FIXME("Adding default lights has failed dismally\n");
2247 return D3DERR_INVALIDCALL;
2251 /* OK, we now have a light... */
2252 if (Enable == FALSE) {
2254 /* If we are disabling it, check it was enabled, and
2255 still only do something if it has assigned a glIndex (which it should have!) */
2256 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2257 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2258 ENTER_GL();
2259 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2260 checkGLcall("glDisable GL_LIGHT0+Index");
2261 LEAVE_GL();
2262 } else {
2263 TRACE("Nothing to do as light was not enabled\n");
2265 lightInfo->lightEnabled = FALSE;
2266 } else {
2268 /* We are enabling it. If it is enabled, it's really simple */
2269 if (lightInfo->lightEnabled) {
2270 /* nop */
2271 TRACE("Nothing to do as light was enabled\n");
2273 /* If it already has a glIndex, it's still simple */
2274 } else if (lightInfo->glIndex != -1) {
2275 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2276 lightInfo->lightEnabled = TRUE;
2277 ENTER_GL();
2278 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2279 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2280 LEAVE_GL();
2282 /* Otherwise got to find space - lights are ordered gl indexes first */
2283 } else {
2284 PLIGHTINFOEL *bsf = NULL;
2285 PLIGHTINFOEL *pos = This->stateBlock->lights;
2286 PLIGHTINFOEL *prev = NULL;
2287 int Index= 0;
2288 int glIndex = -1;
2290 /* Try to minimize changes as much as possible */
2291 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2293 /* Try to remember which index can be replaced if necessary */
2294 if (bsf==NULL && pos->lightEnabled == FALSE) {
2295 /* Found a light we can replace, save as best replacement */
2296 bsf = pos;
2299 /* Step to next space */
2300 prev = pos;
2301 pos = pos->next;
2302 Index ++;
2305 /* If we have too many active lights, fail the call */
2306 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2307 FIXME("Program requests too many concurrent lights\n");
2308 return D3DERR_INVALIDCALL;
2310 /* If we have allocated all lights, but not all are enabled,
2311 reuse one which is not enabled */
2312 } else if (Index == This->maxConcurrentLights) {
2313 /* use bsf - Simply swap the new light and the BSF one */
2314 PLIGHTINFOEL *bsfNext = bsf->next;
2315 PLIGHTINFOEL *bsfPrev = bsf->prev;
2317 /* Sort out ends */
2318 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2319 if (bsf->prev != NULL) {
2320 bsf->prev->next = lightInfo;
2321 } else {
2322 This->stateBlock->lights = lightInfo;
2325 /* If not side by side, lots of chains to update */
2326 if (bsf->next != lightInfo) {
2327 lightInfo->prev->next = bsf;
2328 bsf->next->prev = lightInfo;
2329 bsf->next = lightInfo->next;
2330 bsf->prev = lightInfo->prev;
2331 lightInfo->next = bsfNext;
2332 lightInfo->prev = bsfPrev;
2334 } else {
2335 /* Simple swaps */
2336 bsf->prev = lightInfo;
2337 bsf->next = lightInfo->next;
2338 lightInfo->next = bsf;
2339 lightInfo->prev = bsfPrev;
2343 /* Update states */
2344 glIndex = bsf->glIndex;
2345 bsf->glIndex = -1;
2346 lightInfo->glIndex = glIndex;
2347 lightInfo->lightEnabled = TRUE;
2349 /* Finally set up the light in gl itself */
2350 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2351 ENTER_GL();
2352 setup_light(iface, glIndex, lightInfo);
2353 glEnable(GL_LIGHT0 + glIndex);
2354 checkGLcall("glEnable GL_LIGHT0 new setup");
2355 LEAVE_GL();
2357 /* If we reached the end of the allocated lights, with space in the
2358 gl lights, setup a new light */
2359 } else if (pos->glIndex == -1) {
2361 /* We reached the end of the allocated gl lights, so already
2362 know the index of the next one! */
2363 glIndex = Index;
2364 lightInfo->glIndex = glIndex;
2365 lightInfo->lightEnabled = TRUE;
2367 /* In an ideal world, it's already in the right place */
2368 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2369 /* No need to move it */
2370 } else {
2371 /* Remove this light from the list */
2372 lightInfo->prev->next = lightInfo->next;
2373 if (lightInfo->next != NULL) {
2374 lightInfo->next->prev = lightInfo->prev;
2377 /* Add in at appropriate place (inbetween prev and pos) */
2378 lightInfo->prev = prev;
2379 lightInfo->next = pos;
2380 if (prev == NULL) {
2381 This->stateBlock->lights = lightInfo;
2382 } else {
2383 prev->next = lightInfo;
2385 if (pos != NULL) {
2386 pos->prev = lightInfo;
2390 /* Finally set up the light in gl itself */
2391 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2392 ENTER_GL();
2393 setup_light(iface, glIndex, lightInfo);
2394 glEnable(GL_LIGHT0 + glIndex);
2395 checkGLcall("glEnable GL_LIGHT0 new setup");
2396 LEAVE_GL();
2401 return D3D_OK;
2404 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2406 PLIGHTINFOEL *lightInfo = NULL;
2407 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2408 TRACE("(%p) : for idx(%ld)\n", This, Index);
2410 /* Locate the light in the live lights */
2411 lightInfo = This->stateBlock->lights;
2412 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2414 if (lightInfo == NULL) {
2415 TRACE("Light enabled state requested but light not defined\n");
2416 return D3DERR_INVALIDCALL;
2418 *pEnable = lightInfo->lightEnabled;
2419 return D3D_OK;
2422 /*****
2423 * Get / Set Clip Planes
2424 *****/
2425 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2426 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2427 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2429 /* Validate Index */
2430 if (Index >= GL_LIMITS(clipplanes)) {
2431 TRACE("Application has requested clipplane this device doesn't support\n");
2432 return D3DERR_INVALIDCALL;
2435 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2436 This->updateStateBlock->set.clipplane[Index] = TRUE;
2437 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2438 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2439 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2440 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2442 /* Handle recording of state blocks */
2443 if (This->isRecordingState) {
2444 TRACE("Recording... not performing anything\n");
2445 return D3D_OK;
2448 /* Apply it */
2450 ENTER_GL();
2452 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2453 glMatrixMode(GL_MODELVIEW);
2454 glPushMatrix();
2455 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2457 TRACE("Clipplane [%f,%f,%f,%f]\n",
2458 This->updateStateBlock->clipplane[Index][0],
2459 This->updateStateBlock->clipplane[Index][1],
2460 This->updateStateBlock->clipplane[Index][2],
2461 This->updateStateBlock->clipplane[Index][3]);
2462 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2463 checkGLcall("glClipPlane");
2465 glPopMatrix();
2466 LEAVE_GL();
2468 return D3D_OK;
2471 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2472 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2473 TRACE("(%p) : for idx %ld\n", This, Index);
2475 /* Validate Index */
2476 if (Index >= GL_LIMITS(clipplanes)) {
2477 TRACE("Application has requested clipplane this device doesn't support\n");
2478 return D3DERR_INVALIDCALL;
2481 pPlane[0] = This->stateBlock->clipplane[Index][0];
2482 pPlane[1] = This->stateBlock->clipplane[Index][1];
2483 pPlane[2] = This->stateBlock->clipplane[Index][2];
2484 pPlane[3] = This->stateBlock->clipplane[Index][3];
2485 return D3D_OK;
2488 /*****
2489 * Get / Set Clip Plane Status
2490 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2491 *****/
2492 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2493 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2494 FIXME("(%p) : stub\n", This);
2495 if (NULL == pClipStatus) {
2496 return D3DERR_INVALIDCALL;
2498 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2499 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2500 return D3D_OK;
2503 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2504 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2505 FIXME("(%p) : stub\n", This);
2506 if (NULL == pClipStatus) {
2507 return D3DERR_INVALIDCALL;
2509 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2510 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2511 return D3D_OK;
2514 /*****
2515 * Get / Set Material
2516 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2517 *****/
2518 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2519 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2521 This->updateStateBlock->changed.material = TRUE;
2522 This->updateStateBlock->set.material = TRUE;
2523 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2525 /* Handle recording of state blocks */
2526 if (This->isRecordingState) {
2527 TRACE("Recording... not performing anything\n");
2528 return D3D_OK;
2531 ENTER_GL();
2532 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2533 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2534 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2535 pMaterial->Ambient.b, pMaterial->Ambient.a);
2536 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2537 pMaterial->Specular.b, pMaterial->Specular.a);
2538 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2539 pMaterial->Emissive.b, pMaterial->Emissive.a);
2540 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2542 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2543 checkGLcall("glMaterialfv(GL_AMBIENT)");
2544 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2545 checkGLcall("glMaterialfv(GL_DIFFUSE)");
2547 /* Only change material color if specular is enabled, otherwise it is set to black */
2548 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2549 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2550 checkGLcall("glMaterialfv(GL_SPECULAR");
2551 } else {
2552 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2553 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2554 checkGLcall("glMaterialfv(GL_SPECULAR");
2556 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2557 checkGLcall("glMaterialfv(GL_EMISSION)");
2558 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2559 checkGLcall("glMaterialf(GL_SHININESS");
2561 LEAVE_GL();
2562 return D3D_OK;
2565 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2566 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2567 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2568 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2569 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2570 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2571 pMaterial->Ambient.b, pMaterial->Ambient.a);
2572 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2573 pMaterial->Specular.b, pMaterial->Specular.a);
2574 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2575 pMaterial->Emissive.b, pMaterial->Emissive.a);
2576 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2578 return D3D_OK;
2581 /*****
2582 * Get / Set Indices
2583 *****/
2584 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2585 UINT BaseVertexIndex) {
2586 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2587 IWineD3DIndexBuffer *oldIdxs;
2589 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2590 oldIdxs = This->updateStateBlock->pIndexData;
2592 This->updateStateBlock->changed.indices = TRUE;
2593 This->updateStateBlock->set.indices = TRUE;
2594 This->updateStateBlock->pIndexData = pIndexData;
2595 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2597 /* Handle recording of state blocks */
2598 if (This->isRecordingState) {
2599 TRACE("Recording... not performing anything\n");
2600 return D3D_OK;
2603 if (pIndexData) {
2604 IUnknown *indexBufferParent;
2605 /* Getting the parent causes a addRef... it gets released when the indicies are clear */
2606 IWineD3DIndexBuffer_GetParent(pIndexData, &indexBufferParent);
2608 if (oldIdxs) {
2609 IUnknown *indexBufferParent;
2610 IWineD3DIndexBuffer_GetParent(oldIdxs, &indexBufferParent);
2611 IUnknown_Release(indexBufferParent);
2612 IUnknown_Release(indexBufferParent);
2614 return D3D_OK;
2617 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2618 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2620 *ppIndexData = This->stateBlock->pIndexData;
2622 /* up ref count on ppindexdata */
2623 if (*ppIndexData) {
2624 IWineD3DIndexBuffer_AddRef(*ppIndexData);
2625 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2626 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
2627 }else{
2628 TRACE("(%p) No index data set\n", This);
2630 TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
2632 return D3D_OK;
2635 /*****
2636 * Get / Set Viewports
2637 *****/
2638 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2639 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2641 TRACE("(%p)\n", This);
2642 This->updateStateBlock->changed.viewport = TRUE;
2643 This->updateStateBlock->set.viewport = TRUE;
2644 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2646 /* Handle recording of state blocks */
2647 if (This->isRecordingState) {
2648 TRACE("Recording... not performing anything\n");
2649 return D3D_OK;
2652 ENTER_GL();
2654 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2655 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2657 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2658 checkGLcall("glDepthRange");
2659 /* Note: GL requires lower left, DirectX supplies upper left */
2660 /* TODO: replace usage of renderTarget with context management */
2661 glViewport(pViewport->X,
2662 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2663 pViewport->Width, pViewport->Height);
2665 checkGLcall("glViewport");
2667 LEAVE_GL();
2669 return D3D_OK;
2673 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2674 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2675 TRACE("(%p)\n", This);
2676 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2677 return D3D_OK;
2680 /*****
2681 * Get / Set Render States
2682 * TODO: Verify against dx9 definitions
2683 *****/
2684 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2686 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2687 DWORD OldValue = This->stateBlock->renderState[State];
2689 /* Simple way of referring to either a DWORD or a 4 byte float */
2690 union {
2691 DWORD d;
2692 float f;
2693 } tmpvalue;
2695 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2696 This->updateStateBlock->changed.renderState[State] = TRUE;
2697 This->updateStateBlock->set.renderState[State] = TRUE;
2698 This->updateStateBlock->renderState[State] = Value;
2700 /* Handle recording of state blocks */
2701 if (This->isRecordingState) {
2702 TRACE("Recording... not performing anything\n");
2703 return D3D_OK;
2706 ENTER_GL();
2708 switch (State) {
2709 case WINED3DRS_FILLMODE :
2710 switch ((D3DFILLMODE) Value) {
2711 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2712 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2713 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2714 default:
2715 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
2717 checkGLcall("glPolygonMode (fillmode)");
2718 break;
2720 case WINED3DRS_LIGHTING :
2721 if (Value) {
2722 glEnable(GL_LIGHTING);
2723 checkGLcall("glEnable GL_LIGHTING");
2724 } else {
2725 glDisable(GL_LIGHTING);
2726 checkGLcall("glDisable GL_LIGHTING");
2728 break;
2730 case WINED3DRS_ZENABLE :
2731 switch ((D3DZBUFFERTYPE) Value) {
2732 case D3DZB_FALSE:
2733 glDisable(GL_DEPTH_TEST);
2734 checkGLcall("glDisable GL_DEPTH_TEST");
2735 break;
2736 case D3DZB_TRUE:
2737 glEnable(GL_DEPTH_TEST);
2738 checkGLcall("glEnable GL_DEPTH_TEST");
2739 break;
2740 case D3DZB_USEW:
2741 glEnable(GL_DEPTH_TEST);
2742 checkGLcall("glEnable GL_DEPTH_TEST");
2743 FIXME("W buffer is not well handled\n");
2744 break;
2745 default:
2746 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2748 break;
2750 case WINED3DRS_CULLMODE :
2752 /* If we are culling "back faces with clockwise vertices" then
2753 set front faces to be counter clockwise and enable culling
2754 of back faces */
2755 switch ((D3DCULL) Value) {
2756 case D3DCULL_NONE:
2757 glDisable(GL_CULL_FACE);
2758 checkGLcall("glDisable GL_CULL_FACE");
2759 break;
2760 case D3DCULL_CW:
2761 glEnable(GL_CULL_FACE);
2762 checkGLcall("glEnable GL_CULL_FACE");
2763 if (This->renderUpsideDown) {
2764 glFrontFace(GL_CW);
2765 checkGLcall("glFrontFace GL_CW");
2766 } else {
2767 glFrontFace(GL_CCW);
2768 checkGLcall("glFrontFace GL_CCW");
2770 glCullFace(GL_BACK);
2771 break;
2772 case D3DCULL_CCW:
2773 glEnable(GL_CULL_FACE);
2774 checkGLcall("glEnable GL_CULL_FACE");
2775 if (This->renderUpsideDown) {
2776 glFrontFace(GL_CCW);
2777 checkGLcall("glFrontFace GL_CCW");
2778 } else {
2779 glFrontFace(GL_CW);
2780 checkGLcall("glFrontFace GL_CW");
2782 glCullFace(GL_BACK);
2783 break;
2784 default:
2785 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2787 break;
2789 case WINED3DRS_SHADEMODE :
2790 switch ((D3DSHADEMODE) Value) {
2791 case D3DSHADE_FLAT:
2792 glShadeModel(GL_FLAT);
2793 checkGLcall("glShadeModel");
2794 break;
2795 case D3DSHADE_GOURAUD:
2796 glShadeModel(GL_SMOOTH);
2797 checkGLcall("glShadeModel");
2798 break;
2799 case D3DSHADE_PHONG:
2800 FIXME("D3DSHADE_PHONG isn't supported?\n");
2802 LEAVE_GL();
2803 return D3DERR_INVALIDCALL;
2804 default:
2805 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2807 break;
2809 case WINED3DRS_DITHERENABLE :
2810 if (Value) {
2811 glEnable(GL_DITHER);
2812 checkGLcall("glEnable GL_DITHER");
2813 } else {
2814 glDisable(GL_DITHER);
2815 checkGLcall("glDisable GL_DITHER");
2817 break;
2819 case WINED3DRS_ZWRITEENABLE :
2820 if (Value) {
2821 glDepthMask(1);
2822 checkGLcall("glDepthMask");
2823 } else {
2824 glDepthMask(0);
2825 checkGLcall("glDepthMask");
2827 break;
2829 case WINED3DRS_ZFUNC :
2831 int glParm = GL_LESS;
2833 switch ((D3DCMPFUNC) Value) {
2834 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2835 case D3DCMP_LESS: glParm=GL_LESS; break;
2836 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2837 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2838 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2839 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2840 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2841 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2842 default:
2843 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2845 glDepthFunc(glParm);
2846 checkGLcall("glDepthFunc");
2848 break;
2850 case WINED3DRS_AMBIENT :
2852 float col[4];
2853 D3DCOLORTOGLFLOAT4(Value, col);
2854 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2855 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2856 checkGLcall("glLightModel for MODEL_AMBIENT");
2859 break;
2861 case WINED3DRS_ALPHABLENDENABLE :
2862 if (Value) {
2863 glEnable(GL_BLEND);
2864 checkGLcall("glEnable GL_BLEND");
2865 } else {
2866 glDisable(GL_BLEND);
2867 checkGLcall("glDisable GL_BLEND");
2869 break;
2871 case WINED3DRS_SRCBLEND :
2872 case WINED3DRS_DESTBLEND :
2874 int newVal = GL_ZERO;
2875 switch (Value) {
2876 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2877 case D3DBLEND_ONE : newVal = GL_ONE; break;
2878 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2879 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2880 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2881 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2882 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2883 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2884 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2885 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2886 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2888 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2889 This->srcBlend = newVal;
2890 This->dstBlend = newVal;
2891 break;
2893 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2894 This->srcBlend = newVal;
2895 This->dstBlend = newVal;
2896 break;
2897 default:
2898 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2901 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2902 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2903 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2904 glBlendFunc(This->srcBlend, This->dstBlend);
2906 checkGLcall("glBlendFunc");
2908 break;
2910 case WINED3DRS_ALPHATESTENABLE :
2911 if (Value) {
2912 glEnable(GL_ALPHA_TEST);
2913 checkGLcall("glEnable GL_ALPHA_TEST");
2914 } else {
2915 glDisable(GL_ALPHA_TEST);
2916 checkGLcall("glDisable GL_ALPHA_TEST");
2918 break;
2920 case WINED3DRS_ALPHAFUNC :
2922 int glParm = GL_LESS;
2923 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2925 switch ((D3DCMPFUNC) Value) {
2926 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2927 case D3DCMP_LESS: glParm = GL_LESS; break;
2928 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2929 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2930 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2931 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2932 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2933 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2934 default:
2935 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2937 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2938 glAlphaFunc(glParm, ref);
2939 This->alphafunc = glParm;
2940 checkGLcall("glAlphaFunc");
2942 break;
2944 case WINED3DRS_ALPHAREF :
2946 int glParm = This->alphafunc;
2947 float ref = 1.0f;
2949 ref = ((float) Value) / 255.0f;
2950 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2951 glAlphaFunc(glParm, ref);
2952 checkGLcall("glAlphaFunc");
2954 break;
2956 case WINED3DRS_CLIPPLANEENABLE :
2957 case WINED3DRS_CLIPPING :
2959 /* Ensure we only do the changed clip planes */
2960 DWORD enable = 0xFFFFFFFF;
2961 DWORD disable = 0x00000000;
2963 /* If enabling / disabling all */
2964 if (State == WINED3DRS_CLIPPING) {
2965 if (Value) {
2966 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2967 disable = 0x00;
2968 } else {
2969 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2970 enable = 0x00;
2972 } else {
2973 enable = Value & ~OldValue;
2974 disable = ~Value & OldValue;
2977 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2978 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2979 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2980 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2981 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2982 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2984 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2985 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2986 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2987 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2988 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2989 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2991 /** update clipping status */
2992 if (enable) {
2993 This->stateBlock->clip_status.ClipUnion = 0;
2994 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
2995 } else {
2996 This->stateBlock->clip_status.ClipUnion = 0;
2997 This->stateBlock->clip_status.ClipIntersection = 0;
3000 break;
3002 case WINED3DRS_BLENDOP :
3004 int glParm = GL_FUNC_ADD;
3006 switch ((D3DBLENDOP) Value) {
3007 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
3008 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
3009 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3010 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
3011 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
3012 default:
3013 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
3015 TRACE("glBlendEquation(%x)\n", glParm);
3016 glBlendEquation(glParm);
3017 checkGLcall("glBlendEquation");
3019 break;
3021 case WINED3DRS_TEXTUREFACTOR :
3023 unsigned int i;
3025 /* Note the texture color applies to all textures whereas
3026 GL_TEXTURE_ENV_COLOR applies to active only */
3027 float col[4];
3028 D3DCOLORTOGLFLOAT4(Value, col);
3029 /* Set the default alpha blend color */
3030 glBlendColor(col[0], col[1], col[2], col[3]);
3031 checkGLcall("glBlendColor");
3033 /* And now the default texture color as well */
3034 for (i = 0; i < GL_LIMITS(textures); i++) {
3036 /* Note the D3DRS value applies to all textures, but GL has one
3037 per texture, so apply it now ready to be used! */
3038 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3039 GLACTIVETEXTURE(i);
3040 } else if (i>0) {
3041 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3044 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3045 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3048 break;
3050 case WINED3DRS_SPECULARENABLE :
3052 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3053 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3054 specular color. This is wrong:
3055 Separate specular color means the specular colour is maintained separately, whereas
3056 single color means it is merged in. However in both cases they are being used to
3057 some extent.
3058 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3059 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3060 running 1.4 yet!
3062 if (Value) {
3063 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3064 checkGLcall("glMaterialfv");
3065 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3066 glEnable(GL_COLOR_SUM_EXT);
3067 } else {
3068 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3070 checkGLcall("glEnable(GL_COLOR_SUM)");
3071 } else {
3072 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3074 /* for the case of enabled lighting: */
3075 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3076 checkGLcall("glMaterialfv");
3078 /* for the case of disabled lighting: */
3079 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3080 glDisable(GL_COLOR_SUM_EXT);
3081 } else {
3082 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3084 checkGLcall("glDisable(GL_COLOR_SUM)");
3087 break;
3089 case WINED3DRS_STENCILENABLE :
3090 if (Value) {
3091 glEnable(GL_STENCIL_TEST);
3092 checkGLcall("glEnable GL_STENCIL_TEST");
3093 } else {
3094 glDisable(GL_STENCIL_TEST);
3095 checkGLcall("glDisable GL_STENCIL_TEST");
3097 break;
3099 case WINED3DRS_STENCILFUNC :
3101 int glParm = GL_ALWAYS;
3102 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3103 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3105 switch ((D3DCMPFUNC) Value) {
3106 case D3DCMP_NEVER: glParm=GL_NEVER; break;
3107 case D3DCMP_LESS: glParm=GL_LESS; break;
3108 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
3109 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
3110 case D3DCMP_GREATER: glParm=GL_GREATER; break;
3111 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
3112 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
3113 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
3114 default:
3115 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3117 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3118 This->stencilfunc = glParm;
3119 glStencilFunc(glParm, ref, mask);
3120 checkGLcall("glStencilFunc");
3122 break;
3124 case WINED3DRS_STENCILREF :
3126 int glParm = This->stencilfunc;
3127 int ref = 0;
3128 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3130 ref = Value;
3131 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3132 glStencilFunc(glParm, ref, mask);
3133 checkGLcall("glStencilFunc");
3135 break;
3137 case WINED3DRS_STENCILMASK :
3139 int glParm = This->stencilfunc;
3140 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3141 GLuint mask = Value;
3143 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3144 glStencilFunc(glParm, ref, mask);
3145 checkGLcall("glStencilFunc");
3147 break;
3149 case WINED3DRS_STENCILFAIL :
3151 GLenum fail ;
3152 GLint zpass ;
3153 GLint zfail ;
3155 fail = StencilOp(Value);
3156 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
3157 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
3158 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
3159 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
3161 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3162 glStencilOp(fail, zfail, zpass);
3163 checkGLcall("glStencilOp(fail, zfail, zpass);");
3165 break;
3166 case WINED3DRS_STENCILZFAIL :
3168 GLint fail ;
3169 GLint zpass ;
3170 GLenum zfail ;
3172 glGetIntegerv(GL_STENCIL_FAIL, &fail);
3173 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
3174 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
3175 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
3176 zfail = StencilOp(Value);
3178 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3179 glStencilOp(fail, zfail, zpass);
3180 checkGLcall("glStencilOp(fail, zfail, zpass);");
3182 break;
3183 case WINED3DRS_STENCILPASS :
3185 GLint fail ;
3186 GLenum zpass ;
3187 GLint zfail ;
3189 glGetIntegerv(GL_STENCIL_FAIL, &fail);
3190 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
3191 zpass = StencilOp(Value);
3192 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
3193 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
3195 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3196 glStencilOp(fail, zfail, zpass);
3197 checkGLcall("glStencilOp(fail, zfail, zpass);");
3199 break;
3201 case WINED3DRS_STENCILWRITEMASK :
3203 glStencilMask(Value);
3204 TRACE("glStencilMask(%lu)\n", Value);
3205 checkGLcall("glStencilMask");
3207 break;
3209 case WINED3DRS_FOGENABLE :
3211 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
3212 glEnable(GL_FOG);
3213 checkGLcall("glEnable GL_FOG");
3214 } else {
3215 glDisable(GL_FOG);
3216 checkGLcall("glDisable GL_FOG");
3219 break;
3221 case WINED3DRS_RANGEFOGENABLE :
3223 if (Value) {
3224 TRACE("Enabled RANGEFOG");
3225 } else {
3226 TRACE("Disabled RANGEFOG");
3229 break;
3231 case WINED3DRS_FOGCOLOR :
3233 float col[4];
3234 D3DCOLORTOGLFLOAT4(Value, col);
3235 /* Set the default alpha blend color */
3236 glFogfv(GL_FOG_COLOR, &col[0]);
3237 checkGLcall("glFog GL_FOG_COLOR");
3239 break;
3241 case WINED3DRS_FOGTABLEMODE :
3243 glHint(GL_FOG_HINT, GL_NICEST);
3244 switch (Value) {
3245 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3246 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3247 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3248 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3249 default:
3250 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3252 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3253 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3256 break;
3258 case WINED3DRS_FOGVERTEXMODE :
3260 glHint(GL_FOG_HINT, GL_FASTEST);
3261 switch (Value) {
3262 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3263 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3264 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3265 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3266 default:
3267 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3269 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3270 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
3273 break;
3275 case WINED3DRS_FOGSTART :
3277 tmpvalue.d = Value;
3278 glFogfv(GL_FOG_START, &tmpvalue.f);
3279 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3280 TRACE("Fog Start == %f\n", tmpvalue.f);
3282 break;
3284 case WINED3DRS_FOGEND :
3286 tmpvalue.d = Value;
3287 glFogfv(GL_FOG_END, &tmpvalue.f);
3288 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3289 TRACE("Fog End == %f\n", tmpvalue.f);
3291 break;
3293 case WINED3DRS_FOGDENSITY :
3295 tmpvalue.d = Value;
3296 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3297 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3299 break;
3301 case WINED3DRS_VERTEXBLEND :
3303 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3304 TRACE("Vertex Blending state to %ld\n", Value);
3306 break;
3308 case WINED3DRS_TWEENFACTOR :
3310 tmpvalue.d = Value;
3311 This->updateStateBlock->tween_factor = tmpvalue.f;
3312 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3314 break;
3316 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
3318 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3320 break;
3322 case WINED3DRS_COLORVERTEX :
3323 case WINED3DRS_DIFFUSEMATERIALSOURCE :
3324 case WINED3DRS_SPECULARMATERIALSOURCE :
3325 case WINED3DRS_AMBIENTMATERIALSOURCE :
3326 case WINED3DRS_EMISSIVEMATERIALSOURCE :
3328 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3330 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3331 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3332 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3333 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3334 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3335 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3337 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3338 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3339 Parm = GL_AMBIENT_AND_DIFFUSE;
3340 } else {
3341 Parm = GL_DIFFUSE;
3343 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3344 Parm = GL_AMBIENT;
3345 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3346 Parm = GL_EMISSION;
3347 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3348 Parm = GL_SPECULAR;
3349 } else {
3350 Parm = -1;
3353 if (Parm == -1) {
3354 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3355 } else {
3356 This->tracking_color = NEEDS_TRACKING;
3357 This->tracking_parm = Parm;
3360 } else {
3361 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3364 break;
3366 case WINED3DRS_LINEPATTERN :
3368 union {
3369 DWORD d;
3370 D3DLINEPATTERN lp;
3371 } tmppattern;
3372 tmppattern.d = Value;
3374 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3376 if (tmppattern.lp.wRepeatFactor) {
3377 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3378 checkGLcall("glLineStipple(repeat, linepattern)");
3379 glEnable(GL_LINE_STIPPLE);
3380 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3381 } else {
3382 glDisable(GL_LINE_STIPPLE);
3383 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3386 break;
3388 case WINED3DRS_ZBIAS : /* D3D8 only */
3390 if (Value) {
3391 tmpvalue.d = Value;
3392 TRACE("ZBias value %f\n", tmpvalue.f);
3393 glPolygonOffset(0, -tmpvalue.f);
3394 checkGLcall("glPolygonOffset(0, -Value)");
3395 glEnable(GL_POLYGON_OFFSET_FILL);
3396 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3397 glEnable(GL_POLYGON_OFFSET_LINE);
3398 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3399 glEnable(GL_POLYGON_OFFSET_POINT);
3400 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3401 } else {
3402 glDisable(GL_POLYGON_OFFSET_FILL);
3403 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3404 glDisable(GL_POLYGON_OFFSET_LINE);
3405 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3406 glDisable(GL_POLYGON_OFFSET_POINT);
3407 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3410 break;
3412 case WINED3DRS_NORMALIZENORMALS :
3413 if (Value) {
3414 glEnable(GL_NORMALIZE);
3415 checkGLcall("glEnable(GL_NORMALIZE);");
3416 } else {
3417 glDisable(GL_NORMALIZE);
3418 checkGLcall("glDisable(GL_NORMALIZE);");
3420 break;
3422 case WINED3DRS_POINTSIZE :
3423 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
3424 tmpvalue.d = Value;
3425 TRACE("Set point size to %f\n", tmpvalue.f);
3426 glPointSize(tmpvalue.f);
3427 checkGLcall("glPointSize(...);");
3428 break;
3430 case WINED3DRS_POINTSIZE_MIN :
3431 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3432 tmpvalue.d = Value;
3433 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3434 checkGLcall("glPointParameterfEXT(...);");
3435 } else {
3436 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3438 break;
3440 case WINED3DRS_POINTSIZE_MAX :
3441 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3442 tmpvalue.d = Value;
3443 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3444 checkGLcall("glPointParameterfEXT(...);");
3445 } else {
3446 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3448 break;
3450 case WINED3DRS_POINTSCALE_A :
3451 case WINED3DRS_POINTSCALE_B :
3452 case WINED3DRS_POINTSCALE_C :
3453 case WINED3DRS_POINTSCALEENABLE :
3455 /* If enabled, supply the parameters, otherwise fall back to defaults */
3456 if (This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3457 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3458 /* TODO: Correct the scaling (this hack seems to be good enough for every demo that uses point sprites!) */
3459 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A])/ This->stateBlock->viewport.Width;
3460 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B])/ This->stateBlock->viewport.Height;
3461 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) *
3462 2.0f /(This->stateBlock->viewport.Width * This->stateBlock->viewport.Height);
3464 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3465 TRACE("glPointParameterfvARB %f %f %f\n", att[0], att[1], att[2]);
3466 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3467 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3468 } else {
3469 TRACE("WINED3DRS_POINTSCALEENABLE not supported on this opengl\n");
3471 } else {
3472 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3473 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3474 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3475 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3476 } else {
3477 TRACE("WINED3DRS_POINTSCALEENABLE not supported, but not on either\n");
3480 break;
3483 case WINED3DRS_COLORWRITEENABLE :
3485 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3486 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3487 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3488 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3489 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3490 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3491 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3492 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3493 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3494 checkGLcall("glColorMask(...)");
3496 break;
3498 case WINED3DRS_LOCALVIEWER :
3500 GLint state = (Value) ? 1 : 0;
3501 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3502 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3504 break;
3506 case WINED3DRS_LASTPIXEL :
3508 if (Value) {
3509 TRACE("Last Pixel Drawing Enabled\n");
3510 } else {
3511 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3514 break;
3516 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3518 if (Value) {
3519 TRACE("Software Processing Enabled\n");
3520 } else {
3521 TRACE("Software Processing Disabled\n");
3524 break;
3526 /** not supported */
3527 case WINED3DRS_ZVISIBLE :
3529 LEAVE_GL();
3530 return D3DERR_INVALIDCALL;
3532 case WINED3DRS_POINTSPRITEENABLE :
3533 /* TODO: NV_POINT_SPRITE */
3534 if (GL_SUPPORT(ARB_POINT_SPRITE)) {
3535 if (Value != FALSE) {
3536 /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
3537 glDisable(GL_POINT_SMOOTH);
3538 /* Centre the texture on the vertex */
3539 VTRACE("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
3540 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
3542 VTRACE("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
3543 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
3544 checkGLcall("glTexEnvf(...)");
3545 VTRACE("glEnable( GL_POINT_SPRITE_ARB )\n");
3546 glEnable( GL_POINT_SPRITE_ARB );
3547 checkGLcall("glEnable(...)");
3548 } else {
3549 VTRACE("glDisable( GL_POINT_SPRITE_ARB )\n");
3550 glDisable( GL_POINT_SPRITE_ARB );
3551 checkGLcall("glEnable(...)");
3554 break;
3555 /* Unhandled yet...! */
3556 case WINED3DRS_EDGEANTIALIAS :
3557 case WINED3DRS_WRAP0 :
3558 case WINED3DRS_WRAP1 :
3559 case WINED3DRS_WRAP2 :
3560 case WINED3DRS_WRAP3 :
3561 case WINED3DRS_WRAP4 :
3562 case WINED3DRS_WRAP5 :
3563 case WINED3DRS_WRAP6 :
3564 case WINED3DRS_WRAP7 :
3566 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
3567 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
3568 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
3569 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
3570 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
3572 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
3574 TRACE("(%p)->(%d,%ld) Texture wraping not yet supported\n",This, State, Value);
3575 break;
3576 case WINED3DRS_MULTISAMPLEANTIALIAS :
3577 case WINED3DRS_MULTISAMPLEMASK :
3578 case WINED3DRS_PATCHEDGESTYLE :
3579 case WINED3DRS_PATCHSEGMENTS :
3580 case WINED3DRS_DEBUGMONITORTOKEN :
3581 case WINED3DRS_POSITIONORDER :
3582 case WINED3DRS_NORMALORDER :
3583 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3584 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3585 break;
3586 default:
3587 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3590 LEAVE_GL();
3592 return D3D_OK;
3595 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3596 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3597 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3598 *pValue = This->stateBlock->renderState[State];
3599 return D3D_OK;
3602 /*****
3603 * Get / Set Sampler States
3604 * TODO: Verify against dx9 definitions
3605 *****/
3607 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3608 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3610 * SetSampler is designed to allow for more than the standard up to 8 textures
3611 * and Geforce has stopped supporting more than 6 standard textures in openGL.
3612 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3614 * http://developer.nvidia.com/object/General_FAQ.html#t6
3616 * There are two new settings for GForce
3617 * the sampler one:
3618 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3619 * and the texture one:
3620 * GL_MAX_TEXTURE_COORDS_ARB.
3621 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3622 ******************/
3623 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
3624 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
3626 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
3627 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE, Sampler, Type);
3628 return D3DERR_INVALIDCALL;
3630 TRACE("Setting sampler %ld %d to %ld\n", Sampler, Type, Value);
3631 This->updateStateBlock->samplerState[Sampler][Type] = Value;
3632 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
3633 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
3635 /* Handle recording of state blocks */
3636 if (This->isRecordingState) {
3637 TRACE("Recording... not performing anything\n");
3638 return D3D_OK;
3641 return D3D_OK;
3644 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3645 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3646 /** TODO: check that sampler is in range **/
3647 *Value = This->updateStateBlock->samplerState[Sampler][Type];
3648 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
3650 return D3D_OK;
3653 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3654 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3655 ENTER_GL();
3657 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3658 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3659 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3660 LEAVE_GL();
3662 return D3D_OK;
3665 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3666 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3667 GLint scissorBox[4];
3669 ENTER_GL();
3670 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3671 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
3672 pRect->left = scissorBox[1];
3673 pRect->top = scissorBox[2];
3674 pRect->right = scissorBox[1] + scissorBox[3];
3675 pRect->bottom = scissorBox[2] + scissorBox[4];
3676 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3677 LEAVE_GL();
3678 return D3D_OK;
3681 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3682 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3684 TRACE("(%p) : pDecl=%p\n", This, pDecl);
3686 /* TODO: what about recording stateblocks? */
3687 if (NULL != pDecl) {
3688 IWineD3DVertexDeclaration_AddRef(pDecl);
3690 if (NULL != This->updateStateBlock->vertexDecl) {
3691 IWineD3DVertexDeclaration_Release(This->updateStateBlock->vertexDecl);
3693 This->updateStateBlock->vertexDecl = pDecl;
3694 This->updateStateBlock->changed.vertexDecl = TRUE;
3695 This->updateStateBlock->set.vertexDecl = TRUE;
3696 return D3D_OK;
3699 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3700 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3702 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3704 *ppDecl = This->updateStateBlock->vertexDecl;
3705 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3706 return D3D_OK;
3709 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
3710 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3711 IWineD3DVertexShader *oldShader = This->updateStateBlock->vertexShader;
3713 This->updateStateBlock->vertexShader = pShader;
3714 This->updateStateBlock->changed.vertexShader = TRUE;
3715 This->updateStateBlock->set.vertexShader = TRUE;
3717 if (This->isRecordingState) {
3718 TRACE("Recording... not performing anything\n");
3719 return D3D_OK;
3722 if (pShader != NULL) {
3723 IUnknown *newVertexShaderParent;
3724 /* GetParent will add a ref, so leave it hanging until the vertex buffer is cleared */
3725 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3726 IWineD3DVertexShader_GetParent(pShader, &newVertexShaderParent);
3727 } else {
3728 TRACE("Clear down the shader\n");
3730 if (oldShader != NULL) {
3731 IUnknown *oldVertexShaderParent;
3732 IWineD3DVertexShader_GetParent(oldShader, &oldVertexShaderParent);
3733 IUnknown_Release(oldVertexShaderParent);
3734 IUnknown_Release(oldVertexShaderParent);
3737 * TODO: merge HAL shaders context switching from prototype
3739 return D3D_OK;
3742 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
3743 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3745 if (NULL == ppShader) {
3746 return D3DERR_INVALIDCALL;
3748 *ppShader = This->stateBlock->vertexShader;
3749 if( NULL != *ppShader)
3750 IWineD3DVertexShader_AddRef(*ppShader);
3752 TRACE("(%p) : returning %p\n", This, *ppShader);
3753 return D3D_OK;
3756 #define GET_SHADER_CONSTANT(_vertexshaderconstant, _count, _sizecount) \
3757 count = min(_count, MAX_VSHADER_CONSTANTS - (StartRegister + 1)); \
3758 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3759 return D3DERR_INVALIDCALL; \
3760 memcpy(pConstantData, This->updateStateBlock->_vertexshaderconstant + (StartRegister * _sizecount), count * (sizeof(*pConstantData) * _sizecount));
3762 #define SET_SHADER_CONSTANT(_vertexshaderconstant, _count, _sizecount) \
3763 int count = min(_count, MAX_VSHADER_CONSTANTS - (StartRegister + 1)); \
3764 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3765 return D3DERR_INVALIDCALL; \
3766 memcpy(This->updateStateBlock->_vertexshaderconstant + (StartRegister * _sizecount), pConstantData, count * (sizeof(*pConstantData) * _sizecount)); \
3767 This->updateStateBlock->changed.vertexShader = TRUE; \
3768 This->updateStateBlock->set.vertexShader = TRUE;
3770 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
3771 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3772 int i;
3773 SET_SHADER_CONSTANT(vertexShaderConstantB, BoolCount, 1);
3775 /* populate the bitmap that says which constant type we should load */
3776 for (i = StartRegister; i < BoolCount + StartRegister; ++i) {
3777 This->updateStateBlock->changed.vertexShaderConstants[i] = TRUE;
3778 This->updateStateBlock->set.vertexShaderConstants[i] = TRUE;
3779 This->updateStateBlock->vertexShaderConstantT[i] = WINESHADERCNST_BOOL;
3780 TRACE("(%p) : Setting vsb %d to %d\n", This->updateStateBlock, i, pConstantData[i - StartRegister]);
3783 return D3D_OK;
3786 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
3787 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3788 int i, count;
3790 /* verify that the requested shader constant was populated with a boolean */
3791 for (i = StartRegister; i < BoolCount; ++i) {
3792 if (This->updateStateBlock->vertexShaderConstantT[i] != WINESHADERCNST_BOOL) {
3794 /* the constant for this register isn't a boolean */
3795 WARN("(%p) : Caller requested a boolean where stateblock (%p) entry is a %s. Returning D3DERR_INVALIDCALL\n", This,This->updateStateBlock,
3796 This->updateStateBlock->vertexShaderConstantT[i] == WINESHADERCNST_INTEGER ? "integer" : "float");
3797 return D3DERR_INVALIDCALL;
3801 GET_SHADER_CONSTANT(vertexShaderConstantB, BoolCount, 1);
3802 return D3D_OK;
3805 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
3806 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3807 int i;
3809 SET_SHADER_CONSTANT(vertexShaderConstantI, Vector4iCount, 4);
3811 /* populate the bitmap that says which constant type we should load */
3812 for (i = StartRegister; i < StartRegister + Vector4iCount; ++i) {
3813 This->updateStateBlock->changed.vertexShaderConstants[i] = TRUE;
3814 This->updateStateBlock->set.vertexShaderConstants[i] = TRUE;
3815 This->updateStateBlock->vertexShaderConstantT[i] = WINESHADERCNST_INTEGER;
3816 TRACE("(%p) : Setting vsi %d to %d\n", This->updateStateBlock, i, pConstantData[i - StartRegister]);
3819 return D3D_OK;
3822 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
3823 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3824 int i, count;
3826 /* verify that the requested shader constant was populated with a integer */
3827 for (i = StartRegister; i < Vector4iCount; ++i) {
3828 if (This->updateStateBlock->vertexShaderConstantT[i] != WINESHADERCNST_INTEGER) {
3830 /* the constant for this register isn't a integer */
3831 WARN("(%p) : Caller requested a integer where stateblock (%p) entry is a %s. Returning D3DERR_INVALIDCALL\n", This, This->updateStateBlock,
3832 This->updateStateBlock->vertexShaderConstantT[i] == WINESHADERCNST_BOOL ? "boolean" : "float");
3833 return D3DERR_INVALIDCALL;
3837 GET_SHADER_CONSTANT(vertexShaderConstantI, Vector4iCount, 4);
3839 return D3D_OK;
3842 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
3843 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3844 int i;
3846 SET_SHADER_CONSTANT(vertexShaderConstantF, Vector4fCount, 4);
3848 /* populate the bitmap that says which constant type we should load */
3849 for (i = StartRegister; i < StartRegister + Vector4fCount; ++i) {
3850 This->updateStateBlock->changed.vertexShaderConstants[i] = TRUE;
3851 This->updateStateBlock->set.vertexShaderConstants[i] = TRUE;
3852 This->updateStateBlock->vertexShaderConstantT[i] = WINESHADERCNST_FLOAT;
3853 TRACE("(%p) : Setting vsf %d to %f\n", This->updateStateBlock, i, pConstantData[i - StartRegister]);
3855 return D3D_OK;
3858 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
3859 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3860 int i, count;
3862 /* verify that the requested shader constant was populated with a float */
3863 for (i = StartRegister; i < Vector4fCount; ++i) {
3864 if (This->updateStateBlock->vertexShaderConstantT[i] != WINESHADERCNST_FLOAT) {
3866 /* the constant for this register isn't a float */
3867 WARN("(%p) : Caller requested a float where stateblock (%p) entry is a %s. Returning D3DERR_INVALIDCALL\n", This, This->updateStateBlock,
3868 This->updateStateBlock->vertexShaderConstantT[i] == WINESHADERCNST_BOOL ? "boolean" : "integer");
3869 return D3DERR_INVALIDCALL;
3875 GET_SHADER_CONSTANT(vertexShaderConstantF, Vector4fCount, 4);
3877 return D3D_OK;
3880 #undef SET_SHADER_CONSTANT
3881 #undef GET_SHADER_CONSTANT
3884 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
3885 IUnknown *parent;
3886 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3887 IWineD3DPixelShader *oldpShader = This->updateStateBlock->pixelShader;
3888 static BOOL showFixmes = TRUE;
3890 This->updateStateBlock->pixelShader = pShader;
3891 This->updateStateBlock->changed.pixelShader = TRUE;
3892 This->updateStateBlock->set.pixelShader = TRUE;
3894 if (pShader == NULL) {
3895 /* clear down the shader */
3896 TRACE("Clear down the shader\n");
3897 }else{
3898 if (showFixmes) {
3899 FIXME("(%p) : stub pShader(%p)\n", This, pShader);
3900 showFixmes = FALSE;
3904 /* Handle recording of state blocks */
3905 if (This->isRecordingState) {
3906 TRACE("Recording... not performing anything\n");
3907 return D3D_OK;
3910 * TODO: merge HAL shaders context switching from prototype
3913 /* manage reference counting. */
3914 if (pShader != NULL) {
3915 IWineD3DPixelShader_GetParent(pShader, &parent); /* get parent adds a ref for us*/
3918 if (oldpShader != NULL) {
3919 IWineD3DPixelShader_GetParent(oldpShader, &parent);
3920 IUnknown_Release(parent); /* once for the getparent */
3921 IUnknown_Release(parent); /* and once for the ref */
3924 return D3D_OK;
3927 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3928 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3930 if (ppShader == NULL) {
3931 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
3932 return D3DERR_INVALIDCALL;
3935 *ppShader = This->updateStateBlock->pixelShader;
3936 if (NULL != ppShader) {
3937 IWineD3DPixelShader_AddRef(*ppShader);
3939 TRACE("(%p) : returning %p\n", This, *ppShader);
3940 return D3D_OK;
3943 #define GET_SHADER_CONSTANT(_pixelshaderconstant, _count, _sizecount) \
3944 count = min(_count, MAX_PSHADER_CONSTANTS - (StartRegister + 1)); \
3945 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3946 return D3DERR_INVALIDCALL; \
3947 memcpy(pConstantData, This->updateStateBlock->_pixelshaderconstant + (StartRegister * _sizecount), count * (sizeof(*pConstantData) * _sizecount)); \
3950 #define SET_SHADER_CONSTANT(_pixelshaderconstant, _count, _sizecount) \
3951 int count = min(_count, MAX_PSHADER_CONSTANTS - (StartRegister + 1)); \
3952 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3953 return D3DERR_INVALIDCALL; \
3954 memcpy(This->updateStateBlock->_pixelshaderconstant + (StartRegister * _sizecount), pConstantData, count * (sizeof(*pConstantData) * _sizecount)); \
3955 This->updateStateBlock->changed.pixelShader = TRUE; \
3956 This->updateStateBlock->set.pixelShader = TRUE;
3959 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
3960 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3961 int i;
3963 SET_SHADER_CONSTANT(pixelShaderConstantB, BoolCount, 1);
3965 /* populate the bitmap that says which constant type we should load */
3966 for (i = StartRegister; i < BoolCount + StartRegister; ++i) {
3967 This->updateStateBlock->changed.pixelShaderConstants[i] = TRUE;
3968 This->updateStateBlock->set.pixelShaderConstants[i] = TRUE;
3969 This->updateStateBlock->pixelShaderConstantT[i] = WINESHADERCNST_BOOL;
3970 TRACE("(%p) : Setting psb %d to %d\n", This->updateStateBlock, i, pConstantData[i - StartRegister]);
3973 return D3D_OK;
3977 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
3978 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3979 int i, count;
3981 /* populate the bitmap that says which constant type we should load */
3982 for (i = StartRegister; i < BoolCount + StartRegister; ++i) {
3983 This->updateStateBlock->changed.pixelShaderConstants[i] = TRUE;
3984 This->updateStateBlock->set.pixelShaderConstants[i] = TRUE;
3985 This->updateStateBlock->pixelShaderConstantT[i] = WINESHADERCNST_BOOL;
3986 TRACE("(%p) : Setting psb %d to %d\n", This->updateStateBlock, i, pConstantData[i - StartRegister]);
3989 GET_SHADER_CONSTANT(pixelShaderConstantB, BoolCount, 1);
3991 return D3D_OK;
3994 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
3995 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3996 int i;
3998 SET_SHADER_CONSTANT(pixelShaderConstantI, Vector4iCount, 4);
4000 /* populate the bitmap that says which constant type we should load */
4001 for (i = StartRegister; i < Vector4iCount + StartRegister; ++i) {
4002 This->updateStateBlock->changed.pixelShaderConstants[i] = TRUE;
4003 This->updateStateBlock->set.pixelShaderConstants[i] = TRUE;
4004 This->updateStateBlock->pixelShaderConstantT[i] = WINESHADERCNST_INTEGER;
4005 TRACE("(%p) : Setting psb %d to %d\n", This->updateStateBlock, i, pConstantData[i - StartRegister]);
4008 return D3D_OK;
4011 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
4012 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4013 int i, count;
4015 /* verify that the requested shader constant was populated with a integer */
4016 for (i = StartRegister; i < Vector4iCount; ++i) {
4017 if (WINESHADERCNST_INTEGER != This->updateStateBlock->pixelShaderConstantT[i]) {
4019 /* the constant for this register isn't a integer */
4020 WARN("(%p) : Caller requested a integer where stateblock (%p) entry is a %s. Returning D3DERR_INVALIDCALL\n", This, This->updateStateBlock,
4021 WINESHADERCNST_BOOL == This->updateStateBlock->vertexShaderConstantT[i] ? "boolean" : "float");
4022 return D3DERR_INVALIDCALL;
4026 GET_SHADER_CONSTANT(pixelShaderConstantI, Vector4iCount, 4);
4028 return D3D_OK;
4031 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
4032 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4033 int i;
4034 SET_SHADER_CONSTANT(pixelShaderConstantF, Vector4fCount, 4);
4036 /* populate the bitmap that says which constant type we should load */
4037 for (i = StartRegister; i < Vector4fCount + StartRegister; ++i) {
4038 This->updateStateBlock->changed.pixelShaderConstants[i] = TRUE;
4039 This->updateStateBlock->set.pixelShaderConstants[i] = TRUE;
4040 This->updateStateBlock->pixelShaderConstantT[i] = WINESHADERCNST_FLOAT;
4041 TRACE("(%p) : Setting psb %d to %f\n", This->updateStateBlock, i, pConstantData[i - StartRegister]);
4044 return D3D_OK;
4047 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
4048 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4049 int i, count;
4051 /* verify that the requested shader constant was populated with a integer */
4052 for (i = StartRegister; i < Vector4fCount; ++i) {
4053 if (WINESHADERCNST_FLOAT != This->updateStateBlock->pixelShaderConstantT[i]) {
4055 /* the constant for this register isn't a float */
4056 WARN("(%p) : Caller requested a integer where stateblock (%p) entry is a %s. Returning D3DERR_INVALIDCALL\n", This, This->updateStateBlock,
4057 WINESHADERCNST_BOOL == This->updateStateBlock->vertexShaderConstantT[i] ? "boolean" : "integer");
4058 return D3DERR_INVALIDCALL;
4062 GET_SHADER_CONSTANT(pixelShaderConstantF, Vector4fCount, 4);
4064 return D3D_OK;
4067 #undef SET_SHADER_CONSTANT
4068 #undef GET_SHADER_CONSTANT
4070 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
4071 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4072 FIXME("(%p) : stub\n", This);
4073 return D3D_OK;
4076 /*****
4077 * Apply / Get / Set Texture Stage States
4078 * TODO: Verify against dx9 definitions
4079 *****/
4081 /* 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 callnig ApplyTextureStageState */
4082 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
4083 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4084 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
4085 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4087 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4089 /* Check that the stage is within limits */
4090 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4091 TRACE("Attempt to access invalid texture rejected\n");
4092 return;
4095 ENTER_GL();
4097 switch (Type) {
4098 case WINED3DTSS_ALPHAOP :
4099 case WINED3DTSS_COLOROP :
4100 /* nothing to do as moved to drawprim for now */
4101 break;
4102 case WINED3DTSS_ADDRESSW :
4103 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
4104 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
4105 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
4107 } else {
4108 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
4109 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
4110 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
4111 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
4113 #endif
4114 case WINED3DTSS_TEXCOORDINDEX :
4116 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
4118 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
4119 one flag, you can still specify an index value, which the system uses to
4120 determine the texture wrapping mode.
4121 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
4122 means use the vertex position (camera-space) as the input texture coordinates
4123 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
4124 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
4125 to the TEXCOORDINDEX value */
4128 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
4130 switch (Value & 0xFFFF0000) {
4131 case D3DTSS_TCI_PASSTHRU:
4132 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
4133 glDisable(GL_TEXTURE_GEN_S);
4134 glDisable(GL_TEXTURE_GEN_T);
4135 glDisable(GL_TEXTURE_GEN_R);
4136 glDisable(GL_TEXTURE_GEN_Q);
4137 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
4138 break;
4140 case D3DTSS_TCI_CAMERASPACEPOSITION:
4141 /* CameraSpacePosition means use the vertex position, transformed to camera space,
4142 as the input texture coordinates for this stage's texture transformation. This
4143 equates roughly to EYE_LINEAR */
4145 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4146 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4147 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4148 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4149 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4151 glMatrixMode(GL_MODELVIEW);
4152 glPushMatrix();
4153 glLoadIdentity();
4154 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4155 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4156 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4157 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4158 glPopMatrix();
4160 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
4161 glEnable(GL_TEXTURE_GEN_S);
4162 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4163 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4164 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4165 glEnable(GL_TEXTURE_GEN_T);
4166 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4167 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4168 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4169 glEnable(GL_TEXTURE_GEN_R);
4170 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4171 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4172 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4174 break;
4176 case D3DTSS_TCI_CAMERASPACENORMAL:
4178 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4179 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4180 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4181 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4182 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4183 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
4185 glMatrixMode(GL_MODELVIEW);
4186 glPushMatrix();
4187 glLoadIdentity();
4188 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4189 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4190 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4191 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4192 glPopMatrix();
4194 glEnable(GL_TEXTURE_GEN_S);
4195 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4196 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4197 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4198 glEnable(GL_TEXTURE_GEN_T);
4199 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4200 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4201 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4202 glEnable(GL_TEXTURE_GEN_R);
4203 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4204 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4205 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4208 break;
4210 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
4212 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4213 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4214 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4215 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4216 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4217 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
4219 glMatrixMode(GL_MODELVIEW);
4220 glPushMatrix();
4221 glLoadIdentity();
4222 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4223 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4224 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4225 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4226 glPopMatrix();
4228 glEnable(GL_TEXTURE_GEN_S);
4229 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4230 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4231 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4232 glEnable(GL_TEXTURE_GEN_T);
4233 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4234 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4235 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4236 glEnable(GL_TEXTURE_GEN_R);
4237 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4238 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4239 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4242 break;
4244 /* Unhandled types: */
4245 default:
4246 /* Todo: */
4247 /* ? disable GL_TEXTURE_GEN_n ? */
4248 glDisable(GL_TEXTURE_GEN_S);
4249 glDisable(GL_TEXTURE_GEN_T);
4250 glDisable(GL_TEXTURE_GEN_R);
4251 glDisable(GL_TEXTURE_GEN_Q);
4252 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
4253 break;
4256 break;
4258 /* Unhandled */
4259 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
4260 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);
4261 break;
4263 case WINED3DTSS_BUMPENVMAT00 :
4264 case WINED3DTSS_BUMPENVMAT01 :
4265 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
4266 break;
4267 case WINED3DTSS_BUMPENVMAT10 :
4268 case WINED3DTSS_BUMPENVMAT11 :
4269 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
4270 break;
4272 case WINED3DTSS_BUMPENVLSCALE :
4273 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4274 break;
4276 case WINED3DTSS_BUMPENVLOFFSET :
4277 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4278 break;
4280 case WINED3DTSS_RESULTARG :
4281 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4282 break;
4284 default:
4285 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
4286 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4289 LEAVE_GL();
4291 return;
4294 /*****
4295 * Get / Set Texture Stage States
4296 * TODO: Verify against dx9 definitions
4297 *****/
4298 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
4299 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4301 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4303 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4305 /* Reject invalid texture units */
4306 if (Stage >= GL_LIMITS(textures)) {
4307 TRACE("Attempt to access invalid texture rejected\n");
4308 return D3DERR_INVALIDCALL;
4311 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
4312 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
4313 This->updateStateBlock->textureState[Stage][Type] = Value;
4315 return D3D_OK;
4318 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4319 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4320 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4321 *pValue = This->updateStateBlock->textureState[Stage][Type];
4322 return D3D_OK;
4325 /*****
4326 * Get / Set Texture
4327 *****/
4328 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4330 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4331 IWineD3DBaseTexture *oldTexture;
4333 oldTexture = This->updateStateBlock->textures[Stage];
4334 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
4336 #if 0 /* TODO: check so vertex textures */
4337 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
4338 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
4339 return D3D_OK;
4341 #endif
4343 /* Reject invalid texture units */
4344 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4345 WARN("Attempt to access invalid texture rejected\n");
4346 return D3DERR_INVALIDCALL;
4349 oldTexture = This->updateStateBlock->textures[Stage];
4350 TRACE("GL_LIMITS %d\n",GL_LIMITS(textures));
4351 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
4353 This->updateStateBlock->set.textures[Stage] = TRUE;
4354 This->updateStateBlock->changed.textures[Stage] = TRUE;
4355 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
4356 This->updateStateBlock->textures[Stage] = pTexture;
4358 /* Handle recording of state blocks */
4359 if (This->isRecordingState) {
4360 TRACE("Recording... not performing anything\n");
4361 return D3D_OK;
4364 /** NOTE: MSDN says that setTexture increases the reference count,
4365 * and the the application nust set the texture back to null (or have a leaky application),
4366 * This means we should pass the refcount upto the parent
4367 *******************************/
4368 if (NULL != This->updateStateBlock->textures[Stage]) {
4369 IUnknown *textureParent;
4370 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[Stage], (IUnknown **)&textureParent);
4371 /** NOTE: GetParent will increase the ref count for me, I won't clean up until the texture is set to NULL **/
4374 if (NULL != oldTexture) {
4375 IUnknown *textureParent;
4376 IWineD3DBaseTexture_GetParent(oldTexture, (IUnknown **)&textureParent);
4377 IUnknown_Release(textureParent);
4378 IUnknown_Release(textureParent); /** NOTE: Twice because GetParent adds a ref **/
4379 oldTexture = NULL;
4382 return D3D_OK;
4385 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4386 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4387 TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
4389 /* Reject invalid texture units */
4390 if (Stage >= GL_LIMITS(textures)) {
4391 TRACE("Attempt to access invalid texture rejected\n");
4392 return D3DERR_INVALIDCALL;
4394 *ppTexture=This->updateStateBlock->textures[Stage];
4395 if (*ppTexture)
4396 IWineD3DBaseTexture_AddRef(*ppTexture);
4397 else
4398 return D3DERR_INVALIDCALL;
4399 return D3D_OK;
4402 /*****
4403 * Get Back Buffer
4404 *****/
4405 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type,
4406 IWineD3DSurface **ppBackBuffer) {
4407 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4408 IWineD3DSwapChain *swapChain;
4409 HRESULT hr;
4411 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4413 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4414 if (hr == D3D_OK) {
4415 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4416 IWineD3DSwapChain_Release(swapChain);
4417 } else {
4418 *ppBackBuffer = NULL;
4420 return hr;
4423 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4424 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4425 WARN("(%p) : stub, calling idirect3d for now\n", This);
4426 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4429 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
4430 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4431 IWineD3DSwapChain *swapChain;
4432 HRESULT hr;
4434 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4435 if (hr == D3D_OK) {
4436 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4437 IWineD3DSwapChain_Release(swapChain);
4438 } else {
4439 FIXME("(%p) Error getting display mode\n", This);
4441 return hr;
4443 /*****
4444 * Stateblock related functions
4445 *****/
4447 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4448 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4449 IWineD3DStateBlockImpl *object;
4450 TRACE("(%p)", This);
4451 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4452 if (NULL == object ) {
4453 FIXME("(%p)Error allocating memory for stateblock\n", This);
4454 return E_OUTOFMEMORY;
4456 TRACE("(%p) creted object %p\n", This, object);
4457 object->wineD3DDevice= This;
4458 /** FIXME: object->parent = parent; **/
4459 object->parent = NULL;
4460 object->blockType = WINED3DSBT_ALL;
4461 object->ref = 1;
4462 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
4464 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4465 This->updateStateBlock = object;
4466 This->isRecordingState = TRUE;
4468 TRACE("(%p) recording stateblock %p\n",This , object);
4469 return D3D_OK;
4472 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4473 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4475 if (!This->isRecordingState) {
4476 FIXME("(%p) not recording! returning error\n", This);
4477 *ppStateBlock = NULL;
4478 return D3DERR_INVALIDCALL;
4481 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4482 This->isRecordingState = FALSE;
4483 This->updateStateBlock = This->stateBlock;
4484 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4485 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4486 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4487 return D3D_OK;
4490 /*****
4491 * Scene related functions
4492 *****/
4493 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4494 /* At the moment we have no need for any functionality at the beginning
4495 of a scene */
4496 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4497 TRACE("(%p) : stub\n", This);
4498 return D3D_OK;
4501 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4502 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4503 TRACE("(%p)\n", This);
4504 ENTER_GL();
4505 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4506 glFlush();
4507 checkGLcall("glFlush");
4509 TRACE("End Scene\n");
4510 if(This->renderTarget != NULL) {
4512 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4513 IUnknown *targetContainer = NULL;
4514 if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
4515 || D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
4516 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
4517 /** always dirtify for now. we must find a better way to see that surface have been modified
4518 (Modifications should will only occur via draw-primitive, but we do need better locking
4519 switching to render-to-texture should remove the overhead though.
4521 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4522 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
4523 IWineD3DSurface_PreLoad(This->renderTarget);
4524 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4525 IUnknown_Release(targetContainer);
4528 This->sceneEnded = TRUE;
4529 LEAVE_GL();
4530 return D3D_OK;
4533 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4534 CONST RECT* pSourceRect, CONST RECT* pDestRect,
4535 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4536 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4537 IWineD3DSwapChain *swapChain = NULL;
4538 int i;
4539 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4541 TRACE("(%p) Presenting the frame\n", This);
4543 for(i = 0 ; i < swapchains ; i ++) {
4545 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4546 TRACE("presentinng chain %d, %p\n", i, swapChain);
4547 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4548 IWineD3DSwapChain_Release(swapChain);
4551 return D3D_OK;
4554 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4555 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4556 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4558 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4559 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4560 when the depth-buffer format does not contain stencil buffer information, this method fails. */
4561 GLbitfield glMask = 0;
4562 GLboolean old_ztest;
4563 GLfloat old_z_clear_value;
4564 GLint old_stencil_clear_value;
4565 GLfloat old_color_clear_value[4];
4566 unsigned int i;
4567 CONST D3DRECT* curRect;
4569 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4570 Count, pRects, Flags, Z, Stencil);
4572 ENTER_GL();
4574 glEnable(GL_SCISSOR_TEST);
4575 checkGLcall("glEnable GL_SCISSOR_TEST");
4577 if (Count > 0 && pRects) {
4578 curRect = pRects;
4579 } else {
4580 curRect = NULL;
4583 /* Only set the values up once, as they are not changing */
4584 if (Flags & D3DCLEAR_STENCIL) {
4585 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4586 glClearStencil(Stencil);
4587 checkGLcall("glClearStencil");
4588 glMask = glMask | GL_STENCIL_BUFFER_BIT;
4589 glStencilMask(0xFFFFFFFF);
4592 if (Flags & D3DCLEAR_ZBUFFER) {
4593 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4594 glDepthMask(GL_TRUE);
4595 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4596 glClearDepth(Z);
4597 checkGLcall("glClearDepth");
4598 glMask = glMask | GL_DEPTH_BUFFER_BIT;
4601 if (Flags & D3DCLEAR_TARGET) {
4602 TRACE("Clearing screen with glClear to color %lx\n", Color);
4603 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4604 glClearColor(D3DCOLOR_R(Color),
4605 D3DCOLOR_G(Color),
4606 D3DCOLOR_B(Color),
4607 D3DCOLOR_A(Color));
4608 checkGLcall("glClearColor");
4610 /* Clear ALL colors! */
4611 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4612 glMask = glMask | GL_COLOR_BUFFER_BIT;
4615 /* Now process each rect in turn */
4616 for (i = 0; i < Count || i == 0; i++) {
4618 if (curRect) {
4619 /* Note gl uses lower left, width/height */
4620 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4621 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4622 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4623 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4624 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4625 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4626 checkGLcall("glScissor");
4627 } else {
4628 glScissor(This->stateBlock->viewport.X,
4629 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
4630 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4631 This->stateBlock->viewport.Width,
4632 This->stateBlock->viewport.Height);
4633 checkGLcall("glScissor");
4636 /* Clear the selected rectangle (or full screen) */
4637 glClear(glMask);
4638 checkGLcall("glClear");
4640 /* Step to the next rectangle */
4641 if (curRect) curRect = curRect + sizeof(D3DRECT);
4644 /* Restore the old values (why..?) */
4645 if (Flags & D3DCLEAR_STENCIL) {
4646 glClearStencil(old_stencil_clear_value);
4647 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4649 if (Flags & D3DCLEAR_ZBUFFER) {
4650 glDepthMask(old_ztest);
4651 glClearDepth(old_z_clear_value);
4653 if (Flags & D3DCLEAR_TARGET) {
4654 glClearColor(old_color_clear_value[0],
4655 old_color_clear_value[1],
4656 old_color_clear_value[2],
4657 old_color_clear_value[3]);
4658 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4659 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4660 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4661 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4664 glDisable(GL_SCISSOR_TEST);
4665 checkGLcall("glDisable");
4666 LEAVE_GL();
4668 return D3D_OK;
4671 /*****
4672 * Drawing functions
4673 *****/
4674 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4675 UINT PrimitiveCount) {
4677 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4678 This->stateBlock->streamIsUP = FALSE;
4680 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4681 debug_d3dprimitivetype(PrimitiveType),
4682 StartVertex, PrimitiveCount);
4683 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
4684 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
4687 return D3D_OK;
4690 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4691 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4692 D3DPRIMITIVETYPE PrimitiveType,
4693 INT baseVIndex, UINT minIndex,
4694 UINT NumVertices, UINT startIndex, UINT primCount) {
4696 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4697 UINT idxStride = 2;
4698 IWineD3DIndexBuffer *pIB;
4699 D3DINDEXBUFFER_DESC IdxBufDsc;
4701 pIB = This->stateBlock->pIndexData;
4702 This->stateBlock->streamIsUP = FALSE;
4704 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
4705 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4706 minIndex, NumVertices, startIndex, baseVIndex, primCount);
4708 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4709 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4710 idxStride = 2;
4711 } else {
4712 idxStride = 4;
4715 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
4716 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
4718 return D3D_OK;
4721 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4722 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4723 UINT VertexStreamZeroStride) {
4724 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4726 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4727 debug_d3dprimitivetype(PrimitiveType),
4728 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4730 if (This->stateBlock->streamSource[0] != NULL) {
4731 IUnknown *vertexBufferParent;
4732 IWineD3DVertexBuffer_GetParent(This->stateBlock->streamSource[0], &vertexBufferParent);
4733 IUnknown_Release(vertexBufferParent);
4734 IUnknown_Release(vertexBufferParent);
4737 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4738 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4739 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4740 This->stateBlock->streamIsUP = TRUE;
4742 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
4743 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
4744 /* stream zero settings set to null at end, as per the msdn
4745 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
4747 This->stateBlock->streamStride[0] = 0;
4748 This->stateBlock->streamSource[0] = NULL;
4750 /*stream zero settings set to null at end, as per the msdn */
4751 return D3D_OK;
4754 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4755 UINT MinVertexIndex, UINT NumVertices,
4756 UINT PrimitiveCount, CONST void* pIndexData,
4757 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4758 UINT VertexStreamZeroStride) {
4759 int idxStride;
4760 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4762 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4763 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4764 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
4765 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4767 if (IndexDataFormat == WINED3DFMT_INDEX16) {
4768 idxStride = 2;
4769 } else {
4770 idxStride = 4;
4773 if (This->stateBlock->streamSource[0] != NULL) {
4774 IUnknown *vertexBufferParent;
4775 IWineD3DVertexBuffer_GetParent(This->stateBlock->streamSource[0], &vertexBufferParent);
4776 This->stateBlock->streamSource[0] = NULL;
4777 IUnknown_Release(vertexBufferParent);
4778 IUnknown_Release(vertexBufferParent);
4781 if (This->stateBlock->pIndexData) {
4782 IUnknown *indexBufferParent;
4783 IWineD3DIndexBuffer_GetParent(This->stateBlock->pIndexData, &indexBufferParent);
4784 This->stateBlock->pIndexData = NULL;
4785 IUnknown_Release(indexBufferParent);
4786 IUnknown_Release(indexBufferParent);
4789 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4790 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4791 This->stateBlock->streamIsUP = TRUE;
4792 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4794 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
4795 /* stream zero settings set to null at end as per the msdn
4796 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
4799 /* stream zero settings set to null at end as per the msdn */
4800 This->stateBlock->streamSource[0] = NULL;
4801 This->stateBlock->streamStride[0] = 0;
4803 return D3D_OK;
4806 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4807 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
4808 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4809 HRESULT hr = D3D_OK;
4810 D3DRESOURCETYPE sourceType;
4811 D3DRESOURCETYPE destinationType;
4812 int i ,levels;
4814 /* TODO: think about moving the code into IWineD3DBaseTexture */
4816 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
4818 /* verify that the source and destination textures arebn't NULL */
4819 if (NULL == pSourceTexture || NULL == pDestinationTexture) {
4820 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning D3DERR_INVALIDCALL\n",
4821 This, pSourceTexture, pDestinationTexture);
4822 hr = D3DERR_INVALIDCALL;
4825 if (pSourceTexture == pDestinationTexture) {
4826 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning D3DERR_INVALIDCALL\n",
4827 This, pSourceTexture, pDestinationTexture);
4828 hr = D3DERR_INVALIDCALL;
4830 /* Verify that the source and destination textures are the same type */
4831 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
4832 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
4834 if (sourceType != destinationType) {
4835 WARN("(%p) Sorce and destination types must match, returning D3DERR_INVALIDCALL\n",
4836 This);
4837 hr = D3DERR_INVALIDCALL;
4840 /* check that both textures have the identical numbers of levels */
4841 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
4842 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning D3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
4843 hr = D3DERR_INVALIDCALL;
4846 if (D3D_OK == hr) {
4848 /* Make sure that the destination texture is loaded */
4849 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
4851 /* Update every surface level of the texture */
4852 levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
4854 switch (sourceType) {
4855 case D3DRTYPE_TEXTURE:
4857 IWineD3DSurface *srcSurface;
4858 IWineD3DSurface *destSurface;
4860 for (i = 0 ; i < levels ; ++i) {
4861 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture, i, &srcSurface);
4862 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
4863 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4864 IWineD3DSurface_Release(srcSurface);
4865 IWineD3DSurface_Release(destSurface);
4866 if (D3D_OK != hr) {
4867 WARN("(%p) : Call to update surface failed\n", This);
4868 return hr;
4872 break;
4873 case D3DRTYPE_CUBETEXTURE:
4875 IWineD3DSurface *srcSurface;
4876 IWineD3DSurface *destSurface;
4877 D3DCUBEMAP_FACES faceType;
4879 for (i = 0 ; i < levels ; ++i) {
4880 /* Update each cube face */
4881 for (faceType = D3DCUBEMAP_FACE_POSITIVE_X; faceType <= D3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
4882 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture, faceType, i, &srcSurface);
4883 if (D3D_OK != hr) {
4884 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4885 } else {
4886 TRACE("Got srcSurface %p\n", srcSurface);
4888 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
4889 if (D3D_OK != hr) {
4890 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4891 } else {
4892 TRACE("Got desrSurface %p\n", destSurface);
4894 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4895 IWineD3DSurface_Release(srcSurface);
4896 IWineD3DSurface_Release(destSurface);
4897 if (D3D_OK != hr) {
4898 WARN("(%p) : Call to update surface failed\n", This);
4899 return hr;
4904 break;
4905 #if 0 /* TODO: Add support for volume textures */
4906 case D3DRTYPE_VOLUMETEXTURE:
4908 IWineD3DVolume srcVolume = NULL;
4909 IWineD3DSurface destVolume = NULL;
4911 for (i = 0 ; i < levels ; ++i) {
4912 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture, i, &srcVolume);
4913 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
4914 hr = IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
4915 IWineD3DVolume_Release(srcSurface);
4916 IWineD3DVolume_Release(destSurface);
4917 if (D3D_OK != hr) {
4918 WARN("(%p) : Call to update volume failed\n", This);
4919 return hr;
4923 break;
4924 #endif
4925 default:
4926 FIXME("(%p) : Unsupported source and destination type\n", This);
4927 hr = D3DERR_INVALIDCALL;
4931 return hr;
4934 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
4935 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
4936 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
4937 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4939 TRACE("(%p) : stub\n", This);
4940 return D3D_OK;
4942 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
4943 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4944 /** TODO: remove remove casts to IWineD3DSurfaceImpl *
4945 * NOTE It may be best to move the code into surface to occomplish this
4946 ****************************************/
4948 WINED3DSURFACE_DESC surfaceDesc;
4949 unsigned int surfaceWidth, surfaceHeight;
4950 glDescriptor *targetGlDescription = NULL;
4951 glDescriptor *surfaceGlDescription = NULL;
4952 IWineD3DSwapChainImpl *container = NULL;
4954 IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
4955 IWineD3DSurface_GetGlDesc(pSurface, &surfaceGlDescription);
4956 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
4958 surfaceDesc.Width = &surfaceWidth;
4959 surfaceDesc.Height = &surfaceHeight;
4960 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
4961 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sureteh data is upto date)*/
4963 /* Ok, I may need to setup some kind of active swapchain reference on the device */
4964 IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
4965 ENTER_GL();
4966 /* TODO: opengl Context switching for swapchains etc... */
4967 if (NULL != container || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
4968 if (NULL != container && (pRenderTarget == container->backBuffer)) {
4969 glReadBuffer(GL_BACK);
4970 vcheckGLcall("glReadBuffer(GL_BACK)");
4971 } else if ((NULL != container && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
4972 glReadBuffer(GL_FRONT);
4973 vcheckGLcall("glReadBuffer(GL_FRONT)");
4974 } else if (pRenderTarget == This->depthStencilBuffer) {
4975 FIXME("Reading of depthstencil not yet supported\n");
4978 glReadPixels(surfaceGlDescription->target,
4979 surfaceGlDescription->level,
4980 surfaceWidth,
4981 surfaceHeight,
4982 surfaceGlDescription->glFormat,
4983 surfaceGlDescription->glType,
4984 (void *)IWineD3DSurface_GetData(pSurface));
4985 vcheckGLcall("glReadPixels(...)");
4986 if(NULL != container ){
4987 IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
4989 } else {
4990 IWineD3DBaseTexture *container;
4991 GLenum textureDimensions = GL_TEXTURE_2D;
4993 if (D3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
4994 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
4995 IWineD3DBaseTexture_Release(container);
4997 /* TODO: 2D -> Cube surface coppies etc.. */
4998 if (surfaceGlDescription->target != textureDimensions) {
4999 FIXME("(%p) : Texture dimension mismatch\n", This);
5001 glEnable(textureDimensions);
5002 vcheckGLcall("glEnable(GL_TEXTURE_...)");
5003 /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
5004 glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
5005 vcheckGLcall("glBindTexture");
5006 glGetTexImage(surfaceGlDescription->target,
5007 surfaceGlDescription->level,
5008 surfaceGlDescription->glFormat,
5009 surfaceGlDescription->glType,
5010 (void *)IWineD3DSurface_GetData(pSurface));
5011 glDisable(textureDimensions);
5012 vcheckGLcall("glDisable(GL_TEXTURE_...)");
5015 LEAVE_GL();
5016 return D3D_OK;
5019 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
5020 IWineD3DSwapChain *swapChain;
5021 HRESULT hr;
5022 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5023 if(hr == D3D_OK) {
5024 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
5025 IWineD3DSwapChain_Release(swapChain);
5027 return hr;
5030 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5031 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5032 /* return a sensible default */
5033 *pNumPasses = 1;
5034 /* TODO: If the window is minimized then validate device shold return something other than d3d_ok */
5035 FIXME("(%p) : stub\n", This);
5036 return D3D_OK;
5039 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5040 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5041 int j;
5042 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5043 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5044 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5045 return D3DERR_INVALIDCALL;
5047 for (j = 0; j < 256; ++j) {
5048 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
5049 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5050 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
5051 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5053 TRACE("(%p) : returning\n", This);
5054 return D3D_OK;
5057 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5058 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5059 int j;
5060 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5061 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5062 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5063 return D3DERR_INVALIDCALL;
5065 for (j = 0; j < 256; ++j) {
5066 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
5067 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5068 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
5069 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5071 TRACE("(%p) : returning\n", This);
5072 return D3D_OK;
5075 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5076 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5077 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5078 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5079 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5080 return D3DERR_INVALIDCALL;
5082 /*TODO: stateblocks */
5083 This->currentPalette = PaletteNumber;
5084 TRACE("(%p) : returning\n", This);
5085 return D3D_OK;
5088 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
5089 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5090 if (PaletteNumber == NULL) {
5091 WARN("(%p) : returning Invalid Call\n", This);
5092 return D3DERR_INVALIDCALL;
5094 /*TODO: stateblocks */
5095 *PaletteNumber = This->currentPalette;
5096 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
5097 return D3D_OK;
5100 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
5101 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5102 static BOOL showFixmes = TRUE;
5103 if (showFixmes) {
5104 FIXME("(%p) : stub\n", This);
5105 showFixmes = FALSE;
5108 This->softwareVertexProcessing = bSoftware;
5109 return D3D_OK;
5113 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
5114 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5115 static BOOL showFixmes = TRUE;
5116 if (showFixmes) {
5117 FIXME("(%p) : stub\n", This);
5118 showFixmes = FALSE;
5120 return This->softwareVertexProcessing;
5124 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
5125 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5126 IWineD3DSwapChain *swapChain;
5127 HRESULT hr;
5129 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
5131 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5132 if(hr == D3D_OK){
5133 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
5134 IWineD3DSwapChain_Release(swapChain);
5135 }else{
5136 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
5138 return hr;
5142 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
5143 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5144 static BOOL showfixmes = TRUE;
5145 if(nSegments != 0.0f) {
5146 if( showfixmes) {
5147 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
5148 showfixmes = FALSE;
5151 return D3D_OK;
5154 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
5155 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5156 static BOOL showfixmes = TRUE;
5157 if( showfixmes) {
5158 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
5159 showfixmes = FALSE;
5161 return 0.0f;
5164 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
5165 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5166 /** TODO: remove casts to IWineD3DSurfaceImpl
5167 * NOTE: move code to surface to accomplish this
5168 ****************************************/
5169 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
5170 int srcWidth, srcHeight;
5171 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
5172 WINED3DFORMAT destFormat, srcFormat;
5173 UINT destSize;
5174 int destLeft, destTop;
5175 D3DPOOL srcPool, destPool;
5176 int offset = 0;
5177 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
5178 glDescriptor *glDescription = NULL;
5179 GLenum textureDimensions = GL_TEXTURE_2D;
5180 IWineD3DBaseTexture *baseTexture;
5182 WINED3DSURFACE_DESC winedesc;
5184 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
5185 memset(&winedesc, 0, sizeof(winedesc));
5186 winedesc.Width = &srcSurfaceWidth;
5187 winedesc.Height = &srcSurfaceHeight;
5188 winedesc.Pool = &srcPool;
5189 winedesc.Format = &srcFormat;
5191 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5193 winedesc.Width = &destSurfaceWidth;
5194 winedesc.Height = &destSurfaceHeight;
5195 winedesc.Pool = &destPool;
5196 winedesc.Format = &destFormat;
5197 winedesc.Size = &destSize;
5199 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5201 if(srcPool != D3DPOOL_SYSTEMMEM || destPool != D3DPOOL_DEFAULT){
5202 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning D3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
5203 return D3DERR_INVALIDCALL;
5206 if (destFormat == WINED3DFMT_UNKNOWN) {
5207 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5208 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5210 /* Get the update surface description */
5211 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5214 /* Make sure the surface is loaded and upto date */
5215 IWineD3DSurface_PreLoad(pDestinationSurface);
5217 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
5219 ENTER_GL();
5221 /* this needs to be done in lines if the sourceRect != the sourceWidth */
5222 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
5223 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
5224 destLeft = pDestPoint ? pDestPoint->x : 0;
5225 destTop = pDestPoint ? pDestPoint->y : 0;
5228 /* This function doesn't support compressed textures
5229 the pitch is just bytesPerPixel * width */
5230 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
5231 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
5232 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
5233 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
5235 /* TODO DXT formats */
5237 if(pSourceRect != NULL && pSourceRect->top != 0){
5238 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
5240 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
5241 ,This
5242 ,glDescription->level
5243 ,destLeft
5244 ,destTop
5245 ,srcWidth
5246 ,srcHeight
5247 ,glDescription->glFormat
5248 ,glDescription->glType
5249 ,IWineD3DSurface_GetData(pSourceSurface)
5252 /* Sanity check */
5253 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
5255 /* need to lock the surface to get the data */
5256 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5259 /* TODO: Cube and volume support */
5260 if(rowoffset != 0){
5261 /* not a whole row so we have to do it a line at a time */
5262 int j;
5264 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
5265 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5267 for(j = destTop ; j < (srcHeight + destTop) ; j++){
5269 glTexSubImage2D(glDescription->target
5270 ,glDescription->level
5271 ,destLeft
5273 ,srcWidth
5275 ,glDescription->glFormat
5276 ,glDescription->glType
5277 ,data /* could be quicker using */
5279 data += rowoffset;
5282 } else { /* Full width, so just write out the whole texture */
5284 if (WINED3DFMT_DXT1 == destFormat ||
5285 WINED3DFMT_DXT2 == destFormat ||
5286 WINED3DFMT_DXT3 == destFormat ||
5287 WINED3DFMT_DXT4 == destFormat ||
5288 WINED3DFMT_DXT5 == destFormat) {
5289 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
5290 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
5291 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
5292 FIXME("Updating part of a compressed texture is not supported at the moment\n");
5293 } if (destFormat != srcFormat) {
5294 FIXME("Updating mixed format compressed texture is not curretly support\n");
5295 } else {
5296 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
5297 glDescription->level,
5298 glDescription->glFormatInternal,
5299 srcWidth,
5300 srcHeight,
5302 destSize,
5303 IWineD3DSurface_GetData(pSourceSurface));
5305 } else {
5306 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
5310 } else {
5311 if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
5313 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
5314 to repack the data from pow2Width/Height to expected Width,Height, this makes the
5315 data returned by GetData non-power2 width/height with hardware non-power2
5316 pow2Width/height are set to surface width height, repacking isn't needed so it
5317 doesn't matter which function gets called. */
5318 glTexSubImage2D(glDescription->target
5319 ,glDescription->level
5320 ,destLeft
5321 ,destTop
5322 ,srcWidth
5323 ,srcHeight
5324 ,glDescription->glFormat
5325 ,glDescription->glType
5326 ,IWineD3DSurface_GetData(pSourceSurface)
5328 } else {
5330 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
5331 glTexSubImage2D(glDescription->target
5332 ,glDescription->level
5333 ,destLeft
5334 ,destTop
5335 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
5336 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
5337 ,glDescription->glFormat
5338 ,glDescription->glType
5339 ,IWineD3DSurface_GetData(pSourceSurface)
5345 checkGLcall("glTexSubImage2D");
5347 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
5348 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
5349 * surface bigger than it needs to be hmm.. */
5350 if (D3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
5351 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
5352 IWineD3DBaseTexture_Release(baseTexture);
5355 glDisable(textureDimensions); /* This needs to be managed better.... */
5356 LEAVE_GL();
5358 return D3D_OK;
5361 /* Implementation details at http://developer.nvidia.com/attach/6494
5363 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
5364 hmm.. no longer supported use
5365 OpenGL evaluators or tessellate surfaces within your application.
5368 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
5369 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
5370 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5371 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
5372 FIXME("(%p) : Stub\n", This);
5373 return D3D_OK;
5377 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
5378 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
5379 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5380 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
5381 FIXME("(%p) : Stub\n", This);
5382 return D3D_OK;
5385 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5386 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5387 TRACE("(%p) Handle(%d)\n", This, Handle);
5388 FIXME("(%p) : Stub\n", This);
5389 return D3D_OK;
5392 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
5393 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
5394 fill a surface with a block of color! */
5395 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5396 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
5397 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
5398 IWineD3DSwapChainImpl *container = NULL;
5399 BOOL isRenderTarget = FALSE;
5400 unsigned int width, height;
5401 unsigned int top, left;
5402 unsigned int u, v;
5403 DWORD *data;
5404 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
5406 if (surface->resource.pool != D3DPOOL_DEFAULT) {
5407 FIXME("call to colorfill with non D3DPOOL_DEFAULT surface\n");
5408 return D3DERR_INVALIDCALL;
5411 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
5412 if (D3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
5413 if (D3DUSAGE_RENDERTARGET & surface->resource.usage) {
5414 /* TODO: make sure we set everything back to the way it was, and context management!
5415 glGetIntegerv(GL_READ_BUFFER, &prev_read);
5416 vcheckGLcall("glIntegerv");
5417 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
5418 vcheckGLcall("glIntegerv");
5420 TRACE("Color fill to render targets may cause some graphics issues\n");
5421 if (pSurface == container->frontBuffer) {
5422 glDrawBuffer(GL_FRONT);
5423 } else {
5424 glDrawBuffer(GL_BACK);
5426 } else {
5427 if (D3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
5428 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld\n", surface, surface->resource.usage);
5429 } else {
5430 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
5432 if (container != NULL) {
5433 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5435 /* we can use GL_STENCIL_INDEX etc...*/
5436 return D3D_OK;
5438 if (container != NULL) {
5439 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5441 isRenderTarget = TRUE;
5443 /* TODO: drawing to GL_FRONT and GL_BACK */
5444 /* TODO: see if things can be speeded up by using the correct
5445 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
5446 if (pRect == NULL) {
5447 top = 0;
5448 left = 0;
5449 width = surface->currentDesc.Width;
5450 height = surface->currentDesc.Height;
5451 } else {
5452 left = pRect->x1;
5453 top = pRect->y1;
5454 width = pRect->x2 - left;
5455 height = pRect->y2 - top;
5458 data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
5459 /* Create a 'line' of color color, in the correct format for the surface */
5460 for (u = 0 ; u < width ; u ++) {
5461 data[u] = color;
5464 ENTER_GL();
5465 if (isRenderTarget == FALSE) {
5466 glDescriptor *glDesc;
5467 IWineD3DSurface_PreLoad(pSurface);
5469 /* draw a block of the coloured line on the sufrace */
5470 IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
5471 for (v = 0 ; v< height;v++) {
5472 glTexSubImage2D(glDesc->target
5473 ,glDesc->level /* level */
5474 ,left
5475 ,top + v
5476 ,width
5477 ,1 /* height */
5478 ,GL_RGBA
5479 ,GL_UNSIGNED_BYTE
5480 ,data
5483 checkGLcall("glTexSubImage2D");
5484 /* clean up */
5485 glDisable(glDesc->target);
5486 } else {
5487 /** FIXME: Using GLClear may be faster **/
5488 glRasterPos2i(left, top);
5489 glPixelZoom((float)width ,(float)height);
5490 glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
5491 checkGLcall("glDrawPixels");
5493 HeapFree(GetProcessHeap(), 0, data);
5494 LEAVE_GL();
5495 return D3D_OK;
5499 /* rendertarget and deptth stencil functions */
5500 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
5501 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5503 /* FIXME: Implelent RenderTargetIndex >0 */
5504 if(RenderTargetIndex > 0)
5505 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
5507 *ppRenderTarget = This->renderTarget;
5508 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
5509 /* Note inc ref on returned surface */
5510 if(*ppRenderTarget != NULL)
5511 IWineD3DSurface_AddRef(*ppRenderTarget);
5512 return D3D_OK;
5515 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5516 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5517 *ppZStencilSurface = This->depthStencilBuffer;
5518 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
5520 if(*ppZStencilSurface != NULL) {
5521 /* Note inc ref on returned surface */
5522 IWineD3DSurface_AddRef(*ppZStencilSurface);
5524 return D3D_OK;
5527 /* internal static helper functions */
5528 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5529 IWineD3DSurface *RenderSurface);
5531 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5532 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5533 HRESULT hr = D3D_OK;
5534 WINED3DVIEWPORT viewport;
5536 TRACE("(%p) Swapping rendertarget\n",This);
5537 if (RenderTargetIndex > 0) {
5538 FIXME("(%p) Render targets other than the first are not supported\n",This);
5539 RenderTargetIndex = 0;
5542 /* MSDN says that null disables the render target
5543 but a device must always be associated with a render target
5544 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5546 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5547 for more details
5549 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5550 FIXME("Trying to set render target 0 to NULL\n");
5551 return D3DERR_INVALIDCALL;
5553 /* TODO: replace Impl* usage with interface usage */
5554 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & D3DUSAGE_RENDERTARGET) {
5555 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);
5556 return D3DERR_INVALIDCALL;
5558 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
5559 * builds, but I think wine counts as a 'debug' build for now.
5560 ******************************/
5561 /* If we are trying to set what we already have, don't bother */
5562 if (pRenderTarget == This->renderTarget) {
5563 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5564 } else {
5565 /* Otherwise, set the render target up */
5567 if (FALSE == This->sceneEnded) {
5568 IWineD3DDevice_EndScene(iface);
5570 TRACE("clearing renderer\n");
5571 /* IWineD3DDeviceImpl_CleanRender(iface); */
5572 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5573 depending on the renter target implementation being used.
5574 A shared context implementation will share all buffers between all rendertargets (including swapchains),
5575 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5576 stencil buffer and incure an extra memory overhead */
5577 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
5580 if (SUCCEEDED(hr)) {
5581 /* Finally, reset the viewport as the MSDN states. */
5582 /* TODO: Replace impl usage */
5583 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
5584 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
5585 viewport.X = 0;
5586 viewport.Y = 0;
5587 viewport.MaxZ = 1.0f;
5588 viewport.MinZ = 0.0f;
5589 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
5590 } else {
5591 FIXME("Unknown error setting the render target\n");
5593 This->sceneEnded = FALSE;
5594 return hr;
5597 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
5598 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5599 HRESULT hr = D3D_OK;
5600 IWineD3DSurface *tmp;
5602 TRACE("(%p) Swapping z-buffer\n",This);
5604 if (pNewZStencil == This->stencilBufferTarget) {
5605 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5606 } else {
5607 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5608 * depending on the renter target implementation being used.
5609 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5610 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5611 * stencil buffer and incure an extra memory overhead
5612 ******************************************************/
5615 tmp = This->stencilBufferTarget;
5616 This->stencilBufferTarget = pNewZStencil;
5617 /* should we be calling the parent or the wined3d surface? */
5618 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
5619 if (NULL != tmp) IWineD3DSurface_Release(tmp);
5620 hr = D3D_OK;
5621 /** TODO: glEnable/glDisable on depth/stencil depending on
5622 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
5623 **********************************************************/
5626 return hr;
5630 #ifdef GL_VERSION_1_3
5631 /* Internal functions not in DirectX */
5632 /** TODO: move this off to the opengl context manager
5633 *(the swapchain doesn't need to know anything about offscreen rendering!)
5634 ****************************************************/
5636 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
5638 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5640 TRACE("(%p), %p\n", This, swapchain);
5642 if (swapchain->win != swapchain->drawable) {
5643 /* Set everything back the way it ws */
5644 swapchain->render_ctx = swapchain->glCtx;
5645 swapchain->drawable = swapchain->win;
5647 return D3D_OK;
5650 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
5651 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
5652 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5653 int i;
5654 unsigned int width;
5655 unsigned int height;
5656 WINED3DFORMAT format;
5657 WINED3DSURFACE_DESC surfaceDesc;
5658 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5659 surfaceDesc.Width = &width;
5660 surfaceDesc.Height = &height;
5661 surfaceDesc.Format = &format;
5662 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5663 *context = NULL;
5664 /* I need a get width/height function (and should do something with the format) */
5665 for (i = 0; i < CONTEXT_CACHE; ++i) {
5666 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
5667 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
5668 the pSurface can be set to 0 allowing it to be reused from cache **/
5669 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
5670 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
5671 *context = &This->contextCache[i];
5672 break;
5674 if (This->contextCache[i].Width == 0) {
5675 This->contextCache[i].pSurface = pSurface;
5676 This->contextCache[i].Width = width;
5677 This->contextCache[i].Height = height;
5678 *context = &This->contextCache[i];
5679 break;
5682 if (i == CONTEXT_CACHE) {
5683 int minUsage = 0x7FFFFFFF; /* MAX_INT */
5684 glContext *dropContext = 0;
5685 for (i = 0; i < CONTEXT_CACHE; i++) {
5686 if (This->contextCache[i].usedcount < minUsage) {
5687 dropContext = &This->contextCache[i];
5688 minUsage = This->contextCache[i].usedcount;
5691 /* clean up the context (this doesn't work for ATI at the moment */
5692 #if 0
5693 glXDestroyContext(swapchain->display, dropContext->context);
5694 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
5695 #endif
5696 FIXME("Leak\n");
5697 dropContext->Width = 0;
5698 dropContext->pSurface = pSurface;
5699 *context = dropContext;
5700 } else {
5701 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
5702 for (i = 0; i < CONTEXT_CACHE; i++) {
5703 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
5707 if (*context != NULL)
5708 return D3D_OK;
5709 else
5710 return E_OUTOFMEMORY;
5712 #endif
5714 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
5715 * the functionality needs splitting up so that we don't do more than we should do.
5716 * this only seems to impact performance a little.
5717 ******************************/
5718 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5719 IWineD3DSurface *RenderSurface) {
5720 HRESULT ret = D3DERR_INVALIDCALL;
5723 * Currently only active for GLX >= 1.3
5724 * for others versions we'll have to use GLXPixmaps
5726 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
5727 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
5728 * so only check OpenGL version
5729 * ..........................
5730 * I don't believe that it is a problem with NVidia headers,
5731 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
5732 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
5733 * ATI Note:
5734 * Your application will report GLX version 1.2 on glXQueryVersion.
5735 * However, it is safe to call the GLX 1.3 functions as described below.
5737 #if defined(GL_VERSION_1_3)
5739 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5740 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
5741 IWineD3DSurface *tmp;
5742 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
5743 GLXFBConfig* cfgs = NULL;
5744 int nCfgs = 0;
5745 int attribs[256];
5746 int nAttribs = 0;
5747 IWineD3DSwapChain *currentSwapchain;
5748 IWineD3DSwapChainImpl *swapchain;
5749 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
5750 * but switch them off if the StencilSurface is set to NULL
5751 ** *********************************************************/
5752 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
5753 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
5755 /**TODO:
5756 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
5757 it StencilSurface != NULL && zBufferTarget == NULL switch it on
5760 #define PUSH1(att) attribs[nAttribs++] = (att);
5761 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
5763 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
5765 /** TODO: remove the reff to Impl (context manager should fix this!) **/
5766 IWineD3DSwapChainImpl *impSwapChain;
5767 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
5768 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
5769 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
5772 ENTER_GL();
5774 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
5775 PUSH2(GLX_X_RENDERABLE, TRUE);
5776 PUSH2(GLX_DOUBLEBUFFER, TRUE);
5777 TRACE("calling makeglcfg\n");
5778 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
5779 PUSH1(None);
5781 TRACE("calling chooseFGConfig\n");
5782 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5783 attribs, &nCfgs);
5785 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
5786 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
5787 why we failed and only show this message once! */
5788 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"); /**/
5789 nAttribs = 0;
5790 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
5791 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
5792 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
5793 PUSH2(GLX_DOUBLEBUFFER, FALSE);
5794 TRACE("calling makeglcfg\n");
5795 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
5796 PUSH1(None);
5797 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5798 attribs, &nCfgs);
5801 if (NULL != cfgs) {
5802 #ifdef EXTRA_TRACES
5803 int i;
5804 for (i = 0; i < nCfgs; ++i) {
5805 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
5806 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
5807 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
5810 if (NULL != This->renderTarget) {
5811 glFlush();
5812 vcheckGLcall("glFlush");
5813 /** This is only useful if the old render target was a swapchain,
5814 * we need to supercede this with a function that displays
5815 * the current buffer on the screen. This is easy to do in glx1.3 but
5816 * we need to do copy-write pixels in glx 1.2.
5817 ************************************************/
5818 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
5820 printf("Hit Enter to get next frame ...\n");
5821 getchar();
5823 #endif
5826 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&currentSwapchain) != D3D_OK) {
5827 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
5828 IWineD3DDevice_GetSwapChain(iface, 0, &currentSwapchain);
5832 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
5833 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
5834 **********************************************************************/
5835 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == D3D_OK) {
5836 /* We also need to make sure that the lights &co are also in the context of the swapchains */
5837 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
5838 TRACE("making swapchain active\n");
5839 if (RenderSurface != This->renderTarget) {
5840 if (RenderSurface == swapchain->backBuffer) {
5841 } else {
5842 /* This could be flagged so that some operations work directly with the front buffer */
5843 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
5845 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
5846 == False) {
5847 TRACE("Error in setting current context: context %p drawable %ld !\n",
5848 impSwapChain->glCtx, impSwapChain->win);
5851 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5853 checkGLcall("glXMakeContextCurrent");
5855 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5857 else if (pbuffer_support == TRUE && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
5859 /** ********************************************************************
5860 * This is a quickly hacked out implementation of offscreen textures.
5861 * It will work in most cases but there may be problems if the client
5862 * modifies the texture directly, or expects the contents of the rendertarget
5863 * to be persistent.
5865 * There are some real speed vs compatibility issues here:
5866 * we should really use a new context for every texture, but that eats ram.
5867 * we should also be restoring the texture to the pbuffer but that eats CPU
5868 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
5869 * but if this means reusing the display backbuffer then we need to make sure that
5870 * states are correctly preserved.
5871 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
5872 * and gain a good performance increase at the cost of compatibility.
5873 * I would suggest that, when this is the case, a user configurable flag be made
5874 * available, allowing the user to choose the best emulated experience for them.
5875 *********************************************************************/
5877 XVisualInfo *visinfo;
5878 glContext *newContext;
5880 /* Here were using a shared context model */
5881 if (D3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
5882 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5885 /* If the context doesn't exist then create a new one */
5886 /* TODO: This should really be part of findGlContext */
5887 if (NULL == newContext->context) {
5889 TRACE("making new buffer\n");
5890 nAttribs = 0;
5891 PUSH2(GLX_PBUFFER_WIDTH, newContext->Width);
5892 PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
5893 PUSH1(None);
5895 newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
5897 /** ****************************************
5898 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
5899 *they note:
5900 * In future releases, we may provide the calls glXCreateNewContext,
5901 * glXQueryDrawable and glXMakeContextCurrent.
5902 * so until then we have to use glXGetVisualFromFBConfig &co..
5903 ********************************************/
5906 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
5907 if (!visinfo) {
5908 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
5909 } else {
5910 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
5911 XFree(visinfo);
5914 if (NULL == newContext || NULL == newContext->context) {
5915 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5916 } else {
5917 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
5918 if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
5919 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
5922 /* Clean up the old context */
5923 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5924 /* Set the current context of the swapchain to the new context */
5925 impSwapChain->drawable = newContext->drawable;
5926 impSwapChain->render_ctx = newContext->context;
5930 #if 1 /* Apply the stateblock to the new context
5931 FIXME: This is a bit of a hack, each context should know it's own state,
5932 the directX current directX state should then be applied to the context */
5934 BOOL oldRecording;
5935 IWineD3DStateBlockImpl *oldUpdateStateBlock;
5936 oldUpdateStateBlock = This->updateStateBlock;
5937 oldRecording= This->isRecordingState;
5938 This->isRecordingState = FALSE;
5939 This->updateStateBlock = This->stateBlock;
5940 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
5942 This->isRecordingState = oldRecording;
5943 This->updateStateBlock = oldUpdateStateBlock;
5945 #endif
5948 /* clean up the current rendertargets swapchain (if it belonged to one) */
5949 if (currentSwapchain != NULL) {
5950 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
5953 /* Were done with the opengl context management, setup the rendertargets */
5955 tmp = This->renderTarget;
5956 This->renderTarget = RenderSurface;
5957 IWineD3DSurface_AddRef(This->renderTarget);
5958 IWineD3DSurface_Release(tmp);
5963 DWORD value;
5964 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
5965 /* Check that the container is not a swapchain member */
5967 IWineD3DSwapChain *tmpSwapChain;
5968 if (D3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
5969 This->renderUpsideDown = TRUE;
5970 }else{
5971 This->renderUpsideDown = FALSE;
5972 IWineD3DSwapChain_Release(tmpSwapChain);
5974 /* Force updating the cull mode */
5975 TRACE("setting render state\n");
5976 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
5977 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
5979 /* Force updating projection matrix */
5980 This->last_was_rhw = FALSE;
5981 This->proj_valid = FALSE;
5984 ret = D3D_OK;
5986 if (cfgs != NULL) {
5987 XFree(cfgs);
5988 } else {
5989 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
5990 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
5993 #undef PUSH1
5994 #undef PUSH2
5995 if ( NULL != impSwapChain) {
5996 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
5998 LEAVE_GL();
6000 #endif
6001 return ret;
6004 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
6005 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
6006 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6007 /* TODO: the use of Impl is deprecated. */
6008 /* some basic validation checks */
6009 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
6011 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
6013 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
6014 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
6015 return D3DERR_INVALIDCALL;
6017 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
6018 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
6019 return D3DERR_INVALIDCALL;
6021 /* TODO: make the cursor 'real' */
6023 This->xHotSpot = XHotSpot;
6024 This->yHotSpot = YHotSpot;
6026 return D3D_OK;
6029 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
6030 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6031 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
6033 This->xScreenSpace = XScreenSpace;
6034 This->yScreenSpace = YScreenSpace;
6036 return;
6040 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
6041 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6042 TRACE("(%p) : visible(%d)\n", This, bShow);
6044 This->bCursorVisible = bShow;
6046 return D3D_OK;
6049 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
6050 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6051 TRACE("(%p) : state (%lu)\n", This, This->state);
6052 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
6053 switch (This->state) {
6054 case D3D_OK:
6055 return D3D_OK;
6056 case D3DERR_DEVICELOST:
6058 ResourceList *resourceList = This->resources;
6059 while (NULL != resourceList) {
6060 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == D3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
6061 return D3DERR_DEVICENOTRESET;
6062 resourceList = resourceList->next;
6064 return D3DERR_DEVICELOST;
6066 case D3DERR_DRIVERINTERNALERROR:
6067 return D3DERR_DRIVERINTERNALERROR;
6070 /* Unknown state */
6071 return D3DERR_DRIVERINTERNALERROR;
6075 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
6076 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6077 /** FIXME: Resource tracking needs to be done,
6078 * The closes we can do to this is set the priorities of all managed textures low
6079 * and then reset them.
6080 ***********************************************************/
6081 FIXME("(%p) : stub\n", This);
6082 return D3D_OK;
6085 HRESULT WINAPI IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
6086 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6087 /** FIXME: Resource trascking needs to be done.
6088 * in effect this pulls all non only default
6089 * textures out of video memory and deletes all glTextures (glDeleteTextures)
6090 * and should clear down the context and set it up according to pPresentationParameters
6091 ***********************************************************/
6092 FIXME("(%p) : stub\n", This);
6093 return D3D_OK;
6096 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
6097 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6098 /** FIXME: always true at the moment **/
6099 if(bEnableDialogs == FALSE) {
6100 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
6102 return D3D_OK;
6106 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
6107 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6109 FIXME("(%p) : stub\n", This);
6110 /* Setup some reasonable defaults */
6111 pParameters->AdapterOrdinal = 0; /* always for now */
6112 pParameters->DeviceType = D3DDEVTYPE_HAL; /* always for now */
6113 pParameters->hFocusWindow = 0;
6114 pParameters->BehaviorFlags =0;
6115 return D3D_OK;
6118 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
6119 IWineD3DSwapChain *swapchain;
6120 HRESULT hrc = D3D_OK;
6122 TRACE("Relaying to swapchain\n");
6124 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
6125 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (D3DGAMMARAMP *)pRamp);
6126 IWineD3DSwapChain_Release(swapchain);
6128 return;
6131 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
6132 IWineD3DSwapChain *swapchain;
6133 HRESULT hrc = D3D_OK;
6135 TRACE("Relaying to swapchain\n");
6137 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
6138 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
6139 IWineD3DSwapChain_Release(swapchain);
6141 return;
6145 /** ********************************************************
6146 * Notification functions
6147 ** ********************************************************/
6148 /** This function must be called in the release of a resource when ref == 0,
6149 * the contents of resource must still be correct,
6150 * any handels to other resource held by the caller must be closed
6151 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
6152 *****************************************************/
6153 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6154 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6155 ResourceList* resourceList;
6157 TRACE("(%p) : resource %p\n", This, resource);
6158 #if 0
6159 EnterCriticalSection(&resourceStoreCriticalSection);
6160 #endif
6161 /* add a new texture to the frot of the linked list */
6162 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
6163 resourceList->resource = resource;
6165 /* Get the old head */
6166 resourceList->next = This->resources;
6168 This->resources = resourceList;
6169 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
6171 #if 0
6172 LeaveCriticalSection(&resourceStoreCriticalSection);
6173 #endif
6174 return;
6177 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6178 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6179 ResourceList* resourceList = NULL;
6180 ResourceList* previousResourceList = NULL;
6182 TRACE("(%p) : resource %p\n", This, resource);
6184 #if 0
6185 EnterCriticalSection(&resourceStoreCriticalSection);
6186 #endif
6187 resourceList = This->resources;
6189 while (resourceList != NULL) {
6190 if(resourceList->resource == resource) break;
6191 previousResourceList = resourceList;
6192 resourceList = resourceList->next;
6195 if (resourceList == NULL) {
6196 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
6197 #if 0
6198 LeaveCriticalSection(&resourceStoreCriticalSection);
6199 #endif
6200 return;
6201 } else {
6202 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
6204 /* make sure we don't leave a hole in the list */
6205 if (previousResourceList != NULL) {
6206 previousResourceList->next = resourceList->next;
6207 } else {
6208 This->resources = resourceList->next;
6211 #if 0
6212 LeaveCriticalSection(&resourceStoreCriticalSection);
6213 #endif
6214 return;
6218 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
6219 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6220 int counter;
6222 TRACE("(%p) : resource %p\n", This, resource);
6223 switch(IWineD3DResource_GetType(resource)){
6224 case D3DRTYPE_SURFACE:
6225 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
6226 break;
6227 case D3DRTYPE_TEXTURE:
6228 case D3DRTYPE_CUBETEXTURE:
6229 case D3DRTYPE_VOLUMETEXTURE:
6230 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
6231 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6232 IUnknown *textureParent;
6233 IWineD3DBaseTexture_GetParent(This->stateBlock->textures[counter], &textureParent);
6234 /* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
6235 FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter, resource, textureParent);
6236 IUnknown_Release(textureParent);
6237 This->stateBlock->textures[counter] = NULL;
6239 if (This->updateStateBlock != This->stateBlock ){
6240 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6241 IUnknown *textureParent;
6242 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[counter], &textureParent);
6243 /* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
6244 FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter, resource, textureParent);
6245 IUnknown_Release(textureParent);
6246 This->updateStateBlock->textures[counter] = NULL;
6250 break;
6251 case D3DRTYPE_VOLUME:
6252 /* TODO: nothing really? */
6253 break;
6254 case D3DRTYPE_VERTEXBUFFER:
6255 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
6257 int streamNumber;
6258 TRACE("Cleaning up stream pointers\n");
6260 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
6261 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
6262 FINDOUT: should changes.streamSource[StreamNumber] be set ?
6264 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6265 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
6266 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
6267 This->updateStateBlock->streamSource[streamNumber] = 0;
6268 /* Set changed flag? */
6271 if (This->stateBlock != NULL ) { /* only happens if their is an error in the application, or on reset/release (because we don't manage internal tracknig properly) */
6272 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
6273 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
6274 This->stateBlock->streamSource[streamNumber] = 0;
6277 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
6278 else { /* This shouldn't happen */
6279 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
6281 #endif
6285 break;
6286 case D3DRTYPE_INDEXBUFFER:
6287 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
6288 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6289 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6290 This->updateStateBlock->pIndexData = NULL;
6293 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
6294 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6295 This->stateBlock->pIndexData = NULL;
6299 break;
6300 default:
6301 FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
6302 break;
6306 /* Remove the resoruce from the resourceStore */
6307 IWineD3DDeviceImpl_RemoveResource(iface, resource);
6309 TRACE("Resource released\n");
6314 /** This function is to be called by the swapchain when it is released and it's ref = 0
6315 *****************************************************/
6316 void WINAPI IWineD3DDeviceImpl_SwapChainReleased(IWineD3DDevice *iface, IWineD3DSwapChain *swapChain){
6317 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6318 SwapChainList **nextSwapchain;
6319 nextSwapchain = &This->swapchains;
6321 /* Check to see if the swapchian is being used as the render target */
6322 if (This->renderTarget != NULL) {
6323 IWineD3DSurface *swapchainBackBuffer;
6325 IWineD3DSwapChain_GetBackBuffer(swapChain, 0 ,( D3DBACKBUFFER_TYPE) 0, &swapchainBackBuffer);
6326 if (This->renderTarget == swapchainBackBuffer) {
6327 /* Don't know what to do, so warn and carry on as usual (which in this case leaves the renderterget in limbo) */
6328 FIXME("Atempting to release a swapchain that is currently beuing used as a render target, behaviour is undefined\n");
6332 /* Go through the swapchain list and try to find the swapchain being released */
6333 while(*nextSwapchain != NULL && (*nextSwapchain)->swapchain != swapChain) {
6334 nextSwapchain = &(*nextSwapchain)->next;
6337 /* Check to see if we found the swapchain */
6338 if (NULL != *nextSwapchain) {
6339 /* We found the swapchain so remove it from the list */
6340 TRACE("(%p) releasing swapchain(%p)\n", iface, swapChain);
6341 HeapFree(GetProcessHeap(), 0 , *nextSwapchain);
6342 *nextSwapchain = (*nextSwapchain)->next;
6343 } else {
6344 /* We didn't find the swapchain on the list, this can only heppen because of a programming error in wined3d */
6345 FIXME("(%p) Attempting to release a swapchain (%p) that hasn't been stored\n", iface, swapChain);
6348 TRACE("swapchain (%p) released\n", swapChain);
6349 return;
6352 /**********************************************************
6353 * IWineD3DDevice VTbl follows
6354 **********************************************************/
6356 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
6358 /*** IUnknown methods ***/
6359 IWineD3DDeviceImpl_QueryInterface,
6360 IWineD3DDeviceImpl_AddRef,
6361 IWineD3DDeviceImpl_Release,
6362 /*** IWineD3DDevice methods ***/
6363 IWineD3DDeviceImpl_GetParent,
6364 /*** Creation methods**/
6365 IWineD3DDeviceImpl_CreateVertexBuffer,
6366 IWineD3DDeviceImpl_CreateIndexBuffer,
6367 IWineD3DDeviceImpl_CreateStateBlock,
6368 IWineD3DDeviceImpl_CreateSurface,
6369 IWineD3DDeviceImpl_CreateTexture,
6370 IWineD3DDeviceImpl_CreateVolumeTexture,
6371 IWineD3DDeviceImpl_CreateVolume,
6372 IWineD3DDeviceImpl_CreateCubeTexture,
6373 IWineD3DDeviceImpl_CreateQuery,
6374 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
6375 IWineD3DDeviceImpl_CreateVertexDeclaration,
6376 IWineD3DDeviceImpl_CreateVertexShader,
6377 IWineD3DDeviceImpl_CreatePixelShader,
6378 /*** Odd functions **/
6379 IWineD3DDeviceImpl_EvictManagedResources,
6380 IWineD3DDeviceImpl_GetAvailableTextureMem,
6381 IWineD3DDeviceImpl_GetBackBuffer,
6382 IWineD3DDeviceImpl_GetCreationParameters,
6383 IWineD3DDeviceImpl_GetDeviceCaps,
6384 IWineD3DDeviceImpl_GetDirect3D,
6385 IWineD3DDeviceImpl_GetDisplayMode,
6386 IWineD3DDeviceImpl_GetNumberOfSwapChains,
6387 IWineD3DDeviceImpl_GetRasterStatus,
6388 IWineD3DDeviceImpl_GetSwapChain,
6389 IWineD3DDeviceImpl_Reset,
6390 IWineD3DDeviceImpl_SetDialogBoxMode,
6391 IWineD3DDeviceImpl_SetCursorProperties,
6392 IWineD3DDeviceImpl_SetCursorPosition,
6393 IWineD3DDeviceImpl_ShowCursor,
6394 IWineD3DDeviceImpl_TestCooperativeLevel,
6395 /*** Getters and setters **/
6396 IWineD3DDeviceImpl_SetClipPlane,
6397 IWineD3DDeviceImpl_GetClipPlane,
6398 IWineD3DDeviceImpl_SetClipStatus,
6399 IWineD3DDeviceImpl_GetClipStatus,
6400 IWineD3DDeviceImpl_SetCurrentTexturePalette,
6401 IWineD3DDeviceImpl_GetCurrentTexturePalette,
6402 IWineD3DDeviceImpl_SetDepthStencilSurface,
6403 IWineD3DDeviceImpl_GetDepthStencilSurface,
6404 IWineD3DDeviceImpl_SetFVF,
6405 IWineD3DDeviceImpl_GetFVF,
6406 IWineD3DDeviceImpl_SetGammaRamp,
6407 IWineD3DDeviceImpl_GetGammaRamp,
6408 IWineD3DDeviceImpl_SetIndices,
6409 IWineD3DDeviceImpl_GetIndices,
6410 IWineD3DDeviceImpl_SetLight,
6411 IWineD3DDeviceImpl_GetLight,
6412 IWineD3DDeviceImpl_SetLightEnable,
6413 IWineD3DDeviceImpl_GetLightEnable,
6414 IWineD3DDeviceImpl_SetMaterial,
6415 IWineD3DDeviceImpl_GetMaterial,
6416 IWineD3DDeviceImpl_SetNPatchMode,
6417 IWineD3DDeviceImpl_GetNPatchMode,
6418 IWineD3DDeviceImpl_SetPaletteEntries,
6419 IWineD3DDeviceImpl_GetPaletteEntries,
6420 IWineD3DDeviceImpl_SetPixelShader,
6421 IWineD3DDeviceImpl_GetPixelShader,
6422 IWineD3DDeviceImpl_SetPixelShaderConstantB,
6423 IWineD3DDeviceImpl_GetPixelShaderConstantB,
6424 IWineD3DDeviceImpl_SetPixelShaderConstantI,
6425 IWineD3DDeviceImpl_GetPixelShaderConstantI,
6426 IWineD3DDeviceImpl_SetPixelShaderConstantF,
6427 IWineD3DDeviceImpl_GetPixelShaderConstantF,
6428 IWineD3DDeviceImpl_SetRenderState,
6429 IWineD3DDeviceImpl_GetRenderState,
6430 IWineD3DDeviceImpl_SetRenderTarget,
6431 IWineD3DDeviceImpl_GetRenderTarget,
6432 IWineD3DDeviceImpl_SetSamplerState,
6433 IWineD3DDeviceImpl_GetSamplerState,
6434 IWineD3DDeviceImpl_SetScissorRect,
6435 IWineD3DDeviceImpl_GetScissorRect,
6436 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
6437 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
6438 IWineD3DDeviceImpl_SetStreamSource,
6439 IWineD3DDeviceImpl_GetStreamSource,
6440 IWineD3DDeviceImpl_SetStreamSourceFreq,
6441 IWineD3DDeviceImpl_GetStreamSourceFreq,
6442 IWineD3DDeviceImpl_SetTexture,
6443 IWineD3DDeviceImpl_GetTexture,
6444 IWineD3DDeviceImpl_SetTextureStageState,
6445 IWineD3DDeviceImpl_GetTextureStageState,
6446 IWineD3DDeviceImpl_SetTransform,
6447 IWineD3DDeviceImpl_GetTransform,
6448 IWineD3DDeviceImpl_SetVertexDeclaration,
6449 IWineD3DDeviceImpl_GetVertexDeclaration,
6450 IWineD3DDeviceImpl_SetVertexShader,
6451 IWineD3DDeviceImpl_GetVertexShader,
6452 IWineD3DDeviceImpl_SetVertexShaderConstantB,
6453 IWineD3DDeviceImpl_GetVertexShaderConstantB,
6454 IWineD3DDeviceImpl_SetVertexShaderConstantI,
6455 IWineD3DDeviceImpl_GetVertexShaderConstantI,
6456 IWineD3DDeviceImpl_SetVertexShaderConstantF,
6457 IWineD3DDeviceImpl_GetVertexShaderConstantF,
6458 IWineD3DDeviceImpl_SetViewport,
6459 IWineD3DDeviceImpl_GetViewport,
6460 IWineD3DDeviceImpl_MultiplyTransform,
6461 IWineD3DDeviceImpl_ValidateDevice,
6462 IWineD3DDeviceImpl_ProcessVertices,
6463 /*** State block ***/
6464 IWineD3DDeviceImpl_BeginStateBlock,
6465 IWineD3DDeviceImpl_EndStateBlock,
6466 /*** Scene management ***/
6467 IWineD3DDeviceImpl_BeginScene,
6468 IWineD3DDeviceImpl_EndScene,
6469 IWineD3DDeviceImpl_Present,
6470 IWineD3DDeviceImpl_Clear,
6471 /*** Drawing ***/
6472 IWineD3DDeviceImpl_DrawPrimitive,
6473 IWineD3DDeviceImpl_DrawIndexedPrimitive,
6474 IWineD3DDeviceImpl_DrawPrimitiveUP,
6475 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
6476 IWineD3DDeviceImpl_DrawRectPatch,
6477 IWineD3DDeviceImpl_DrawTriPatch,
6478 IWineD3DDeviceImpl_DeletePatch,
6479 IWineD3DDeviceImpl_ColorFill,
6480 IWineD3DDeviceImpl_UpdateTexture,
6481 IWineD3DDeviceImpl_UpdateSurface,
6482 IWineD3DDeviceImpl_StretchRect,
6483 IWineD3DDeviceImpl_GetRenderTargetData,
6484 IWineD3DDeviceImpl_GetFrontBufferData,
6485 /*** Internal use IWineD3DDevice methods ***/
6486 IWineD3DDeviceImpl_SetupTextureStates,
6487 /*** object tracking ***/
6488 IWineD3DDeviceImpl_SwapChainReleased,
6489 IWineD3DDeviceImpl_ResourceReleased
6493 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
6494 WINED3DRS_ALPHABLENDENABLE ,
6495 WINED3DRS_ALPHAFUNC ,
6496 WINED3DRS_ALPHAREF ,
6497 WINED3DRS_ALPHATESTENABLE ,
6498 WINED3DRS_BLENDOP ,
6499 WINED3DRS_COLORWRITEENABLE ,
6500 WINED3DRS_DESTBLEND ,
6501 WINED3DRS_DITHERENABLE ,
6502 WINED3DRS_FILLMODE ,
6503 WINED3DRS_FOGDENSITY ,
6504 WINED3DRS_FOGEND ,
6505 WINED3DRS_FOGSTART ,
6506 WINED3DRS_LASTPIXEL ,
6507 WINED3DRS_SHADEMODE ,
6508 WINED3DRS_SRCBLEND ,
6509 WINED3DRS_STENCILENABLE ,
6510 WINED3DRS_STENCILFAIL ,
6511 WINED3DRS_STENCILFUNC ,
6512 WINED3DRS_STENCILMASK ,
6513 WINED3DRS_STENCILPASS ,
6514 WINED3DRS_STENCILREF ,
6515 WINED3DRS_STENCILWRITEMASK ,
6516 WINED3DRS_STENCILZFAIL ,
6517 WINED3DRS_TEXTUREFACTOR ,
6518 WINED3DRS_WRAP0 ,
6519 WINED3DRS_WRAP1 ,
6520 WINED3DRS_WRAP2 ,
6521 WINED3DRS_WRAP3 ,
6522 WINED3DRS_WRAP4 ,
6523 WINED3DRS_WRAP5 ,
6524 WINED3DRS_WRAP6 ,
6525 WINED3DRS_WRAP7 ,
6526 WINED3DRS_ZENABLE ,
6527 WINED3DRS_ZFUNC ,
6528 WINED3DRS_ZWRITEENABLE
6531 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
6532 WINED3DTSS_ADDRESSW ,
6533 WINED3DTSS_ALPHAARG0 ,
6534 WINED3DTSS_ALPHAARG1 ,
6535 WINED3DTSS_ALPHAARG2 ,
6536 WINED3DTSS_ALPHAOP ,
6537 WINED3DTSS_BUMPENVLOFFSET ,
6538 WINED3DTSS_BUMPENVLSCALE ,
6539 WINED3DTSS_BUMPENVMAT00 ,
6540 WINED3DTSS_BUMPENVMAT01 ,
6541 WINED3DTSS_BUMPENVMAT10 ,
6542 WINED3DTSS_BUMPENVMAT11 ,
6543 WINED3DTSS_COLORARG0 ,
6544 WINED3DTSS_COLORARG1 ,
6545 WINED3DTSS_COLORARG2 ,
6546 WINED3DTSS_COLOROP ,
6547 WINED3DTSS_RESULTARG ,
6548 WINED3DTSS_TEXCOORDINDEX ,
6549 WINED3DTSS_TEXTURETRANSFORMFLAGS
6552 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
6553 WINED3DSAMP_ADDRESSU ,
6554 WINED3DSAMP_ADDRESSV ,
6555 WINED3DSAMP_ADDRESSW ,
6556 WINED3DSAMP_BORDERCOLOR ,
6557 WINED3DSAMP_MAGFILTER ,
6558 WINED3DSAMP_MINFILTER ,
6559 WINED3DSAMP_MIPFILTER ,
6560 WINED3DSAMP_MIPMAPLODBIAS ,
6561 WINED3DSAMP_MAXMIPLEVEL ,
6562 WINED3DSAMP_MAXANISOTROPY ,
6563 WINED3DSAMP_SRGBTEXTURE ,
6564 WINED3DSAMP_ELEMENTINDEX
6567 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
6568 WINED3DRS_AMBIENT ,
6569 WINED3DRS_AMBIENTMATERIALSOURCE ,
6570 WINED3DRS_CLIPPING ,
6571 WINED3DRS_CLIPPLANEENABLE ,
6572 WINED3DRS_COLORVERTEX ,
6573 WINED3DRS_DIFFUSEMATERIALSOURCE ,
6574 WINED3DRS_EMISSIVEMATERIALSOURCE ,
6575 WINED3DRS_FOGDENSITY ,
6576 WINED3DRS_FOGEND ,
6577 WINED3DRS_FOGSTART ,
6578 WINED3DRS_FOGTABLEMODE ,
6579 WINED3DRS_FOGVERTEXMODE ,
6580 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
6581 WINED3DRS_LIGHTING ,
6582 WINED3DRS_LOCALVIEWER ,
6583 WINED3DRS_MULTISAMPLEANTIALIAS ,
6584 WINED3DRS_MULTISAMPLEMASK ,
6585 WINED3DRS_NORMALIZENORMALS ,
6586 WINED3DRS_PATCHEDGESTYLE ,
6587 WINED3DRS_POINTSCALE_A ,
6588 WINED3DRS_POINTSCALE_B ,
6589 WINED3DRS_POINTSCALE_C ,
6590 WINED3DRS_POINTSCALEENABLE ,
6591 WINED3DRS_POINTSIZE ,
6592 WINED3DRS_POINTSIZE_MAX ,
6593 WINED3DRS_POINTSIZE_MIN ,
6594 WINED3DRS_POINTSPRITEENABLE ,
6595 WINED3DRS_RANGEFOGENABLE ,
6596 WINED3DRS_SPECULARMATERIALSOURCE ,
6597 WINED3DRS_TWEENFACTOR ,
6598 WINED3DRS_VERTEXBLEND
6601 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
6602 WINED3DTSS_TEXCOORDINDEX ,
6603 WINED3DTSS_TEXTURETRANSFORMFLAGS
6606 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
6607 WINED3DSAMP_DMAPOFFSET