wined3d: Don't set the container to the device for standalone surfaces.
[wine/multimedia.git] / dlls / wined3d / device.c
blobf814973bce989a518a09747ea32ce836155172ae
1 /*
2 * IWineD3DDevice implementation
4 * Copyright 2002-2005 Jason Edmeades
5 * Copyright 2003-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "config.h"
25 #include "wined3d_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
28 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
30 /* x11drv GDI escapes */
31 #define X11DRV_ESCAPE 6789
32 enum x11drv_escape_codes
34 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
35 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
36 X11DRV_GET_FONT, /* get current X font for a DC */
39 /* retrieve the X display to use on a given DC */
40 inline static Display *get_display( HDC hdc )
42 Display *display;
43 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
45 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
46 sizeof(display), (LPSTR)&display )) display = NULL;
47 return display;
50 /* Memory tracking and object counting */
51 static unsigned int emulated_textureram = 64*1024*1024;
53 /* TODO: setup some flags in the regestry to enable, disable pbuffer support */
54 /* enable pbuffer support for offscreen textures */
55 BOOL pbuffer_support = FALSE;
56 /* allocate one pbuffer per surface */
57 BOOL pbuffer_per_surface = FALSE;
59 /* static function declarations */
60 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
62 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type);
64 /* helper macros */
65 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return D3DERR_OUTOFVIDEOMEMORY;}
67 #define D3DCREATEOBJECTINSTANCE(object, type) { \
68 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
69 D3DMEMCHECK(object, pp##type); \
70 object->lpVtbl = &IWineD3D##type##_Vtbl; \
71 object->wineD3DDevice = This; \
72 object->parent = parent; \
73 object->ref = 1; \
74 *pp##type = (IWineD3D##type *) object; \
77 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
78 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
79 D3DMEMCHECK(object, pp##type); \
80 object->lpVtbl = &IWineD3D##type##_Vtbl; \
81 object->resource.wineD3DDevice = This; \
82 object->resource.parent = parent; \
83 object->resource.resourceType = d3dtype; \
84 object->resource.ref = 1; \
85 object->resource.pool = Pool; \
86 object->resource.format = Format; \
87 object->resource.usage = Usage; \
88 object->resource.size = _size; \
89 /* Check that we have enough video ram left */ \
90 if (Pool == D3DPOOL_DEFAULT) { \
91 if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
92 WARN("Out of 'bogus' video memory\n"); \
93 HeapFree(GetProcessHeap(), 0, object); \
94 *pp##type = NULL; \
95 return D3DERR_OUTOFVIDEOMEMORY; \
96 } \
97 globalChangeGlRam(_size); \
98 } \
99 object->resource.allocatedMemory = (0 == _size ? NULL : Pool == D3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
100 if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != D3DPOOL_DEFAULT) { \
101 FIXME("Out of memory!\n"); \
102 HeapFree(GetProcessHeap(), 0, object); \
103 *pp##type = NULL; \
104 return D3DERR_OUTOFVIDEOMEMORY; \
106 *pp##type = (IWineD3D##type *) object; \
107 IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
108 TRACE("(%p) : Created resource %p\n", This, object); \
111 #define D3DINITIALIZEBASETEXTURE(_basetexture) { \
112 _basetexture.levels = Levels; \
113 _basetexture.filterType = (Usage & D3DUSAGE_AUTOGENMIPMAP) ? D3DTEXF_LINEAR : D3DTEXF_NONE; \
114 _basetexture.LOD = 0; \
115 _basetexture.dirty = TRUE; \
118 /**********************************************************
119 * Global variable / Constants follow
120 **********************************************************/
121 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
123 /**********************************************************
124 * Utility functions follow
125 **********************************************************/
126 /* Convert the D3DLIGHT properties into equivalent gl lights */
127 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
129 float quad_att;
130 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
131 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
133 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
134 glMatrixMode(GL_MODELVIEW);
135 glPushMatrix();
136 glLoadMatrixf((float *)&This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
138 /* Diffuse: */
139 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
140 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
141 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
142 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
143 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
144 checkGLcall("glLightfv");
146 /* Specular */
147 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
148 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
149 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
150 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
151 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
152 checkGLcall("glLightfv");
154 /* Ambient */
155 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
156 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
157 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
158 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
159 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
160 checkGLcall("glLightfv");
162 /* Attenuation - Are these right? guessing... */
163 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
164 checkGLcall("glLightf");
165 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
166 checkGLcall("glLightf");
168 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) != 0) {
169 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
170 } else {
171 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
174 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
175 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
176 checkGLcall("glLightf");
178 switch (lightInfo->OriginalParms.Type) {
179 case D3DLIGHT_POINT:
180 /* Position */
181 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
182 checkGLcall("glLightfv");
183 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
184 checkGLcall("glLightf");
185 /* FIXME: Range */
186 break;
188 case D3DLIGHT_SPOT:
189 /* Position */
190 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
191 checkGLcall("glLightfv");
192 /* Direction */
193 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
194 checkGLcall("glLightfv");
195 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
196 checkGLcall("glLightf");
197 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
198 checkGLcall("glLightf");
199 /* FIXME: Range */
200 break;
202 case D3DLIGHT_DIRECTIONAL:
203 /* Direction */
204 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
205 checkGLcall("glLightfv");
206 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
207 checkGLcall("glLightf");
208 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
209 checkGLcall("glLightf");
210 break;
212 default:
213 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
216 /* Restore the modelview matrix */
217 glPopMatrix();
220 /* Apply the current values to the specified texture stage */
221 void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Sampler, DWORD Flags) {
222 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
223 float col[4];
225 union {
226 float f;
227 DWORD d;
228 } tmpvalue;
230 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
231 clamping, MIPLOD, etc. This will work for up to 16 samplers.
234 if (Sampler >= GL_LIMITS(samplers)) {
235 FIXME("Trying to set the state of more samplers %ld than are supported %d by this openGL implementation\n", Sampler, GL_LIMITS(samplers));
236 return;
238 VTRACE(("Activating appropriate texture state %ld\n", Sampler));
239 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
240 ENTER_GL();
241 GLACTIVETEXTURE(Sampler);
242 LEAVE_GL();
243 /* Could we use bindTexture and then apply the states instead of GLACTIVETEXTURE */
244 } else if (Sampler > 0) {
245 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
246 return;
249 /* TODO: change this to a lookup table
250 LOOKUP_TEXTURE_STATES lists all texture states that should be applied.
251 LOOKUP_CONTEXT_SATES list all context applicable states that can be applied
252 etc.... it's a lot cleaner, quicker and possibly easier to maintain than running a switch and setting a skip flag...
253 especially when there are a number of groups of states. */
255 TRACE("-----------------------> Updating the texture at Sampler %ld to have new texture state information\n", Sampler);
257 /* The list of states not to apply is a big as the list of states to apply, so it makes sense to produce an inclusive list */
258 #define APPLY_STATE(_state) IWineD3DDeviceImpl_ApplyTextureUnitState(iface, Sampler, _state)
259 /* these are the only two supported states that need to be applied */
260 APPLY_STATE(WINED3DTSS_TEXCOORDINDEX);
261 APPLY_STATE(WINED3DTSS_TEXTURETRANSFORMFLAGS);
262 #if 0 /* not supported at the moment */
263 APPLY_STATE(WINED3DTSS_BUMPENVMAT00);
264 APPLY_STATE(WINED3DTSS_BUMPENVMAT01);
265 APPLY_STATE(WINED3DTSS_BUMPENVMAT10);
266 APPLY_STATE(WINED3DTSS_BUMPENVMAT11);
267 APPLY_STATE(WINED3DTSS_BUMPENVLSCALE);
268 APPLY_STATE(WINED3DTSS_BUMPENVLOFFSET);
269 APPLY_STATE(WINED3DTSS_RESULTARG);
270 APPLY_STATE(WINED3DTSS_CONSTANT);
271 #endif
272 /* a quick sanity check in case someone forgot to update this function */
273 if (WINED3D_HIGHEST_TEXTURE_STATE > WINED3DTSS_CONSTANT) {
274 FIXME("(%p) : There are more texture states than expected, update device.c to match\n", This);
276 #undef APPLY_STATE
278 /* apply any sampler states that always need applying */
279 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
280 tmpvalue.d = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPMAPLODBIAS];
281 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
282 GL_TEXTURE_LOD_BIAS_EXT,
283 tmpvalue.f);
284 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
287 /* Note the D3DRS value applies to all textures, but GL has one
288 * per texture, so apply it now ready to be used!
290 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
291 /* Set the default alpha blend color */
292 glBlendColor(col[0], col[1], col[2], col[3]);
293 checkGLcall("glBlendColor");
295 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
296 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
297 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
299 /* TODO: NV_POINT_SPRITE */
300 if (GL_SUPPORT(ARB_POINT_SPRITE)) {
301 if (This->stateBlock->renderState[WINED3DRS_POINTSPRITEENABLE] != FALSE) {
302 /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
303 glDisable(GL_POINT_SMOOTH);
305 /* Centre the texture on the vertex */
306 VTRACE("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
307 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
309 VTRACE("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
310 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
311 checkGLcall("glTexEnvf(...)");
312 VTRACE("glEnable( GL_POINT_SPRITE_ARB )\n");
313 glEnable( GL_POINT_SPRITE_ARB );
314 checkGLcall("glEnable(...)");
315 } else {
316 VTRACE("glDisable( GL_POINT_SPRITE_ARB )\n");
317 glDisable( GL_POINT_SPRITE_ARB );
318 checkGLcall("glEnable(...)");
322 TRACE("-----------------------> Updated the texture at Sampler %ld to have new texture state information\n", Sampler);
325 /**********************************************************
326 * IUnknown parts follows
327 **********************************************************/
329 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
331 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
333 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
334 if (IsEqualGUID(riid, &IID_IUnknown)
335 || IsEqualGUID(riid, &IID_IWineD3DBase)
336 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
337 IUnknown_AddRef(iface);
338 *ppobj = This;
339 return D3D_OK;
342 return E_NOINTERFACE;
345 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
346 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
347 ULONG refCount = InterlockedIncrement(&This->ref);
349 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
350 return refCount;
353 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
354 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
355 ULONG refCount = InterlockedDecrement(&This->ref);
357 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
359 if (!refCount) {
360 /* TODO: Clean up all the surfaces and textures! */
361 /* FIXME: Create targets and state blocks in d3d8 */
362 if (((IWineD3DImpl *)This->wineD3D)->dxVersion > 8) { /*We don't create a state block in d3d8 yet*/
363 /* NOTE: You must release the parent if the object was created via a callback
364 ** ***************************/
365 /* TODO: this is exactly the same as required by _Reset.., so at some point we need to move the code so that is can be called by reset add release... */
366 /* Release all of the swapchains, except the implicit swapchain */
367 IUnknown* stencilBufferParent;
368 IUnknown* swapChainParent;
370 /* NOTE: Don't release swapchain 0 here, it's 'special' */
371 SwapChainList *nextSwapchain = This->swapchains;
372 if (nextSwapchain != NULL) {
373 nextSwapchain = nextSwapchain->next;
374 } else {
375 WARN("Expected to find the implicit swapchain\n");
378 /* release all the other swapchains */
379 while (nextSwapchain != NULL) {
380 SwapChainList *prevSwapchain = nextSwapchain;
381 nextSwapchain = nextSwapchain->next;
382 IWineD3DSwapChain_Release(prevSwapchain->swapchain);
383 /* NOTE: no need to free the list element, it will be done by the release callback
384 HeapFree(GetProcessHeap(), 0, prevSwapchain); */
386 /* Release the buffers (with sanity checks)*/
387 if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
388 if(This->depthStencilBuffer != This->stencilBufferTarget)
389 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
391 This->stencilBufferTarget = NULL;
393 if(IWineD3DSurface_Release(This->renderTarget) >0){
394 /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
396 This->renderTarget = NULL;
398 IWineD3DSurface_GetParent(This->depthStencilBuffer, &stencilBufferParent);
399 IUnknown_Release(stencilBufferParent); /* once for the get parent */
400 if(IUnknown_Release(stencilBufferParent) >0){ /* the second time for when it was created */
401 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
403 This->depthStencilBuffer = NULL;
405 /* Release the update stateblock */
406 if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){
407 if(This->updateStateBlock != This->stateBlock)
408 FIXME("(%p) Something's still holding the Update stateblock\n",This);
410 This->updateStateBlock = NULL;
411 { /* because were not doing proper internal refcounts releasing the primary state block
412 causes recursion with the extra checks in ResourceReleased, to avoid this we have
413 to set this->stateBlock = NULL; first */
414 IWineD3DStateBlock *stateBlock = (IWineD3DStateBlock *)This->stateBlock;
415 This->stateBlock = NULL;
417 /* Release the stateblock */
418 if(IWineD3DStateBlock_Release(stateBlock) > 0){
419 FIXME("(%p) Something's still holding the Update stateblock\n",This);
423 if (This->swapchains != NULL) {
424 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
425 IWineD3DSwapChain_GetParent(This->swapchains->swapchain, &swapChainParent);
426 IUnknown_Release(swapChainParent); /* once for the get parent */
427 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
428 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
432 if (This->resources != NULL ) {
433 FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This);
435 #if 0 /* TODO: Dump a list of all the resources still bound */
436 dumpResources(This->resources);
437 #endif
438 /* TODO: set the resources to a lost state */
442 IWineD3D_Release(This->wineD3D);
443 This->wineD3D = NULL;
444 HeapFree(GetProcessHeap(), 0, This);
445 TRACE("Freed device %p\n", This);
446 This = NULL;
448 return refCount;
451 /**********************************************************
452 * IWineD3DDevice implementation follows
453 **********************************************************/
454 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
455 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
456 *pParent = This->parent;
457 IUnknown_AddRef(This->parent);
458 return D3D_OK;
461 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
462 DWORD FVF, D3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
463 IUnknown *parent) {
464 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
465 IWineD3DVertexBufferImpl *object;
466 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
467 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, D3DRTYPE_VERTEXBUFFER, Size)
469 /*TODO: use VBO's */
470 if (Pool == D3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
471 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
473 object->fvf = FVF;
475 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
476 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
478 return D3D_OK;
481 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
482 WINED3DFORMAT Format, D3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
483 HANDLE *sharedHandle, IUnknown *parent) {
484 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
485 IWineD3DIndexBufferImpl *object;
486 TRACE("(%p) Creating index buffer\n", This);
488 /* Allocate the storage for the device */
489 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,D3DRTYPE_INDEXBUFFER, Length)
491 /*TODO: use VBO's */
492 if (Pool == D3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
493 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
496 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
497 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
498 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
500 return D3D_OK;
503 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
505 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
506 IWineD3DStateBlockImpl *object;
507 int i, j;
509 D3DCREATEOBJECTINSTANCE(object, StateBlock)
510 object->blockType = Type;
512 /* Special case - Used during initialization to produce a placeholder stateblock
513 so other functions called can update a state block */
514 if (Type == WINED3DSBT_INIT) {
515 /* Don't bother increasing the reference count otherwise a device will never
516 be freed due to circular dependencies */
517 return D3D_OK;
520 /* Otherwise, might as well set the whole state block to the appropriate values */
521 if ( This->stateBlock != NULL) {
522 memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
523 } else {
524 memset(object->streamFreq, 1, sizeof(object->streamFreq));
527 /* Reset the ref and type after kludging it */
528 object->wineD3DDevice = This;
529 object->ref = 1;
530 object->blockType = Type;
532 TRACE("Updating changed flags appropriate for type %d\n", Type);
534 if (Type == WINED3DSBT_ALL) {
536 TRACE("ALL => Pretend everything has changed\n");
537 memset(&object->changed, TRUE, sizeof(This->stateBlock->changed));
538 } else if (Type == WINED3DSBT_PIXELSTATE) {
540 TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
541 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
543 object->changed.pixelShader = TRUE;
545 /* Pixel Shader Constants */
546 for (i = 0; i < MAX_PSHADER_CONSTANTS; ++i) {
547 object->changed.pixelShaderConstants[i] = TRUE;
549 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
550 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
552 for (j = 0; j < GL_LIMITS(textures); j++) {
553 for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
554 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
557 for (j = 0 ; j < 16; j++) {
558 for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
560 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
564 } else if (Type == WINED3DSBT_VERTEXSTATE) {
566 TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
567 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
569 object->changed.vertexShader = TRUE;
571 /* Vertex Shader Constants */
572 for (i = 0; i < MAX_VSHADER_CONSTANTS; ++i) {
573 object->changed.vertexShaderConstants[i] = TRUE;
575 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
576 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
578 for (j = 0; j < GL_LIMITS(textures); j++) {
579 for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
580 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
583 for (j = 0 ; j < 16; j++){
584 for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
585 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
589 /* Duplicate light chain */
591 PLIGHTINFOEL *src = NULL;
592 PLIGHTINFOEL *dst = NULL;
593 PLIGHTINFOEL *newEl = NULL;
594 src = This->stateBlock->lights;
595 object->lights = NULL;
598 while (src) {
599 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
600 if (newEl == NULL) return D3DERR_OUTOFVIDEOMEMORY;
601 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
602 newEl->prev = dst;
603 newEl->changed = TRUE;
604 newEl->enabledChanged = TRUE;
605 if (dst == NULL) {
606 object->lights = newEl;
607 } else {
608 dst->next = newEl;
610 dst = newEl;
611 src = src->next;
616 } else {
617 FIXME("Unrecognized state block type %d\n", Type);
620 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
621 return D3D_OK;
625 /* ************************************
626 MSDN:
627 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
629 Discard
630 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
632 If this flag is set, the contents of the depth stencil buffer will be invalid after calling either IDirect3DDevice9::Present or IDirect3DDevice9::SetDepthStencilSurface with a different depth surface.
634 ******************************** */
636 HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height, WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **ppSurface,D3DRESOURCETYPE Type, DWORD Usage, D3DPOOL Pool, D3DMULTISAMPLE_TYPE MultiSample ,DWORD MultisampleQuality, HANDLE* pSharedHandle, IUnknown *parent) {
637 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
638 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
639 unsigned int pow2Width, pow2Height;
640 unsigned int Size = 1;
641 TRACE("(%p) Create surface\n",This);
643 /** FIXME: Check ranges on the inputs are valid
644 * MSDN
645 * MultisampleQuality
646 * [in] Quality level. The valid range is between zero and one less than the level
647 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
648 * Passing a larger value returns the error D3DERR_INVALIDCALL. The MultisampleQuality
649 * values of paired render targets, depth stencil surfaces, and the MultiSample type
650 * must all match.
651 *******************************/
655 * TODO: Discard MSDN
656 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
658 * If this flag is set, the contents of the depth stencil buffer will be
659 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
660 * with a different depth surface.
662 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
663 ***************************/
665 if(MultisampleQuality < 0) {
666 FIXME("Invalid multisample level %ld\n", MultisampleQuality);
667 return D3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
670 if(MultisampleQuality > 0) {
671 FIXME("MultisampleQuality set to %ld, substituting 0\n", MultisampleQuality);
672 MultisampleQuality=0;
675 /** FIXME: Check that the format is supported
676 * by the device.
677 *******************************/
679 /* Non-power2 support */
681 /* Find the nearest pow2 match */
682 pow2Width = pow2Height = 1;
683 while (pow2Width < Width) pow2Width <<= 1;
684 while (pow2Height < Height) pow2Height <<= 1;
686 if (pow2Width > Width || pow2Height > Height) {
687 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
688 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
689 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
690 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
691 This, Width, Height);
692 return D3DERR_NOTAVAILABLE;
696 /** Check against the maximum texture sizes supported by the video card **/
697 if (pow2Width > GL_LIMITS(texture_size) || pow2Height > GL_LIMITS(texture_size)) {
698 /* one of three options
699 1: Do the same as we do with nonpow 2 and scale the texture, (any texture ops would require the texture to be scaled which is potentially slow)
700 2: Set the texture to the maxium size (bad idea)
701 3: WARN and return D3DERR_NOTAVAILABLE;
703 WARN("(%p) Application requested a surface w %d, h %d, but the graphics card only supports %d\n", This, Width, Height, GL_LIMITS(texture_size));
704 return D3DERR_NOTAVAILABLE;
709 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
710 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
711 * space!
712 *********************************/
713 if (WINED3DFMT_UNKNOWN == Format) {
714 Size = 0;
715 } else if (Format == WINED3DFMT_DXT1) {
716 /* DXT1 is half byte per pixel */
717 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4)) >> 1;
719 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
720 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
721 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4));
722 } else {
723 Size = (pow2Width * D3DFmtGetBpp(This, Format)) * pow2Height;
726 /** Create and initialise the surface resource **/
727 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,D3DRTYPE_SURFACE, Size)
728 /* "Standalone" surface */
729 IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL);
731 object->currentDesc.Width = Width;
732 object->currentDesc.Height = Height;
733 object->currentDesc.MultiSampleType = MultiSample;
734 object->currentDesc.MultiSampleQuality = MultisampleQuality;
736 /* Setup some glformat defaults */
737 if (WINED3DFMT_UNKNOWN != Format) {
738 object->glDescription.glFormat = D3DFmt2GLFmt(This, object->resource.format);
739 object->glDescription.glFormatInternal = D3DFmt2GLIntFmt(This, object->resource.format);
740 object->glDescription.glType = D3DFmt2GLType(This, object->resource.format);
741 } else {
742 object->glDescription.glFormat = 0;
743 object->glDescription.glFormatInternal = 0;
744 object->glDescription.glType = 0;
747 object->glDescription.textureName = 0;
748 object->glDescription.level = Level;
749 object->glDescription.target = GL_TEXTURE_2D;
751 /* Internal data */
752 object->pow2Width = pow2Width;
753 object->pow2Height = pow2Height;
754 object->nonpow2 = (pow2Width != Width || pow2Height != Height) ? TRUE : FALSE;
755 object->discard = Discard;
756 object->activeLock = FALSE;
758 if (WINED3DFMT_UNKNOWN != Format) {
759 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
760 object->pow2Size = (pow2Width * object->bytesPerPixel) * pow2Height;
761 } else {
762 object->bytesPerPixel = 0;
763 object->pow2Size = 0;
766 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
768 TRACE("Pool %d %d %d %d",Pool, D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM);
770 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
771 * this function is too deap to need to care about things like this.
772 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
773 * ****************************************/
774 switch(Pool) {
775 case D3DPOOL_SCRATCH:
776 if(Lockable == FALSE)
777 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
778 which are mutually exclusive, setting lockable to true\n");
779 Lockable = TRUE;
780 break;
781 case D3DPOOL_SYSTEMMEM:
782 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
783 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
784 case D3DPOOL_MANAGED:
785 if(Usage == D3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
786 Usage of DYNAMIC which are mutually exclusive, not doing \
787 anything just telling you.\n");
788 break;
789 case D3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
790 if(!(Usage & D3DUSAGE_DYNAMIC) && !(Usage & D3DUSAGE_RENDERTARGET)
791 && !(Usage && D3DUSAGE_DEPTHSTENCIL ) && Lockable == TRUE)
792 FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
793 break;
794 default:
795 FIXME("(%p) Unknown pool %d\n", This, Pool);
796 break;
799 if (Usage & D3DUSAGE_RENDERTARGET && Pool != D3DPOOL_DEFAULT) {
800 FIXME("Trying to create a render target that isn't in the default pool\n");
804 object->locked = FALSE;
805 object->lockable = (WINED3DFMT_D16_LOCKABLE == Format) ? TRUE : Lockable;
807 /* mark the texture as dirty so that it get's loaded first time around*/
808 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
809 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
810 This, Width, Height, Format, debug_d3dformat(Format),
811 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
812 return D3D_OK;
816 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
817 DWORD Usage, WINED3DFORMAT Format, D3DPOOL Pool,
818 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
819 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
821 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
822 IWineD3DTextureImpl *object;
823 unsigned int i;
824 UINT tmpW;
825 UINT tmpH;
826 HRESULT hr;
827 unsigned int pow2Width = Width;
828 unsigned int pow2Height = Height;
831 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) ....\n", This, Width, Height, Levels, Usage);
833 /* TODO: It should only be possible to create textures for formats
834 that are reported as supported */
835 if (WINED3DFMT_UNKNOWN >= Format) {
836 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
837 return D3DERR_INVALIDCALL;
840 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, D3DRTYPE_TEXTURE, 0);
841 D3DINITIALIZEBASETEXTURE(object->baseTexture);
842 object->width = Width;
843 object->height = Height;
845 /** Non-power2 support **/
846 /* Find the nearest pow2 match */
847 pow2Width = pow2Height = 1;
848 while (pow2Width < Width) pow2Width <<= 1;
849 while (pow2Height < Height) pow2Height <<= 1;
851 /** FIXME: add support for real non-power-two if it's provided by the video card **/
852 /* Precalculated scaling for 'faked' non power of two texture coords */
853 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
854 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
855 TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
857 /* Calculate levels for mip mapping */
858 if (Levels == 0) {
859 TRACE("calculating levels %d\n", object->baseTexture.levels);
860 object->baseTexture.levels++;
861 tmpW = Width;
862 tmpH = Height;
863 while (tmpW > 1 && tmpH > 1) {
864 tmpW = max(1, tmpW >> 1);
865 tmpH = max(1, tmpH >> 1);
866 object->baseTexture.levels++;
868 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
871 /* Generate all the surfaces */
872 tmpW = Width;
873 tmpH = Height;
874 for (i = 0; i < object->baseTexture.levels; i++)
876 /* use the callback to create the texture surface */
877 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
878 if (hr!= D3D_OK) {
879 int j;
880 FIXME("Failed to create surface %p\n", object);
881 /* clean up */
882 for (j = 0 ; j < i ; j++) {
883 IWineD3DSurface_Release(object->surfaces[j]);
885 /* heap free object */
886 HeapFree(GetProcessHeap(), 0, object);
888 *ppTexture = NULL;
889 return hr;
892 IWineD3DSurface_SetContainer(object->surfaces[i], (IWineD3DBase *)object);
893 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
894 /* calculate the next mipmap level */
895 tmpW = max(1, tmpW >> 1);
896 tmpH = max(1, tmpH >> 1);
899 TRACE("(%p) : Created texture %p\n", This, object);
900 return D3D_OK;
903 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
904 UINT Width, UINT Height, UINT Depth,
905 UINT Levels, DWORD Usage,
906 WINED3DFORMAT Format, D3DPOOL Pool,
907 IWineD3DVolumeTexture **ppVolumeTexture,
908 HANDLE *pSharedHandle, IUnknown *parent,
909 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
911 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
912 IWineD3DVolumeTextureImpl *object;
913 unsigned int i;
914 UINT tmpW;
915 UINT tmpH;
916 UINT tmpD;
918 /* TODO: It should only be possible to create textures for formats
919 that are reported as supported */
920 if (WINED3DFMT_UNKNOWN >= Format) {
921 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
922 return D3DERR_INVALIDCALL;
925 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, D3DRTYPE_VOLUMETEXTURE, 0);
926 D3DINITIALIZEBASETEXTURE(object->baseTexture);
928 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
929 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
931 object->width = Width;
932 object->height = Height;
933 object->depth = Depth;
935 /* Calculate levels for mip mapping */
936 if (Levels == 0) {
937 object->baseTexture.levels++;
938 tmpW = Width;
939 tmpH = Height;
940 tmpD = Depth;
941 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
942 tmpW = max(1, tmpW >> 1);
943 tmpH = max(1, tmpH >> 1);
944 tmpD = max(1, tmpD >> 1);
945 object->baseTexture.levels++;
947 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
950 /* Generate all the surfaces */
951 tmpW = Width;
952 tmpH = Height;
953 tmpD = Depth;
955 for (i = 0; i < object->baseTexture.levels; i++)
957 /* Create the volume */
958 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
959 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
961 /* Set it's container to this object */
962 IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)object);
964 /* calcualte the next mipmap level */
965 tmpW = max(1, tmpW >> 1);
966 tmpH = max(1, tmpH >> 1);
967 tmpD = max(1, tmpD >> 1);
970 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
971 TRACE("(%p) : Created volume texture %p\n", This, object);
972 return D3D_OK;
975 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
976 UINT Width, UINT Height, UINT Depth,
977 DWORD Usage,
978 WINED3DFORMAT Format, D3DPOOL Pool,
979 IWineD3DVolume** ppVolume,
980 HANDLE* pSharedHandle, IUnknown *parent) {
982 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
983 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
985 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, D3DRTYPE_VOLUME, ((Width * D3DFmtGetBpp(This, Format)) * Height * Depth))
987 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
988 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
990 object->currentDesc.Width = Width;
991 object->currentDesc.Height = Height;
992 object->currentDesc.Depth = Depth;
993 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
995 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
996 object->lockable = TRUE;
997 object->locked = FALSE;
998 memset(&object->lockedBox, 0, sizeof(D3DBOX));
999 object->dirty = TRUE;
1001 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
1004 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
1005 UINT Levels, DWORD Usage,
1006 WINED3DFORMAT Format, D3DPOOL Pool,
1007 IWineD3DCubeTexture **ppCubeTexture,
1008 HANDLE *pSharedHandle, IUnknown *parent,
1009 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1011 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1012 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1013 unsigned int i, j;
1014 UINT tmpW;
1015 HRESULT hr;
1016 unsigned int pow2EdgeLength = EdgeLength;
1018 /* TODO: It should only be possible to create textures for formats
1019 that are reported as supported */
1020 if (WINED3DFMT_UNKNOWN >= Format) {
1021 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
1022 return D3DERR_INVALIDCALL;
1025 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, D3DRTYPE_CUBETEXTURE, 0);
1026 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1028 TRACE("(%p) Create Cube Texture\n", This);
1030 /** Non-power2 support **/
1032 /* Find the nearest pow2 match */
1033 pow2EdgeLength = 1;
1034 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
1036 object->edgeLength = EdgeLength;
1037 /* TODO: support for native non-power 2 */
1038 /* Precalculated scaling for 'faked' non power of two texture coords */
1039 object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
1041 /* Calculate levels for mip mapping */
1042 if (Levels == 0) {
1043 object->baseTexture.levels++;
1044 tmpW = EdgeLength;
1045 while (tmpW > 1) {
1046 tmpW = max(1, tmpW >> 1);
1047 object->baseTexture.levels++;
1049 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1052 /* Generate all the surfaces */
1053 tmpW = EdgeLength;
1054 for (i = 0; i < object->baseTexture.levels; i++) {
1056 /* Create the 6 faces */
1057 for (j = 0; j < 6; j++) {
1059 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
1060 i /* Level */, &object->surfaces[j][i],pSharedHandle);
1062 if(hr!= D3D_OK) {
1063 /* clean up */
1064 int k;
1065 int l;
1066 for (l = 0; l < j; l++) {
1067 IWineD3DSurface_Release(object->surfaces[j][i]);
1069 for (k = 0; k < i; k++) {
1070 for (l = 0; l < 6; l++) {
1071 IWineD3DSurface_Release(object->surfaces[l][j]);
1075 FIXME("(%p) Failed to create surface\n",object);
1076 HeapFree(GetProcessHeap(),0,object);
1077 *ppCubeTexture = NULL;
1078 return hr;
1080 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IWineD3DBase *)object);
1081 TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1083 tmpW = max(1, tmpW >> 1);
1086 TRACE("(%p) : Created Cube Texture %p\n", This, object);
1087 *ppCubeTexture = (IWineD3DCubeTexture *) object;
1088 return D3D_OK;
1091 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1092 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1093 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1095 if (NULL == ppQuery) {
1096 /* Just a check to see if we support this type of query */
1097 HRESULT hr = D3DERR_NOTAVAILABLE;
1098 /* Lie and say everything is good (we can return ok fake data from a stub) */
1099 switch(Type) {
1100 case WINED3DQUERYTYPE_VCACHE:
1101 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1102 case WINED3DQUERYTYPE_VERTEXSTATS:
1103 case WINED3DQUERYTYPE_EVENT:
1104 case WINED3DQUERYTYPE_TIMESTAMP:
1105 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1106 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1107 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1108 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1109 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1110 case WINED3DQUERYTYPE_PIXELTIMINGS:
1111 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1112 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1113 break;
1114 case WINED3DQUERYTYPE_OCCLUSION:
1115 TRACE("(%p) occlusion query\n", This);
1116 if (GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY))
1117 hr = D3D_OK;
1118 break;
1119 default:
1120 FIXME("(%p) Unhandled query type %d\n",This , Type);
1122 FIXME("(%p) : Stub request for query type %d returned %ld\n", This, Type, hr);
1123 return hr;
1126 D3DCREATEOBJECTINSTANCE(object, Query)
1127 object->type = Type;
1128 /* allocated the 'extended' data based on the type of query requested */
1129 switch(Type){
1130 case D3DQUERYTYPE_OCCLUSION:
1131 if(GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY)) {
1132 TRACE("(%p) Allocating data for an occlusion query\n", This);
1133 object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1134 break;
1136 case D3DQUERYTYPE_VCACHE:
1137 case D3DQUERYTYPE_RESOURCEMANAGER:
1138 case D3DQUERYTYPE_VERTEXSTATS:
1139 case D3DQUERYTYPE_EVENT:
1140 case D3DQUERYTYPE_TIMESTAMP:
1141 case D3DQUERYTYPE_TIMESTAMPDISJOINT:
1142 case D3DQUERYTYPE_TIMESTAMPFREQ:
1143 case D3DQUERYTYPE_PIPELINETIMINGS:
1144 case D3DQUERYTYPE_INTERFACETIMINGS:
1145 case D3DQUERYTYPE_VERTEXTIMINGS:
1146 case D3DQUERYTYPE_PIXELTIMINGS:
1147 case D3DQUERYTYPE_BANDWIDTHTIMINGS:
1148 case D3DQUERYTYPE_CACHEUTILIZATION:
1149 default:
1150 object->extendedData = 0;
1151 FIXME("(%p) Unhandled query type %d\n",This , Type);
1153 TRACE("(%p) : Created Query %p\n", This, object);
1154 return D3D_OK;
1157 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1158 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1159 IUnknown* parent,
1160 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1161 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1162 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1164 HDC hDc;
1165 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1166 int num;
1167 XVisualInfo template;
1168 GLXContext oldContext;
1169 Drawable oldDrawable;
1170 HRESULT hr = D3D_OK;
1172 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1174 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1175 * does a device hold a reference to a swap chain giving them a lifetime of the device
1176 * or does the swap chain notify the device of its destruction.
1177 *******************************/
1179 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1181 /* Initialize other useful values */
1182 object->presentParms.BackBufferCount = 1; /* TODO:? support for gl_aux buffers */
1184 /*********************
1185 * Lookup the window Handle and the relating X window handle
1186 ********************/
1188 /* Setup hwnd we are using, plus which display this equates to */
1189 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1190 if (!object->win_handle) {
1191 object->win_handle = This->createParms.hFocusWindow;
1194 object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window" );
1195 hDc = GetDC(object->win_handle);
1196 object->display = get_display(hDc);
1197 ReleaseDC(object->win_handle, hDc);
1198 TRACE("Using a display of %p %p\n", object->display, hDc);
1200 if (NULL == object->display || NULL == hDc) {
1201 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1202 return D3DERR_NOTAVAILABLE;
1205 if (object->win == 0) {
1206 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1207 return D3DERR_NOTAVAILABLE;
1210 * Create an opengl context for the display visual
1211 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1212 * use different properties after that point in time. FIXME: How to handle when requested format
1213 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1214 * it chooses is identical to the one already being used!
1215 **********************************/
1217 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1218 ENTER_GL();
1220 /* Create a new context for this swapchain */
1221 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1222 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1223 (or the best possible if none is requested) */
1224 TRACE("Found x visual ID : %ld\n", template.visualid);
1226 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1227 if (NULL == object->visInfo) {
1228 ERR("cannot really get XVisual\n");
1229 LEAVE_GL();
1230 return D3DERR_NOTAVAILABLE;
1231 } else {
1232 int n, value;
1233 /* Write out some debug info about the visual/s */
1234 TRACE("Using x visual ID : %ld\n", template.visualid);
1235 TRACE(" visual info: %p\n", object->visInfo);
1236 TRACE(" num items : %d\n", num);
1237 for (n = 0;n < num; n++) {
1238 TRACE("=====item=====: %d\n", n + 1);
1239 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1240 TRACE(" screen : %d\n", object->visInfo[n].screen);
1241 TRACE(" depth : %u\n", object->visInfo[n].depth);
1242 TRACE(" class : %d\n", object->visInfo[n].class);
1243 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1244 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1245 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1246 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1247 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1248 /* log some extra glx info */
1249 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1250 TRACE(" gl_aux_buffers : %d\n", value);
1251 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1252 TRACE(" gl_buffer_size : %d\n", value);
1253 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1254 TRACE(" gl_red_size : %d\n", value);
1255 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1256 TRACE(" gl_green_size : %d\n", value);
1257 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1258 TRACE(" gl_blue_size : %d\n", value);
1259 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1260 TRACE(" gl_alpha_size : %d\n", value);
1261 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1262 TRACE(" gl_depth_size : %d\n", value);
1263 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1264 TRACE(" gl_stencil_size : %d\n", value);
1266 /* Now choose a simila visual ID*/
1268 #ifdef USE_CONTEXT_MANAGER
1270 /** TODO: use a context mamager **/
1271 #endif
1274 IWineD3DSwapChain *implSwapChain;
1275 if (D3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1276 /* The first time around we create the context that is shared with all other swapchains and render targets */
1277 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1278 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1279 } else {
1281 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1282 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1283 /* and create a new context with the implicit swapchains context as the shared context */
1284 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1285 IWineD3DSwapChain_Release(implSwapChain);
1289 /* Cleanup */
1290 XFree(object->visInfo);
1291 object->visInfo = NULL;
1293 if (NULL == object->glCtx) {
1294 ERR("cannot create glxContext\n");
1295 LEAVE_GL();
1296 return D3DERR_NOTAVAILABLE;
1299 LEAVE_GL();
1300 if (object->glCtx == NULL) {
1301 ERR("Error in context creation !\n");
1302 return D3DERR_INVALIDCALL;
1303 } else {
1304 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1305 object->win_handle, object->glCtx, object->win, object->visInfo);
1308 /*********************
1309 * Windowed / Fullscreen
1310 *******************/
1313 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1314 * so we should really check to see if there is a fullscreen swapchain already
1315 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1316 **************************************/
1318 if (!*(pPresentationParameters->Windowed)) {
1320 DEVMODEW devmode;
1321 HDC hdc;
1322 int bpp = 0;
1324 /* Get info on the current display setup */
1325 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1326 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1327 DeleteDC(hdc);
1329 /* Change the display settings */
1330 memset(&devmode, 0, sizeof(DEVMODEW));
1331 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1332 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1333 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1334 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1335 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1336 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1338 /* Make popup window */
1339 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1340 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1341 *(pPresentationParameters->BackBufferWidth),
1342 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1348 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1349 * then the corresponding dimension of the client area of the hDeviceWindow
1350 * (or the focus window, if hDeviceWindow is NULL) is taken.
1351 **********************/
1353 if (*(pPresentationParameters->Windowed) &&
1354 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1355 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1357 RECT Rect;
1358 GetClientRect(object->win_handle, &Rect);
1360 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1361 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1362 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1364 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1365 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1366 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1370 /*********************
1371 * finish off parameter initialization
1372 *******************/
1374 /* Put the correct figures in the presentation parameters */
1375 TRACE("Coppying accross presentaion paraneters\n");
1376 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1377 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1378 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1379 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1380 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1381 object->presentParms.MultiSampleQuality = NULL == pPresentationParameters->MultiSampleQuality ? 0 : *(pPresentationParameters->MultiSampleQuality);
1382 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1383 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1384 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1385 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1386 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1387 object->presentParms.Flags = *(pPresentationParameters->Flags);
1388 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1389 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1392 /*********************
1393 * Create the back, front and stencil buffers
1394 *******************/
1395 TRACE("calling rendertarget CB\n");
1396 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1397 object->presentParms.BackBufferWidth,
1398 object->presentParms.BackBufferHeight,
1399 object->presentParms.BackBufferFormat,
1400 object->presentParms.MultiSampleType,
1401 object->presentParms.MultiSampleQuality,
1402 TRUE /* Lockable */,
1403 &object->frontBuffer,
1404 NULL /* pShared (always null)*/);
1405 if (object->frontBuffer != NULL)
1406 IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
1407 TRACE("calling rendertarget CB\n");
1408 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1409 object->presentParms.BackBufferWidth,
1410 object->presentParms.BackBufferHeight,
1411 object->presentParms.BackBufferFormat,
1412 object->presentParms.MultiSampleType,
1413 object->presentParms.MultiSampleQuality,
1414 TRUE /* Lockable */,
1415 &object->backBuffer,
1416 NULL /* pShared (always null)*/);
1417 if (object->backBuffer != NULL)
1418 IWineD3DSurface_SetContainer(object->backBuffer, (IWineD3DBase *)object);
1420 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1421 if (pPresentationParameters->EnableAutoDepthStencil) {
1422 TRACE("Creating depth stencil buffer\n");
1423 if (This->depthStencilBuffer == NULL ) {
1424 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1425 object->presentParms.BackBufferWidth,
1426 object->presentParms.BackBufferHeight,
1427 object->presentParms.AutoDepthStencilFormat,
1428 object->presentParms.MultiSampleType,
1429 object->presentParms.MultiSampleQuality,
1430 FALSE /* FIXME: Discard */,
1431 &This->depthStencilBuffer,
1432 NULL /* pShared (always null)*/ );
1433 if (This->depthStencilBuffer != NULL)
1434 IWineD3DSurface_SetContainer(This->depthStencilBuffer, (IWineD3DBase *)iface);
1437 /** TODO: A check on width, height and multisample types
1438 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1439 ****************************/
1440 object->wantsDepthStencilBuffer = TRUE;
1441 } else {
1442 object->wantsDepthStencilBuffer = FALSE;
1445 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1448 /*********************
1449 * init the default renderTarget management
1450 *******************/
1451 object->drawable = object->win;
1452 object->render_ctx = object->glCtx;
1454 if (hr == D3D_OK) {
1455 /*********************
1456 * Setup some defaults and clear down the buffers
1457 *******************/
1458 ENTER_GL();
1459 /** save current context and drawable **/
1460 oldContext = glXGetCurrentContext();
1461 oldDrawable = glXGetCurrentDrawable();
1463 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1464 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1465 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1467 checkGLcall("glXMakeCurrent");
1469 TRACE("Setting up the screen\n");
1470 /* Clear the screen */
1471 glClearColor(1.0, 0.0, 0.0, 0.0);
1472 checkGLcall("glClearColor");
1473 glClearIndex(0);
1474 glClearDepth(1);
1475 glClearStencil(0xffff);
1477 checkGLcall("glClear");
1479 glColor3f(1.0, 1.0, 1.0);
1480 checkGLcall("glColor3f");
1482 glEnable(GL_LIGHTING);
1483 checkGLcall("glEnable");
1485 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1486 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1488 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1489 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1491 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1492 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1494 /* switch back to the original context (if there was one)*/
1495 if (This->swapchains != NULL) {
1496 /** TODO: restore the context and drawable **/
1497 glXMakeCurrent(object->display, oldDrawable, oldContext);
1500 LEAVE_GL();
1502 { /* Finally add the swapchain to the end of the devices' swapchain list */
1503 SwapChainList **nextSwapchain;
1504 nextSwapchain = &This->swapchains;
1505 while (*nextSwapchain != NULL) {
1506 nextSwapchain = &((*nextSwapchain)->next);
1508 (*nextSwapchain) = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->swapchains));
1509 (*nextSwapchain)->swapchain = (IWineD3DSwapChain *)object;
1511 TRACE("Set swapchain to %p\n", object);
1512 } else { /* something went wrong so clean up */
1513 IUnknown* bufferParent;
1514 if (object->frontBuffer) {
1516 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1517 IUnknown_Release(bufferParent); /* once for the get parent */
1518 if (IUnknown_Release(bufferParent) > 0) {
1519 FIXME("(%p) Something's still holding the front buffer\n",This);
1522 if (object->backBuffer) {
1523 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1524 IUnknown_Release(bufferParent); /* once for the get parent */
1525 if (IUnknown_Release(bufferParent) > 0) {
1526 FIXME("(%p) Something's still holding the back buffer\n",This);
1529 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1530 /* Clean up the context */
1531 /* check that we are the current context first (we shouldn't be though!) */
1532 if (object->glCtx != 0) {
1533 if(glXGetCurrentContext() == object->glCtx) {
1534 glXMakeCurrent(object->display, None, NULL);
1536 glXDestroyContext(object->display, object->glCtx);
1538 HeapFree(GetProcessHeap(), 0, object);
1542 return hr;
1545 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1546 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1547 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1548 unsigned int numberOfSwapChains = 0;
1549 SwapChainList *swapchain;
1551 swapchain = This->swapchains;
1552 /* itterate through the list to get a count */
1553 while (swapchain != NULL) {
1554 swapchain = swapchain->next;
1555 numberOfSwapChains++;
1558 TRACE("(%p) returning %d\n", This, numberOfSwapChains);
1559 return numberOfSwapChains;
1562 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1563 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1564 SwapChainList *swapchain;
1565 int i = iSwapChain;
1566 HRESULT hr = D3DERR_INVALIDCALL;
1567 swapchain = This->swapchains;
1568 TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1571 TRACE("(%p) Finding swapchain %d\n", This, iSwapChain);
1572 while (i > 0 && swapchain != NULL) {
1573 swapchain = swapchain->next;
1574 --i;
1577 if (i > 0) {
1578 FIXME("(%p) Unable to find swapchain %d\n", This, iSwapChain);
1579 *pSwapChain = NULL;
1580 } else if (swapchain != NULL) {
1581 /** TODO: move off to a linkesList implementation **/
1582 *pSwapChain = swapchain->swapchain;
1583 IWineD3DSwapChain_AddRef(*pSwapChain);
1584 hr = D3D_OK;
1587 TRACE("(%p) returning %p\n", This, *pSwapChain);
1588 return hr;
1591 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
1592 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1594 FIXME("(%p) : Stub\n",This);
1595 return D3D_OK;
1599 /*****
1600 * Vertex Declaration
1601 *****/
1602 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1603 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1604 IWineD3DVertexDeclarationImpl *object = NULL;
1605 HRESULT hr = D3D_OK;
1606 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1607 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1608 object->allFVF = 0;
1610 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1612 return hr;
1615 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1616 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pDeclaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1617 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1618 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1619 HRESULT hr = D3D_OK;
1620 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1622 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1623 hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1625 if (D3D_OK != hr) {
1626 FIXME("(%p) : Failed to set the function, returning D3DERR_INVALIDCALL\n", iface);
1627 IWineD3DVertexShader_Release(*ppVertexShader);
1628 return D3DERR_INVALIDCALL;
1631 #if 0 /* TODO: In D3D* SVP is atatched to the shader, in D3D9 it's attached to the device and isn't stored in the stateblock. */
1632 if(Usage == WINED3DUSAGE_SOFTWAREVERTEXPROCESSING) {
1633 /* Foo */
1634 } else {
1635 /* Bar */
1638 #endif
1641 /* If a vertex declaration has been passed, save it to the vertex shader, this affects d3d8 only. */
1642 if (pDeclaration != NULL) {
1643 IWineD3DVertexDeclaration *vertexDeclaration;
1644 hr = IWineD3DDevice_CreateVertexDeclaration(iface, pDeclaration, &vertexDeclaration ,NULL);
1645 if (D3D_OK == hr) {
1646 TRACE("(%p) : Setting vertex declaration to %p\n", This, vertexDeclaration);
1647 object->vertexDeclaration = vertexDeclaration;
1648 } else {
1649 FIXME("(%p) : Failed to set the declaration, returning D3DERR_INVALIDCALL\n", iface);
1650 IWineD3DVertexShader_Release(*ppVertexShader);
1651 return D3DERR_INVALIDCALL;
1655 return D3D_OK;
1658 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
1659 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1660 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1661 HRESULT hr = D3D_OK;
1663 D3DCREATEOBJECTINSTANCE(object, PixelShader)
1664 hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
1665 if (D3D_OK == hr) {
1666 TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
1667 } else {
1668 WARN("(%p) : Failed to create pixel shader\n", This);
1671 return hr;
1674 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
1675 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1676 *ppD3D= This->wineD3D;
1677 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1678 IWineD3D_AddRef(*ppD3D);
1679 return D3D_OK;
1682 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1683 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1684 * Into the video ram as possible and seeing how many fit
1685 * you can also get the correct initial value from via X and ATI's driver
1686 *******************/
1687 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1688 static BOOL showfixmes = TRUE;
1689 if (showfixmes) {
1690 FIXME("(%p) : stub, emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1691 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1692 showfixmes = FALSE;
1694 TRACE("(%p) : emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1695 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1696 /* videomemory is simulated videomemory + AGP memory left */
1697 return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1702 /*****
1703 * Get / Set FVF
1704 *****/
1705 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1706 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1707 HRESULT hr = D3D_OK;
1709 /* Update the current state block */
1710 This->updateStateBlock->fvf = fvf;
1711 This->updateStateBlock->changed.fvf = TRUE;
1712 This->updateStateBlock->set.fvf = TRUE;
1714 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1716 if (0 != fvf) {
1717 /* clear down the vertex declaration
1718 NOTE: Axis and Allies doesn't work properly otherwise
1719 (may be a stateblock problem though!)
1721 hr = IWineD3DDevice_SetVertexDeclaration(iface, NULL);
1724 return hr;
1728 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1729 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1730 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1731 *pfvf = This->stateBlock->fvf;
1732 return D3D_OK;
1735 /*****
1736 * Get / Set Stream Source
1737 *****/
1738 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1739 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1740 IWineD3DVertexBuffer *oldSrc;
1742 /**TODO: instance and index data, see
1743 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1745 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
1746 **************/
1748 /* D3d9 only, but shouldn't hurt d3d8 */
1749 UINT streamFlags;
1751 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1752 if (streamFlags) {
1753 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1754 FIXME("stream index data not supported\n");
1756 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1757 FIXME("stream instance data not supported\n");
1761 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1763 if (StreamNumber >= MAX_STREAMS) {
1764 WARN("Stream out of range %d\n", StreamNumber);
1765 return D3DERR_INVALIDCALL;
1768 oldSrc = This->stateBlock->streamSource[StreamNumber];
1769 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1771 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
1772 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
1773 This->updateStateBlock->streamStride[StreamNumber] = Stride;
1774 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
1775 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
1776 This->updateStateBlock->streamFlags[StreamNumber] = streamFlags;
1778 /* Handle recording of state blocks */
1779 if (This->isRecordingState) {
1780 TRACE("Recording... not performing anything\n");
1781 return D3D_OK;
1784 /* Not recording... */
1785 /* Need to do a getParent and pass the reffs up */
1786 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
1787 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
1788 so for now, just count internally */
1789 if (pStreamData != NULL) {
1790 IWineD3DVertexBuffer_AddRef(pStreamData);
1792 if (oldSrc != NULL) {
1793 IWineD3DVertexBuffer_Release(oldSrc);
1796 return D3D_OK;
1799 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
1800 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1801 UINT streamFlags;
1803 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
1804 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
1807 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1808 if (streamFlags) {
1809 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1810 FIXME("stream index data not supported\n");
1812 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1813 FIXME("stream instance data not supported\n");
1817 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1819 if (StreamNumber >= MAX_STREAMS) {
1820 WARN("Stream out of range %d\n", StreamNumber);
1821 return D3DERR_INVALIDCALL;
1823 *pStream = This->stateBlock->streamSource[StreamNumber];
1824 *pStride = This->stateBlock->streamStride[StreamNumber];
1825 *pOffset = This->stateBlock->streamOffset[StreamNumber];
1827 if (*pStream == NULL) {
1828 FIXME("Attempting to get an empty stream %d, returning D3DERR_INVALIDCALL\n", StreamNumber);
1829 return D3DERR_INVALIDCALL;
1832 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
1833 return D3D_OK;
1836 /*Should be quite easy, just an extension of vertexdata
1837 ref...
1838 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1840 The divider is a bit odd though
1842 VertexOffset = StartVertex / Divider * StreamStride +
1843 VertexIndex / Divider * StreamStride + StreamOffset
1846 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
1847 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1849 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
1850 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (D3DSTREAMSOURCE_INSTANCEDATA | D3DSTREAMSOURCE_INDEXEDDATA );
1852 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
1853 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
1854 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
1856 if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
1857 FIXME("Stream indexing not fully supported\n");
1860 return D3D_OK;
1863 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
1864 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1866 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
1867 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
1869 TRACE("(%p) : returning %d\n", This, *Divider);
1871 return D3D_OK;
1874 /*****
1875 * Get / Set & Multiply Transform
1876 *****/
1877 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1878 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1880 /* Most of this routine, comments included copied from ddraw tree initially: */
1881 TRACE("(%p) : Transform State=%d\n", This, d3dts);
1883 /* Handle recording of state blocks */
1884 if (This->isRecordingState) {
1885 TRACE("Recording... not performing anything\n");
1886 This->updateStateBlock->changed.transform[d3dts] = TRUE;
1887 This->updateStateBlock->set.transform[d3dts] = TRUE;
1888 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1889 return D3D_OK;
1893 * If the new matrix is the same as the current one,
1894 * we cut off any further processing. this seems to be a reasonable
1895 * optimization because as was noticed, some apps (warcraft3 for example)
1896 * tend towards setting the same matrix repeatedly for some reason.
1898 * From here on we assume that the new matrix is different, wherever it matters.
1900 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1901 TRACE("The app is setting the same matrix over again\n");
1902 return D3D_OK;
1903 } else {
1904 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1908 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1909 where ViewMat = Camera space, WorldMat = world space.
1911 In OpenGL, camera and world space is combined into GL_MODELVIEW
1912 matrix. The Projection matrix stay projection matrix.
1915 /* Capture the times we can just ignore the change for now */
1916 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1917 This->modelview_valid = FALSE;
1918 return D3D_OK;
1920 } else if (d3dts == D3DTS_PROJECTION) {
1921 This->proj_valid = FALSE;
1922 return D3D_OK;
1924 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1925 /* Indexed Vertex Blending Matrices 256 -> 511 */
1926 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1927 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1928 return D3D_OK;
1931 /* Now we really are going to have to change a matrix */
1932 ENTER_GL();
1934 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1935 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
1936 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1937 unsigned int k;
1939 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1940 * NOTE: We have to reset the positions even if the light/plane is not currently
1941 * enabled, since the call to enable it will not reset the position.
1942 * NOTE2: Apparently texture transforms do NOT need reapplying
1945 PLIGHTINFOEL *lightChain = NULL;
1946 This->modelview_valid = FALSE;
1947 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
1949 glMatrixMode(GL_MODELVIEW);
1950 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1951 glPushMatrix();
1952 glLoadMatrixf((float *)lpmatrix);
1953 checkGLcall("glLoadMatrixf(...)");
1955 /* Reset lights */
1956 lightChain = This->stateBlock->lights;
1957 while (lightChain && lightChain->glIndex != -1) {
1958 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1959 checkGLcall("glLightfv posn");
1960 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1961 checkGLcall("glLightfv dirn");
1962 lightChain = lightChain->next;
1965 /* Reset Clipping Planes if clipping is enabled */
1966 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1967 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1968 checkGLcall("glClipPlane");
1970 glPopMatrix();
1972 } else { /* What was requested!?? */
1973 WARN("invalid matrix specified: %i\n", d3dts);
1976 /* Release lock, all done */
1977 LEAVE_GL();
1978 return D3D_OK;
1981 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1982 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1983 TRACE("(%p) : for Transform State %d\n", This, State);
1984 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1985 return D3D_OK;
1988 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1989 D3DMATRIX *mat = NULL;
1990 D3DMATRIX temp;
1992 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1993 * below means it will be recorded in a state block change, but it
1994 * works regardless where it is recorded.
1995 * If this is found to be wrong, change to StateBlock.
1997 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1998 TRACE("(%p) : For state %u\n", This, State);
2000 if (State < HIGHEST_TRANSFORMSTATE)
2002 mat = &This->updateStateBlock->transforms[State];
2003 } else {
2004 FIXME("Unhandled transform state!!\n");
2007 /* Copied from ddraw code: */
2008 temp.u.s._11 = (mat->u.s._11 * pMatrix->u.s._11) + (mat->u.s._21 * pMatrix->u.s._12) +
2009 (mat->u.s._31 * pMatrix->u.s._13) + (mat->u.s._41 * pMatrix->u.s._14);
2010 temp.u.s._21 = (mat->u.s._11 * pMatrix->u.s._21) + (mat->u.s._21 * pMatrix->u.s._22) +
2011 (mat->u.s._31 * pMatrix->u.s._23) + (mat->u.s._41 * pMatrix->u.s._24);
2012 temp.u.s._31 = (mat->u.s._11 * pMatrix->u.s._31) + (mat->u.s._21 * pMatrix->u.s._32) +
2013 (mat->u.s._31 * pMatrix->u.s._33) + (mat->u.s._41 * pMatrix->u.s._34);
2014 temp.u.s._41 = (mat->u.s._11 * pMatrix->u.s._41) + (mat->u.s._21 * pMatrix->u.s._42) +
2015 (mat->u.s._31 * pMatrix->u.s._43) + (mat->u.s._41 * pMatrix->u.s._44);
2017 temp.u.s._12 = (mat->u.s._12 * pMatrix->u.s._11) + (mat->u.s._22 * pMatrix->u.s._12) +
2018 (mat->u.s._32 * pMatrix->u.s._13) + (mat->u.s._42 * pMatrix->u.s._14);
2019 temp.u.s._22 = (mat->u.s._12 * pMatrix->u.s._21) + (mat->u.s._22 * pMatrix->u.s._22) +
2020 (mat->u.s._32 * pMatrix->u.s._23) + (mat->u.s._42 * pMatrix->u.s._24);
2021 temp.u.s._32 = (mat->u.s._12 * pMatrix->u.s._31) + (mat->u.s._22 * pMatrix->u.s._32) +
2022 (mat->u.s._32 * pMatrix->u.s._33) + (mat->u.s._42 * pMatrix->u.s._34);
2023 temp.u.s._42 = (mat->u.s._12 * pMatrix->u.s._41) + (mat->u.s._22 * pMatrix->u.s._42) +
2024 (mat->u.s._32 * pMatrix->u.s._43) + (mat->u.s._42 * pMatrix->u.s._44);
2026 temp.u.s._13 = (mat->u.s._13 * pMatrix->u.s._11) + (mat->u.s._23 * pMatrix->u.s._12) +
2027 (mat->u.s._33 * pMatrix->u.s._13) + (mat->u.s._43 * pMatrix->u.s._14);
2028 temp.u.s._23 = (mat->u.s._13 * pMatrix->u.s._21) + (mat->u.s._23 * pMatrix->u.s._22) +
2029 (mat->u.s._33 * pMatrix->u.s._23) + (mat->u.s._43 * pMatrix->u.s._24);
2030 temp.u.s._33 = (mat->u.s._13 * pMatrix->u.s._31) + (mat->u.s._23 * pMatrix->u.s._32) +
2031 (mat->u.s._33 * pMatrix->u.s._33) + (mat->u.s._43 * pMatrix->u.s._34);
2032 temp.u.s._43 = (mat->u.s._13 * pMatrix->u.s._41) + (mat->u.s._23 * pMatrix->u.s._42) +
2033 (mat->u.s._33 * pMatrix->u.s._43) + (mat->u.s._43 * pMatrix->u.s._44);
2035 temp.u.s._14 = (mat->u.s._14 * pMatrix->u.s._11) + (mat->u.s._24 * pMatrix->u.s._12) +
2036 (mat->u.s._34 * pMatrix->u.s._13) + (mat->u.s._44 * pMatrix->u.s._14);
2037 temp.u.s._24 = (mat->u.s._14 * pMatrix->u.s._21) + (mat->u.s._24 * pMatrix->u.s._22) +
2038 (mat->u.s._34 * pMatrix->u.s._23) + (mat->u.s._44 * pMatrix->u.s._24);
2039 temp.u.s._34 = (mat->u.s._14 * pMatrix->u.s._31) + (mat->u.s._24 * pMatrix->u.s._32) +
2040 (mat->u.s._34 * pMatrix->u.s._33) + (mat->u.s._44 * pMatrix->u.s._34);
2041 temp.u.s._44 = (mat->u.s._14 * pMatrix->u.s._41) + (mat->u.s._24 * pMatrix->u.s._42) +
2042 (mat->u.s._34 * pMatrix->u.s._43) + (mat->u.s._44 * pMatrix->u.s._44);
2044 /* Apply change via set transform - will reapply to eg. lights this way */
2045 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2048 /*****
2049 * Get / Set Light
2050 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
2051 *****/
2052 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2053 you can reference any indexes you want as long as that number max are enabled at any
2054 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2055 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2056 but when recording, just build a chain pretty much of commands to be replayed. */
2058 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2059 float rho;
2060 PLIGHTINFOEL *object, *temp;
2062 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2063 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2065 /* If recording state block, just add to end of lights chain */
2066 if (This->isRecordingState) {
2067 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2068 if (NULL == object) {
2069 return D3DERR_OUTOFVIDEOMEMORY;
2071 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2072 object->OriginalIndex = Index;
2073 object->glIndex = -1;
2074 object->changed = TRUE;
2076 /* Add to the END of the chain of lights changes to be replayed */
2077 if (This->updateStateBlock->lights == NULL) {
2078 This->updateStateBlock->lights = object;
2079 } else {
2080 temp = This->updateStateBlock->lights;
2081 while (temp->next != NULL) temp=temp->next;
2082 temp->next = object;
2084 TRACE("Recording... not performing anything more\n");
2085 return D3D_OK;
2088 /* Ok, not recording any longer so do real work */
2089 object = This->stateBlock->lights;
2090 while (object != NULL && object->OriginalIndex != Index) object = object->next;
2092 /* If we didn't find it in the list of lights, time to add it */
2093 if (object == NULL) {
2094 PLIGHTINFOEL *insertAt,*prevPos;
2096 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2097 if (NULL == object) {
2098 return D3DERR_OUTOFVIDEOMEMORY;
2100 object->OriginalIndex = Index;
2101 object->glIndex = -1;
2103 /* Add it to the front of list with the idea that lights will be changed as needed
2104 BUT after any lights currently assigned GL indexes */
2105 insertAt = This->stateBlock->lights;
2106 prevPos = NULL;
2107 while (insertAt != NULL && insertAt->glIndex != -1) {
2108 prevPos = insertAt;
2109 insertAt = insertAt->next;
2112 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2113 This->stateBlock->lights = object;
2114 } else if (insertAt == NULL) { /* End of list */
2115 prevPos->next = object;
2116 object->prev = prevPos;
2117 } else { /* Middle of chain */
2118 if (prevPos == NULL) {
2119 This->stateBlock->lights = object;
2120 } else {
2121 prevPos->next = object;
2123 object->prev = prevPos;
2124 object->next = insertAt;
2125 insertAt->prev = object;
2129 /* Initialize the object */
2130 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,
2131 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2132 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2133 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2134 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2135 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2136 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2138 /* Save away the information */
2139 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2141 switch (pLight->Type) {
2142 case D3DLIGHT_POINT:
2143 /* Position */
2144 object->lightPosn[0] = pLight->Position.x;
2145 object->lightPosn[1] = pLight->Position.y;
2146 object->lightPosn[2] = pLight->Position.z;
2147 object->lightPosn[3] = 1.0f;
2148 object->cutoff = 180.0f;
2149 /* FIXME: Range */
2150 break;
2152 case D3DLIGHT_DIRECTIONAL:
2153 /* Direction */
2154 object->lightPosn[0] = -pLight->Direction.x;
2155 object->lightPosn[1] = -pLight->Direction.y;
2156 object->lightPosn[2] = -pLight->Direction.z;
2157 object->lightPosn[3] = 0.0;
2158 object->exponent = 0.0f;
2159 object->cutoff = 180.0f;
2160 break;
2162 case D3DLIGHT_SPOT:
2163 /* Position */
2164 object->lightPosn[0] = pLight->Position.x;
2165 object->lightPosn[1] = pLight->Position.y;
2166 object->lightPosn[2] = pLight->Position.z;
2167 object->lightPosn[3] = 1.0;
2169 /* Direction */
2170 object->lightDirn[0] = pLight->Direction.x;
2171 object->lightDirn[1] = pLight->Direction.y;
2172 object->lightDirn[2] = pLight->Direction.z;
2173 object->lightDirn[3] = 1.0;
2176 * opengl-ish and d3d-ish spot lights use too different models for the
2177 * light "intensity" as a function of the angle towards the main light direction,
2178 * so we only can approximate very roughly.
2179 * however spot lights are rather rarely used in games (if ever used at all).
2180 * furthermore if still used, probably nobody pays attention to such details.
2182 if (pLight->Falloff == 0) {
2183 rho = 6.28f;
2184 } else {
2185 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2187 if (rho < 0.0001) rho = 0.0001f;
2188 object->exponent = -0.3/log(cos(rho/2));
2189 object->cutoff = pLight->Phi*90/M_PI;
2191 /* FIXME: Range */
2192 break;
2194 default:
2195 FIXME("Unrecognized light type %d\n", pLight->Type);
2198 /* Update the live definitions if the light is currently assigned a glIndex */
2199 if (object->glIndex != -1) {
2200 setup_light(iface, object->glIndex, object);
2202 return D3D_OK;
2205 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2206 PLIGHTINFOEL *lightInfo = NULL;
2207 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2208 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2210 /* Locate the light in the live lights */
2211 lightInfo = This->stateBlock->lights;
2212 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2214 if (lightInfo == NULL) {
2215 TRACE("Light information requested but light not defined\n");
2216 return D3DERR_INVALIDCALL;
2219 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
2220 return D3D_OK;
2223 /*****
2224 * Get / Set Light Enable
2225 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2226 *****/
2227 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2228 PLIGHTINFOEL *lightInfo = NULL;
2229 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2230 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2232 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2233 if (This->isRecordingState) {
2234 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2235 if (NULL == lightInfo) {
2236 return D3DERR_OUTOFVIDEOMEMORY;
2238 lightInfo->OriginalIndex = Index;
2239 lightInfo->glIndex = -1;
2240 lightInfo->enabledChanged = TRUE;
2242 /* Add to the END of the chain of lights changes to be replayed */
2243 if (This->updateStateBlock->lights == NULL) {
2244 This->updateStateBlock->lights = lightInfo;
2245 } else {
2246 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2247 while (temp->next != NULL) temp=temp->next;
2248 temp->next = lightInfo;
2250 TRACE("Recording... not performing anything more\n");
2251 return D3D_OK;
2254 /* Not recording... So, locate the light in the live lights */
2255 lightInfo = This->stateBlock->lights;
2256 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2258 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2259 if (lightInfo == NULL) {
2260 D3DLIGHT9 lightParms;
2261 /* Warning - untested code :-) Prob safe to change fixme to a trace but
2262 wait until someone confirms it seems to work! */
2263 TRACE("Light enabled requested but light not defined, so defining one!\n");
2264 lightParms.Type = D3DLIGHT_DIRECTIONAL;
2265 lightParms.Diffuse.r = 1.0;
2266 lightParms.Diffuse.g = 1.0;
2267 lightParms.Diffuse.b = 1.0;
2268 lightParms.Diffuse.a = 0.0;
2269 lightParms.Specular.r = 0.0;
2270 lightParms.Specular.g = 0.0;
2271 lightParms.Specular.b = 0.0;
2272 lightParms.Specular.a = 0.0;
2273 lightParms.Ambient.r = 0.0;
2274 lightParms.Ambient.g = 0.0;
2275 lightParms.Ambient.b = 0.0;
2276 lightParms.Ambient.a = 0.0;
2277 lightParms.Position.x = 0.0;
2278 lightParms.Position.y = 0.0;
2279 lightParms.Position.z = 0.0;
2280 lightParms.Direction.x = 0.0;
2281 lightParms.Direction.y = 0.0;
2282 lightParms.Direction.z = 1.0;
2283 lightParms.Range = 0.0;
2284 lightParms.Falloff = 0.0;
2285 lightParms.Attenuation0 = 0.0;
2286 lightParms.Attenuation1 = 0.0;
2287 lightParms.Attenuation2 = 0.0;
2288 lightParms.Theta = 0.0;
2289 lightParms.Phi = 0.0;
2290 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
2292 /* Search for it again! Should be fairly quick as near head of list */
2293 lightInfo = This->stateBlock->lights;
2294 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2295 if (lightInfo == NULL) {
2296 FIXME("Adding default lights has failed dismally\n");
2297 return D3DERR_INVALIDCALL;
2301 /* OK, we now have a light... */
2302 if (Enable == FALSE) {
2304 /* If we are disabling it, check it was enabled, and
2305 still only do something if it has assigned a glIndex (which it should have!) */
2306 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2307 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2308 ENTER_GL();
2309 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2310 checkGLcall("glDisable GL_LIGHT0+Index");
2311 LEAVE_GL();
2312 } else {
2313 TRACE("Nothing to do as light was not enabled\n");
2315 lightInfo->lightEnabled = FALSE;
2316 } else {
2318 /* We are enabling it. If it is enabled, it's really simple */
2319 if (lightInfo->lightEnabled) {
2320 /* nop */
2321 TRACE("Nothing to do as light was enabled\n");
2323 /* If it already has a glIndex, it's still simple */
2324 } else if (lightInfo->glIndex != -1) {
2325 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2326 lightInfo->lightEnabled = TRUE;
2327 ENTER_GL();
2328 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2329 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2330 LEAVE_GL();
2332 /* Otherwise got to find space - lights are ordered gl indexes first */
2333 } else {
2334 PLIGHTINFOEL *bsf = NULL;
2335 PLIGHTINFOEL *pos = This->stateBlock->lights;
2336 PLIGHTINFOEL *prev = NULL;
2337 int Index= 0;
2338 int glIndex = -1;
2340 /* Try to minimize changes as much as possible */
2341 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2343 /* Try to remember which index can be replaced if necessary */
2344 if (bsf==NULL && pos->lightEnabled == FALSE) {
2345 /* Found a light we can replace, save as best replacement */
2346 bsf = pos;
2349 /* Step to next space */
2350 prev = pos;
2351 pos = pos->next;
2352 Index ++;
2355 /* If we have too many active lights, fail the call */
2356 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2357 FIXME("Program requests too many concurrent lights\n");
2358 return D3DERR_INVALIDCALL;
2360 /* If we have allocated all lights, but not all are enabled,
2361 reuse one which is not enabled */
2362 } else if (Index == This->maxConcurrentLights) {
2363 /* use bsf - Simply swap the new light and the BSF one */
2364 PLIGHTINFOEL *bsfNext = bsf->next;
2365 PLIGHTINFOEL *bsfPrev = bsf->prev;
2367 /* Sort out ends */
2368 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2369 if (bsf->prev != NULL) {
2370 bsf->prev->next = lightInfo;
2371 } else {
2372 This->stateBlock->lights = lightInfo;
2375 /* If not side by side, lots of chains to update */
2376 if (bsf->next != lightInfo) {
2377 lightInfo->prev->next = bsf;
2378 bsf->next->prev = lightInfo;
2379 bsf->next = lightInfo->next;
2380 bsf->prev = lightInfo->prev;
2381 lightInfo->next = bsfNext;
2382 lightInfo->prev = bsfPrev;
2384 } else {
2385 /* Simple swaps */
2386 bsf->prev = lightInfo;
2387 bsf->next = lightInfo->next;
2388 lightInfo->next = bsf;
2389 lightInfo->prev = bsfPrev;
2393 /* Update states */
2394 glIndex = bsf->glIndex;
2395 bsf->glIndex = -1;
2396 lightInfo->glIndex = glIndex;
2397 lightInfo->lightEnabled = TRUE;
2399 /* Finally set up the light in gl itself */
2400 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2401 ENTER_GL();
2402 setup_light(iface, glIndex, lightInfo);
2403 glEnable(GL_LIGHT0 + glIndex);
2404 checkGLcall("glEnable GL_LIGHT0 new setup");
2405 LEAVE_GL();
2407 /* If we reached the end of the allocated lights, with space in the
2408 gl lights, setup a new light */
2409 } else if (pos->glIndex == -1) {
2411 /* We reached the end of the allocated gl lights, so already
2412 know the index of the next one! */
2413 glIndex = Index;
2414 lightInfo->glIndex = glIndex;
2415 lightInfo->lightEnabled = TRUE;
2417 /* In an ideal world, it's already in the right place */
2418 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2419 /* No need to move it */
2420 } else {
2421 /* Remove this light from the list */
2422 lightInfo->prev->next = lightInfo->next;
2423 if (lightInfo->next != NULL) {
2424 lightInfo->next->prev = lightInfo->prev;
2427 /* Add in at appropriate place (inbetween prev and pos) */
2428 lightInfo->prev = prev;
2429 lightInfo->next = pos;
2430 if (prev == NULL) {
2431 This->stateBlock->lights = lightInfo;
2432 } else {
2433 prev->next = lightInfo;
2435 if (pos != NULL) {
2436 pos->prev = lightInfo;
2440 /* Finally set up the light in gl itself */
2441 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2442 ENTER_GL();
2443 setup_light(iface, glIndex, lightInfo);
2444 glEnable(GL_LIGHT0 + glIndex);
2445 checkGLcall("glEnable GL_LIGHT0 new setup");
2446 LEAVE_GL();
2451 return D3D_OK;
2454 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2456 PLIGHTINFOEL *lightInfo = NULL;
2457 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2458 TRACE("(%p) : for idx(%ld)\n", This, Index);
2460 /* Locate the light in the live lights */
2461 lightInfo = This->stateBlock->lights;
2462 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2464 if (lightInfo == NULL) {
2465 TRACE("Light enabled state requested but light not defined\n");
2466 return D3DERR_INVALIDCALL;
2468 *pEnable = lightInfo->lightEnabled;
2469 return D3D_OK;
2472 /*****
2473 * Get / Set Clip Planes
2474 *****/
2475 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2476 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2477 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2479 /* Validate Index */
2480 if (Index >= GL_LIMITS(clipplanes)) {
2481 TRACE("Application has requested clipplane this device doesn't support\n");
2482 return D3DERR_INVALIDCALL;
2485 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2486 This->updateStateBlock->set.clipplane[Index] = TRUE;
2487 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2488 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2489 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2490 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2492 /* Handle recording of state blocks */
2493 if (This->isRecordingState) {
2494 TRACE("Recording... not performing anything\n");
2495 return D3D_OK;
2498 /* Apply it */
2500 ENTER_GL();
2502 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2503 glMatrixMode(GL_MODELVIEW);
2504 glPushMatrix();
2505 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2507 TRACE("Clipplane [%f,%f,%f,%f]\n",
2508 This->updateStateBlock->clipplane[Index][0],
2509 This->updateStateBlock->clipplane[Index][1],
2510 This->updateStateBlock->clipplane[Index][2],
2511 This->updateStateBlock->clipplane[Index][3]);
2512 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2513 checkGLcall("glClipPlane");
2515 glPopMatrix();
2516 LEAVE_GL();
2518 return D3D_OK;
2521 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2522 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2523 TRACE("(%p) : for idx %ld\n", This, Index);
2525 /* Validate Index */
2526 if (Index >= GL_LIMITS(clipplanes)) {
2527 TRACE("Application has requested clipplane this device doesn't support\n");
2528 return D3DERR_INVALIDCALL;
2531 pPlane[0] = This->stateBlock->clipplane[Index][0];
2532 pPlane[1] = This->stateBlock->clipplane[Index][1];
2533 pPlane[2] = This->stateBlock->clipplane[Index][2];
2534 pPlane[3] = This->stateBlock->clipplane[Index][3];
2535 return D3D_OK;
2538 /*****
2539 * Get / Set Clip Plane Status
2540 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2541 *****/
2542 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2543 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2544 FIXME("(%p) : stub\n", This);
2545 if (NULL == pClipStatus) {
2546 return D3DERR_INVALIDCALL;
2548 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2549 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2550 return D3D_OK;
2553 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2554 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2555 FIXME("(%p) : stub\n", This);
2556 if (NULL == pClipStatus) {
2557 return D3DERR_INVALIDCALL;
2559 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2560 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2561 return D3D_OK;
2564 /*****
2565 * Get / Set Material
2566 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2567 *****/
2568 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2569 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2571 This->updateStateBlock->changed.material = TRUE;
2572 This->updateStateBlock->set.material = TRUE;
2573 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2575 /* Handle recording of state blocks */
2576 if (This->isRecordingState) {
2577 TRACE("Recording... not performing anything\n");
2578 return D3D_OK;
2581 ENTER_GL();
2582 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2583 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2584 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2585 pMaterial->Ambient.b, pMaterial->Ambient.a);
2586 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2587 pMaterial->Specular.b, pMaterial->Specular.a);
2588 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2589 pMaterial->Emissive.b, pMaterial->Emissive.a);
2590 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2592 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2593 checkGLcall("glMaterialfv(GL_AMBIENT)");
2594 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2595 checkGLcall("glMaterialfv(GL_DIFFUSE)");
2597 /* Only change material color if specular is enabled, otherwise it is set to black */
2598 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2599 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2600 checkGLcall("glMaterialfv(GL_SPECULAR");
2601 } else {
2602 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2603 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2604 checkGLcall("glMaterialfv(GL_SPECULAR");
2606 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2607 checkGLcall("glMaterialfv(GL_EMISSION)");
2608 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2609 checkGLcall("glMaterialf(GL_SHININESS");
2611 LEAVE_GL();
2612 return D3D_OK;
2615 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2616 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2617 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2618 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2619 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2620 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2621 pMaterial->Ambient.b, pMaterial->Ambient.a);
2622 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2623 pMaterial->Specular.b, pMaterial->Specular.a);
2624 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2625 pMaterial->Emissive.b, pMaterial->Emissive.a);
2626 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2628 return D3D_OK;
2631 /*****
2632 * Get / Set Indices
2633 *****/
2634 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2635 UINT BaseVertexIndex) {
2636 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2637 IWineD3DIndexBuffer *oldIdxs;
2639 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2640 oldIdxs = This->updateStateBlock->pIndexData;
2642 This->updateStateBlock->changed.indices = TRUE;
2643 This->updateStateBlock->set.indices = TRUE;
2644 This->updateStateBlock->pIndexData = pIndexData;
2645 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2647 /* Handle recording of state blocks */
2648 if (This->isRecordingState) {
2649 TRACE("Recording... not performing anything\n");
2650 return D3D_OK;
2653 if (NULL != pIndexData) {
2654 IWineD3DIndexBuffer_AddRef(pIndexData);
2656 if (NULL != oldIdxs) {
2657 IWineD3DIndexBuffer_Release(oldIdxs);
2659 return D3D_OK;
2662 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2663 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2665 *ppIndexData = This->stateBlock->pIndexData;
2667 /* up ref count on ppindexdata */
2668 if (*ppIndexData) {
2669 IWineD3DIndexBuffer_AddRef(*ppIndexData);
2670 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2671 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
2672 }else{
2673 TRACE("(%p) No index data set\n", This);
2675 TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
2677 return D3D_OK;
2680 /*****
2681 * Get / Set Viewports
2682 *****/
2683 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2684 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2686 TRACE("(%p)\n", This);
2687 This->updateStateBlock->changed.viewport = TRUE;
2688 This->updateStateBlock->set.viewport = TRUE;
2689 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2691 /* Handle recording of state blocks */
2692 if (This->isRecordingState) {
2693 TRACE("Recording... not performing anything\n");
2694 return D3D_OK;
2697 ENTER_GL();
2699 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2700 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2702 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2703 checkGLcall("glDepthRange");
2704 /* Note: GL requires lower left, DirectX supplies upper left */
2705 /* TODO: replace usage of renderTarget with context management */
2706 glViewport(pViewport->X,
2707 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2708 pViewport->Width, pViewport->Height);
2710 checkGLcall("glViewport");
2712 LEAVE_GL();
2714 return D3D_OK;
2718 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2719 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2720 TRACE("(%p)\n", This);
2721 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2722 return D3D_OK;
2725 /*****
2726 * Get / Set Render States
2727 * TODO: Verify against dx9 definitions
2728 *****/
2729 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2731 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2732 DWORD OldValue = This->stateBlock->renderState[State];
2734 /* Simple way of referring to either a DWORD or a 4 byte float */
2735 union {
2736 DWORD d;
2737 float f;
2738 } tmpvalue;
2740 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2741 This->updateStateBlock->changed.renderState[State] = TRUE;
2742 This->updateStateBlock->set.renderState[State] = TRUE;
2743 This->updateStateBlock->renderState[State] = Value;
2745 /* Handle recording of state blocks */
2746 if (This->isRecordingState) {
2747 TRACE("Recording... not performing anything\n");
2748 return D3D_OK;
2751 ENTER_GL();
2753 switch (State) {
2754 case WINED3DRS_FILLMODE :
2755 switch ((D3DFILLMODE) Value) {
2756 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2757 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2758 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2759 default:
2760 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
2762 checkGLcall("glPolygonMode (fillmode)");
2763 break;
2765 case WINED3DRS_LIGHTING :
2766 if (Value) {
2767 glEnable(GL_LIGHTING);
2768 checkGLcall("glEnable GL_LIGHTING");
2769 } else {
2770 glDisable(GL_LIGHTING);
2771 checkGLcall("glDisable GL_LIGHTING");
2773 break;
2775 case WINED3DRS_ZENABLE :
2776 switch ((D3DZBUFFERTYPE) Value) {
2777 case D3DZB_FALSE:
2778 glDisable(GL_DEPTH_TEST);
2779 checkGLcall("glDisable GL_DEPTH_TEST");
2780 break;
2781 case D3DZB_TRUE:
2782 glEnable(GL_DEPTH_TEST);
2783 checkGLcall("glEnable GL_DEPTH_TEST");
2784 break;
2785 case D3DZB_USEW:
2786 glEnable(GL_DEPTH_TEST);
2787 checkGLcall("glEnable GL_DEPTH_TEST");
2788 FIXME("W buffer is not well handled\n");
2789 break;
2790 default:
2791 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2793 break;
2795 case WINED3DRS_CULLMODE :
2797 /* If we are culling "back faces with clockwise vertices" then
2798 set front faces to be counter clockwise and enable culling
2799 of back faces */
2800 switch ((D3DCULL) Value) {
2801 case D3DCULL_NONE:
2802 glDisable(GL_CULL_FACE);
2803 checkGLcall("glDisable GL_CULL_FACE");
2804 break;
2805 case D3DCULL_CW:
2806 glEnable(GL_CULL_FACE);
2807 checkGLcall("glEnable GL_CULL_FACE");
2808 if (This->renderUpsideDown) {
2809 glFrontFace(GL_CW);
2810 checkGLcall("glFrontFace GL_CW");
2811 } else {
2812 glFrontFace(GL_CCW);
2813 checkGLcall("glFrontFace GL_CCW");
2815 glCullFace(GL_BACK);
2816 break;
2817 case D3DCULL_CCW:
2818 glEnable(GL_CULL_FACE);
2819 checkGLcall("glEnable GL_CULL_FACE");
2820 if (This->renderUpsideDown) {
2821 glFrontFace(GL_CCW);
2822 checkGLcall("glFrontFace GL_CCW");
2823 } else {
2824 glFrontFace(GL_CW);
2825 checkGLcall("glFrontFace GL_CW");
2827 glCullFace(GL_BACK);
2828 break;
2829 default:
2830 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2832 break;
2834 case WINED3DRS_SHADEMODE :
2835 switch ((D3DSHADEMODE) Value) {
2836 case D3DSHADE_FLAT:
2837 glShadeModel(GL_FLAT);
2838 checkGLcall("glShadeModel");
2839 break;
2840 case D3DSHADE_GOURAUD:
2841 glShadeModel(GL_SMOOTH);
2842 checkGLcall("glShadeModel");
2843 break;
2844 case D3DSHADE_PHONG:
2845 FIXME("D3DSHADE_PHONG isn't supported?\n");
2847 LEAVE_GL();
2848 return D3DERR_INVALIDCALL;
2849 default:
2850 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2852 break;
2854 case WINED3DRS_DITHERENABLE :
2855 if (Value) {
2856 glEnable(GL_DITHER);
2857 checkGLcall("glEnable GL_DITHER");
2858 } else {
2859 glDisable(GL_DITHER);
2860 checkGLcall("glDisable GL_DITHER");
2862 break;
2864 case WINED3DRS_ZWRITEENABLE :
2865 if (Value) {
2866 glDepthMask(1);
2867 checkGLcall("glDepthMask");
2868 } else {
2869 glDepthMask(0);
2870 checkGLcall("glDepthMask");
2872 break;
2874 case WINED3DRS_ZFUNC :
2876 int glParm = GL_LESS;
2878 switch ((D3DCMPFUNC) Value) {
2879 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2880 case D3DCMP_LESS: glParm=GL_LESS; break;
2881 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2882 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2883 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2884 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2885 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2886 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2887 default:
2888 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2890 glDepthFunc(glParm);
2891 checkGLcall("glDepthFunc");
2893 break;
2895 case WINED3DRS_AMBIENT :
2897 float col[4];
2898 D3DCOLORTOGLFLOAT4(Value, col);
2899 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2900 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2901 checkGLcall("glLightModel for MODEL_AMBIENT");
2904 break;
2906 case WINED3DRS_ALPHABLENDENABLE :
2907 if (Value) {
2908 glEnable(GL_BLEND);
2909 checkGLcall("glEnable GL_BLEND");
2910 } else {
2911 glDisable(GL_BLEND);
2912 checkGLcall("glDisable GL_BLEND");
2914 break;
2916 case WINED3DRS_SRCBLEND :
2917 case WINED3DRS_DESTBLEND :
2919 int newVal = GL_ZERO;
2920 switch (Value) {
2921 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2922 case D3DBLEND_ONE : newVal = GL_ONE; break;
2923 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2924 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2925 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2926 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2927 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2928 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2929 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2930 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2931 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2933 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2934 This->srcBlend = newVal;
2935 This->dstBlend = newVal;
2936 break;
2938 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2939 This->srcBlend = newVal;
2940 This->dstBlend = newVal;
2941 break;
2942 default:
2943 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2946 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2947 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2948 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2949 glBlendFunc(This->srcBlend, This->dstBlend);
2951 checkGLcall("glBlendFunc");
2953 break;
2955 case WINED3DRS_ALPHATESTENABLE :
2956 if (Value) {
2957 glEnable(GL_ALPHA_TEST);
2958 checkGLcall("glEnable GL_ALPHA_TEST");
2959 } else {
2960 glDisable(GL_ALPHA_TEST);
2961 checkGLcall("glDisable GL_ALPHA_TEST");
2963 break;
2965 case WINED3DRS_ALPHAFUNC :
2967 int glParm = GL_LESS;
2968 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2970 switch ((D3DCMPFUNC) Value) {
2971 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2972 case D3DCMP_LESS: glParm = GL_LESS; break;
2973 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2974 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2975 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2976 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2977 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2978 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2979 default:
2980 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2982 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2983 glAlphaFunc(glParm, ref);
2984 This->alphafunc = glParm;
2985 checkGLcall("glAlphaFunc");
2987 break;
2989 case WINED3DRS_ALPHAREF :
2991 int glParm = This->alphafunc;
2992 float ref = 1.0f;
2994 ref = ((float) Value) / 255.0f;
2995 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2996 glAlphaFunc(glParm, ref);
2997 checkGLcall("glAlphaFunc");
2999 break;
3001 case WINED3DRS_CLIPPLANEENABLE :
3002 case WINED3DRS_CLIPPING :
3004 /* Ensure we only do the changed clip planes */
3005 DWORD enable = 0xFFFFFFFF;
3006 DWORD disable = 0x00000000;
3008 /* If enabling / disabling all */
3009 if (State == WINED3DRS_CLIPPING) {
3010 if (Value) {
3011 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3012 disable = 0x00;
3013 } else {
3014 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3015 enable = 0x00;
3017 } else {
3018 enable = Value & ~OldValue;
3019 disable = ~Value & OldValue;
3022 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
3023 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
3024 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
3025 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
3026 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
3027 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
3029 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
3030 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
3031 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
3032 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
3033 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
3034 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
3036 /** update clipping status */
3037 if (enable) {
3038 This->stateBlock->clip_status.ClipUnion = 0;
3039 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
3040 } else {
3041 This->stateBlock->clip_status.ClipUnion = 0;
3042 This->stateBlock->clip_status.ClipIntersection = 0;
3045 break;
3047 case WINED3DRS_BLENDOP :
3049 int glParm = GL_FUNC_ADD;
3051 switch ((D3DBLENDOP) Value) {
3052 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
3053 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
3054 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3055 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
3056 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
3057 default:
3058 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
3060 TRACE("glBlendEquation(%x)\n", glParm);
3061 glBlendEquation(glParm);
3062 checkGLcall("glBlendEquation");
3064 break;
3066 case WINED3DRS_TEXTUREFACTOR :
3068 unsigned int i;
3070 /* Note the texture color applies to all textures whereas
3071 GL_TEXTURE_ENV_COLOR applies to active only */
3072 float col[4];
3073 D3DCOLORTOGLFLOAT4(Value, col);
3074 /* Set the default alpha blend color */
3075 glBlendColor(col[0], col[1], col[2], col[3]);
3076 checkGLcall("glBlendColor");
3078 /* And now the default texture color as well */
3079 for (i = 0; i < GL_LIMITS(textures); i++) {
3081 /* Note the D3DRS value applies to all textures, but GL has one
3082 per texture, so apply it now ready to be used! */
3083 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3084 GLACTIVETEXTURE(i);
3085 } else if (i>0) {
3086 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3089 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3090 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3093 break;
3095 case WINED3DRS_SPECULARENABLE :
3097 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3098 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3099 specular color. This is wrong:
3100 Separate specular color means the specular colour is maintained separately, whereas
3101 single color means it is merged in. However in both cases they are being used to
3102 some extent.
3103 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3104 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3105 running 1.4 yet!
3107 if (Value) {
3108 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3109 checkGLcall("glMaterialfv");
3110 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3111 glEnable(GL_COLOR_SUM_EXT);
3112 } else {
3113 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3115 checkGLcall("glEnable(GL_COLOR_SUM)");
3116 } else {
3117 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3119 /* for the case of enabled lighting: */
3120 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3121 checkGLcall("glMaterialfv");
3123 /* for the case of disabled lighting: */
3124 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3125 glDisable(GL_COLOR_SUM_EXT);
3126 } else {
3127 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3129 checkGLcall("glDisable(GL_COLOR_SUM)");
3132 break;
3134 case WINED3DRS_STENCILENABLE :
3135 if (Value) {
3136 glEnable(GL_STENCIL_TEST);
3137 checkGLcall("glEnable GL_STENCIL_TEST");
3138 } else {
3139 glDisable(GL_STENCIL_TEST);
3140 checkGLcall("glDisable GL_STENCIL_TEST");
3142 break;
3144 case WINED3DRS_STENCILFUNC :
3146 int glParm = GL_ALWAYS;
3147 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3148 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3150 switch ((D3DCMPFUNC) Value) {
3151 case D3DCMP_NEVER: glParm=GL_NEVER; break;
3152 case D3DCMP_LESS: glParm=GL_LESS; break;
3153 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
3154 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
3155 case D3DCMP_GREATER: glParm=GL_GREATER; break;
3156 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
3157 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
3158 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
3159 default:
3160 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3162 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3163 This->stencilfunc = glParm;
3164 glStencilFunc(glParm, ref, mask);
3165 checkGLcall("glStencilFunc");
3167 break;
3169 case WINED3DRS_STENCILREF :
3171 int glParm = This->stencilfunc;
3172 int ref = 0;
3173 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3175 ref = Value;
3176 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3177 glStencilFunc(glParm, ref, mask);
3178 checkGLcall("glStencilFunc");
3180 break;
3182 case WINED3DRS_STENCILMASK :
3184 int glParm = This->stencilfunc;
3185 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3186 GLuint mask = Value;
3188 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3189 glStencilFunc(glParm, ref, mask);
3190 checkGLcall("glStencilFunc");
3192 break;
3194 case WINED3DRS_STENCILFAIL :
3196 GLenum fail ;
3197 GLint zpass ;
3198 GLint zfail ;
3200 fail = StencilOp(Value);
3201 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
3202 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
3203 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
3204 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
3206 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3207 glStencilOp(fail, zfail, zpass);
3208 checkGLcall("glStencilOp(fail, zfail, zpass);");
3210 break;
3211 case WINED3DRS_STENCILZFAIL :
3213 GLint fail ;
3214 GLint zpass ;
3215 GLenum zfail ;
3217 glGetIntegerv(GL_STENCIL_FAIL, &fail);
3218 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
3219 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
3220 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
3221 zfail = StencilOp(Value);
3223 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3224 glStencilOp(fail, zfail, zpass);
3225 checkGLcall("glStencilOp(fail, zfail, zpass);");
3227 break;
3228 case WINED3DRS_STENCILPASS :
3230 GLint fail ;
3231 GLenum zpass ;
3232 GLint zfail ;
3234 glGetIntegerv(GL_STENCIL_FAIL, &fail);
3235 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
3236 zpass = StencilOp(Value);
3237 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
3238 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
3240 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3241 glStencilOp(fail, zfail, zpass);
3242 checkGLcall("glStencilOp(fail, zfail, zpass);");
3244 break;
3246 case WINED3DRS_STENCILWRITEMASK :
3248 glStencilMask(Value);
3249 TRACE("glStencilMask(%lu)\n", Value);
3250 checkGLcall("glStencilMask");
3252 break;
3254 case WINED3DRS_FOGENABLE :
3256 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
3257 glEnable(GL_FOG);
3258 checkGLcall("glEnable GL_FOG");
3259 } else {
3260 glDisable(GL_FOG);
3261 checkGLcall("glDisable GL_FOG");
3264 break;
3266 case WINED3DRS_RANGEFOGENABLE :
3268 if (Value) {
3269 TRACE("Enabled RANGEFOG");
3270 } else {
3271 TRACE("Disabled RANGEFOG");
3274 break;
3276 case WINED3DRS_FOGCOLOR :
3278 float col[4];
3279 D3DCOLORTOGLFLOAT4(Value, col);
3280 /* Set the default alpha blend color */
3281 glFogfv(GL_FOG_COLOR, &col[0]);
3282 checkGLcall("glFog GL_FOG_COLOR");
3284 break;
3286 case WINED3DRS_FOGTABLEMODE :
3288 glHint(GL_FOG_HINT, GL_NICEST);
3289 switch (Value) {
3290 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3291 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3292 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3293 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3294 default:
3295 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3297 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3298 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3301 break;
3303 case WINED3DRS_FOGVERTEXMODE :
3305 glHint(GL_FOG_HINT, GL_FASTEST);
3306 switch (Value) {
3307 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3308 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3309 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3310 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3311 default:
3312 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3314 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3315 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
3318 break;
3320 case WINED3DRS_FOGSTART :
3322 tmpvalue.d = Value;
3323 glFogfv(GL_FOG_START, &tmpvalue.f);
3324 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3325 TRACE("Fog Start == %f\n", tmpvalue.f);
3327 break;
3329 case WINED3DRS_FOGEND :
3331 tmpvalue.d = Value;
3332 glFogfv(GL_FOG_END, &tmpvalue.f);
3333 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3334 TRACE("Fog End == %f\n", tmpvalue.f);
3336 break;
3338 case WINED3DRS_FOGDENSITY :
3340 tmpvalue.d = Value;
3341 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3342 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3344 break;
3346 case WINED3DRS_VERTEXBLEND :
3348 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3349 TRACE("Vertex Blending state to %ld\n", Value);
3351 break;
3353 case WINED3DRS_TWEENFACTOR :
3355 tmpvalue.d = Value;
3356 This->updateStateBlock->tween_factor = tmpvalue.f;
3357 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3359 break;
3361 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
3363 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3365 break;
3367 case WINED3DRS_COLORVERTEX :
3368 case WINED3DRS_DIFFUSEMATERIALSOURCE :
3369 case WINED3DRS_SPECULARMATERIALSOURCE :
3370 case WINED3DRS_AMBIENTMATERIALSOURCE :
3371 case WINED3DRS_EMISSIVEMATERIALSOURCE :
3373 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3375 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3376 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3377 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3378 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3379 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3380 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3382 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3383 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3384 Parm = GL_AMBIENT_AND_DIFFUSE;
3385 } else {
3386 Parm = GL_DIFFUSE;
3388 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3389 Parm = GL_AMBIENT;
3390 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3391 Parm = GL_EMISSION;
3392 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3393 Parm = GL_SPECULAR;
3394 } else {
3395 Parm = -1;
3398 if (Parm == -1) {
3399 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3400 } else {
3401 This->tracking_color = NEEDS_TRACKING;
3402 This->tracking_parm = Parm;
3405 } else {
3406 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3409 break;
3411 case WINED3DRS_LINEPATTERN :
3413 union {
3414 DWORD d;
3415 D3DLINEPATTERN lp;
3416 } tmppattern;
3417 tmppattern.d = Value;
3419 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3421 if (tmppattern.lp.wRepeatFactor) {
3422 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3423 checkGLcall("glLineStipple(repeat, linepattern)");
3424 glEnable(GL_LINE_STIPPLE);
3425 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3426 } else {
3427 glDisable(GL_LINE_STIPPLE);
3428 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3431 break;
3433 case WINED3DRS_ZBIAS : /* D3D8 only */
3435 if (Value) {
3436 tmpvalue.d = Value;
3437 TRACE("ZBias value %f\n", tmpvalue.f);
3438 glPolygonOffset(0, -tmpvalue.f);
3439 checkGLcall("glPolygonOffset(0, -Value)");
3440 glEnable(GL_POLYGON_OFFSET_FILL);
3441 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3442 glEnable(GL_POLYGON_OFFSET_LINE);
3443 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3444 glEnable(GL_POLYGON_OFFSET_POINT);
3445 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3446 } else {
3447 glDisable(GL_POLYGON_OFFSET_FILL);
3448 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3449 glDisable(GL_POLYGON_OFFSET_LINE);
3450 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3451 glDisable(GL_POLYGON_OFFSET_POINT);
3452 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3455 break;
3457 case WINED3DRS_NORMALIZENORMALS :
3458 if (Value) {
3459 glEnable(GL_NORMALIZE);
3460 checkGLcall("glEnable(GL_NORMALIZE);");
3461 } else {
3462 glDisable(GL_NORMALIZE);
3463 checkGLcall("glDisable(GL_NORMALIZE);");
3465 break;
3467 case WINED3DRS_POINTSIZE :
3468 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
3469 tmpvalue.d = Value;
3470 TRACE("Set point size to %f\n", tmpvalue.f);
3471 glPointSize(tmpvalue.f);
3472 checkGLcall("glPointSize(...);");
3473 break;
3475 case WINED3DRS_POINTSIZE_MIN :
3476 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3477 tmpvalue.d = Value;
3478 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3479 checkGLcall("glPointParameterfEXT(...);");
3480 } else {
3481 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3483 break;
3485 case WINED3DRS_POINTSIZE_MAX :
3486 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3487 tmpvalue.d = Value;
3488 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3489 checkGLcall("glPointParameterfEXT(...);");
3490 } else {
3491 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3493 break;
3495 case WINED3DRS_POINTSCALE_A :
3496 case WINED3DRS_POINTSCALE_B :
3497 case WINED3DRS_POINTSCALE_C :
3498 case WINED3DRS_POINTSCALEENABLE :
3501 * POINTSCALEENABLE controls how point size value is treated. If set to
3502 * true, the point size is scaled with repsect to height of viewport.
3503 * When set to false point size is in pixels.
3505 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
3508 /* Default values */
3509 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3512 * Minium valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
3513 * This means that OpenGL will clamp really small point sizes to 1.0f.
3514 * To correct for this we need to multiply by the scale factor when sizes
3515 * are less than 1.0f. scale_factor = 1.0f / point_size.
3517 GLfloat pointSize = *((float*)&This->stateBlock->renderState[D3DRS_POINTSIZE]);
3518 GLfloat scaleFactor;
3519 if(pointSize < 1.0f) {
3520 scaleFactor = pointSize * pointSize;
3521 } else {
3522 scaleFactor = 1.0f;
3525 if(This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3526 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]) /
3527 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3528 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]) /
3529 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3530 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) /
3531 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3534 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
3535 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
3536 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
3538 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3539 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3540 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
3541 } else {
3542 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
3544 break;
3546 case WINED3DRS_COLORWRITEENABLE :
3548 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3549 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3550 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3551 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3552 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3553 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3554 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3555 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3556 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3557 checkGLcall("glColorMask(...)");
3559 break;
3561 case WINED3DRS_LOCALVIEWER :
3563 GLint state = (Value) ? 1 : 0;
3564 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3565 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3567 break;
3569 case WINED3DRS_LASTPIXEL :
3571 if (Value) {
3572 TRACE("Last Pixel Drawing Enabled\n");
3573 } else {
3574 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3577 break;
3579 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3581 if (Value) {
3582 TRACE("Software Processing Enabled\n");
3583 } else {
3584 TRACE("Software Processing Disabled\n");
3587 break;
3589 /** not supported */
3590 case WINED3DRS_ZVISIBLE :
3592 LEAVE_GL();
3593 return D3DERR_INVALIDCALL;
3595 case WINED3DRS_POINTSPRITEENABLE :
3597 /* TODO: NV_POINT_SPRITE */
3598 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
3599 TRACE("Point sprites not supported\n");
3600 break;
3604 * Point sprites are always enabled. Value controls texture coordinate
3605 * replacement mode. Must be set true for point sprites to use
3606 * textures.
3608 glEnable(GL_POINT_SPRITE_ARB);
3609 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
3611 if (Value) {
3612 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
3613 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, TRUE)");
3614 } else {
3615 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, FALSE);
3616 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, FALSE)");
3618 break;
3620 case WINED3DRS_EDGEANTIALIAS :
3622 if(Value) {
3623 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3624 glEnable(GL_BLEND);
3625 checkGLcall("glEnable(GL_BLEND)");
3626 glEnable(GL_LINE_SMOOTH);
3627 checkGLcall("glEnable(GL_LINE_SMOOTH)");
3628 } else {
3629 glDisable(GL_BLEND);
3630 checkGLcall("glDisable(GL_BLEND)");
3631 glDisable(GL_LINE_SMOOTH);
3632 checkGLcall("glDisable(GL_LINE_SMOOTH)");
3634 break;
3636 case WINED3DRS_WRAP0 :
3637 case WINED3DRS_WRAP1 :
3638 case WINED3DRS_WRAP2 :
3639 case WINED3DRS_WRAP3 :
3640 case WINED3DRS_WRAP4 :
3641 case WINED3DRS_WRAP5 :
3642 case WINED3DRS_WRAP6 :
3643 case WINED3DRS_WRAP7 :
3645 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
3646 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
3647 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
3648 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
3649 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
3651 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
3653 TRACE("(%p)->(%d,%ld) Texture wraping not yet supported\n",This, State, Value);
3654 break;
3655 case WINED3DRS_MULTISAMPLEANTIALIAS :
3657 if (!GL_SUPPORT(ARB_MULTISAMPLE)) {
3658 TRACE("Multisample antialiasing not supported\n");
3659 break;
3662 if(Value) {
3663 glEnable(GL_MULTISAMPLE_ARB);
3664 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
3665 } else {
3666 glDisable(GL_MULTISAMPLE_ARB);
3667 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
3669 break;
3671 case WINED3DRS_MULTISAMPLEMASK :
3672 case WINED3DRS_PATCHEDGESTYLE :
3673 case WINED3DRS_PATCHSEGMENTS :
3674 case WINED3DRS_DEBUGMONITORTOKEN :
3675 case WINED3DRS_POSITIONORDER :
3676 case WINED3DRS_NORMALORDER :
3677 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3678 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3679 break;
3680 default:
3681 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3684 LEAVE_GL();
3686 return D3D_OK;
3689 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3690 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3691 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3692 *pValue = This->stateBlock->renderState[State];
3693 return D3D_OK;
3696 /*****
3697 * Get / Set Sampler States
3698 * TODO: Verify against dx9 definitions
3699 *****/
3701 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3702 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3704 * SetSampler is designed to allow for more than the standard up to 8 textures
3705 * and Geforce has stopped supporting more than 6 standard textures in openGL.
3706 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3708 * http://developer.nvidia.com/object/General_FAQ.html#t6
3710 * There are two new settings for GForce
3711 * the sampler one:
3712 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3713 * and the texture one:
3714 * GL_MAX_TEXTURE_COORDS_ARB.
3715 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3716 ******************/
3717 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
3718 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
3720 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
3721 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE, Sampler, Type);
3722 return D3DERR_INVALIDCALL;
3724 TRACE("Setting sampler %ld %d to %ld\n", Sampler, Type, Value);
3725 This->updateStateBlock->samplerState[Sampler][Type] = Value;
3726 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
3727 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
3729 /* Handle recording of state blocks */
3730 if (This->isRecordingState) {
3731 TRACE("Recording... not performing anything\n");
3732 return D3D_OK;
3735 return D3D_OK;
3738 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3739 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3740 /** TODO: check that sampler is in range **/
3741 *Value = This->updateStateBlock->samplerState[Sampler][Type];
3742 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
3744 return D3D_OK;
3747 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3748 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3749 ENTER_GL();
3751 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3752 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3753 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3754 LEAVE_GL();
3756 return D3D_OK;
3759 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3760 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3761 GLint scissorBox[4];
3763 ENTER_GL();
3764 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3765 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
3766 pRect->left = scissorBox[1];
3767 pRect->top = scissorBox[2];
3768 pRect->right = scissorBox[1] + scissorBox[3];
3769 pRect->bottom = scissorBox[2] + scissorBox[4];
3770 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3771 LEAVE_GL();
3772 return D3D_OK;
3775 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3776 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3777 IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
3779 TRACE("(%p) : pDecl=%p\n", This, pDecl);
3781 This->updateStateBlock->vertexDecl = pDecl;
3782 This->updateStateBlock->changed.vertexDecl = TRUE;
3783 This->updateStateBlock->set.vertexDecl = TRUE;
3785 if (This->isRecordingState) {
3786 TRACE("Recording... not performing anything\n");
3789 if (NULL != pDecl) {
3790 IWineD3DVertexDeclaration_AddRef(pDecl);
3792 if (NULL != oldDecl) {
3793 IWineD3DVertexDeclaration_Release(oldDecl);
3795 return D3D_OK;
3798 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3799 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3801 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3803 *ppDecl = This->stateBlock->vertexDecl;
3804 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3805 return D3D_OK;
3808 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
3809 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3810 IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
3812 This->updateStateBlock->vertexShader = pShader;
3813 This->updateStateBlock->changed.vertexShader = TRUE;
3814 This->updateStateBlock->set.vertexShader = TRUE;
3816 if (This->isRecordingState) {
3817 TRACE("Recording... not performing anything\n");
3820 if (NULL != pShader) {
3821 IWineD3DVertexShader_AddRef(pShader);
3823 if (NULL != oldShader) {
3824 IWineD3DVertexShader_Release(oldShader);
3827 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3829 * TODO: merge HAL shaders context switching from prototype
3831 return D3D_OK;
3834 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
3835 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3837 if (NULL == ppShader) {
3838 return D3DERR_INVALIDCALL;
3840 *ppShader = This->stateBlock->vertexShader;
3841 if( NULL != *ppShader)
3842 IWineD3DVertexShader_AddRef(*ppShader);
3844 TRACE("(%p) : returning %p\n", This, *ppShader);
3845 return D3D_OK;
3848 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
3849 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3851 int i;
3852 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
3854 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
3855 iface, dstData, srcData, type, start, count, registersize);
3857 if (type != WINESHADERCNST_NONE) {
3858 if (srcData == NULL || cnt < 0) {
3859 return D3DERR_INVALIDCALL;
3862 CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
3865 for (i = start; i < cnt + start; ++i) {
3866 This->updateStateBlock->changed.vertexShaderConstants[i] = TRUE;
3867 This->updateStateBlock->set.vertexShaderConstants[i] = TRUE;
3868 This->updateStateBlock->vertexShaderConstantT[i] = type;
3871 return D3D_OK;
3874 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
3875 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3877 int i;
3878 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
3880 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
3881 iface, dstData, srcData, type, start, count, registersize);
3883 /* Verify that the requested shader constant was populated with the correct type */
3884 for (i = start; i < cnt + start; ++i) {
3885 if (This->updateStateBlock->vertexShaderConstantT[i] != type) {
3886 TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning D3DERR_INVALIDCALL\n",
3887 This, type, This->updateStateBlock->vertexShaderConstantT[i]);
3888 return D3DERR_INVALIDCALL;
3892 if (dstData == NULL || cnt < 0) {
3893 return D3DERR_INVALIDCALL;
3896 CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
3898 return D3D_OK;
3901 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
3902 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3904 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
3905 This->updateStateBlock->vertexShaderConstantB,
3906 pConstantData,
3907 WINESHADERCNST_BOOL,
3908 StartRegister,
3909 BoolCount,
3910 sizeof(*pConstantData));
3913 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
3914 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3916 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
3917 pConstantData,
3918 This->updateStateBlock->vertexShaderConstantB,
3919 WINESHADERCNST_BOOL,
3920 StartRegister,
3921 BoolCount,
3922 sizeof(*pConstantData));
3925 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
3926 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3928 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
3929 This->updateStateBlock->vertexShaderConstantI,
3930 pConstantData,
3931 WINESHADERCNST_INTEGER,
3932 StartRegister,
3933 Vector4iCount,
3934 4 * sizeof(*pConstantData));
3937 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
3938 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3940 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
3941 pConstantData,
3942 This->updateStateBlock->vertexShaderConstantI,
3943 WINESHADERCNST_INTEGER,
3944 StartRegister,
3945 Vector4iCount,
3946 4 * sizeof(*pConstantData));
3950 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
3951 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3953 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
3954 This->updateStateBlock->vertexShaderConstantF,
3955 pConstantData,
3956 WINESHADERCNST_FLOAT,
3957 StartRegister,
3958 Vector4fCount,
3959 4 * sizeof(*pConstantData));
3962 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
3963 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3965 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
3966 pConstantData,
3967 This->updateStateBlock->vertexShaderConstantF,
3968 WINESHADERCNST_FLOAT,
3969 StartRegister,
3970 Vector4fCount,
3971 4 * sizeof(*pConstantData));
3974 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
3975 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
3976 NULL,
3977 NULL,
3978 WINESHADERCNST_NONE,
3979 StartRegister,
3980 VectorNCount,
3984 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
3985 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3986 IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader;
3987 This->updateStateBlock->pixelShader = pShader;
3988 This->updateStateBlock->changed.pixelShader = TRUE;
3989 This->updateStateBlock->set.pixelShader = TRUE;
3991 /* Handle recording of state blocks */
3992 if (This->isRecordingState) {
3993 TRACE("Recording... not performing anything\n");
3996 if (NULL != pShader) {
3997 IWineD3DPixelShader_AddRef(pShader);
3999 if (NULL != oldShader) {
4000 IWineD3DPixelShader_Release(oldShader);
4003 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4005 * TODO: merge HAL shaders context switching from prototype
4007 return D3D_OK;
4010 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
4011 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4013 if (NULL == ppShader) {
4014 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
4015 return D3DERR_INVALIDCALL;
4018 *ppShader = This->stateBlock->pixelShader;
4019 if (NULL != ppShader) {
4020 IWineD3DPixelShader_AddRef(*ppShader);
4022 TRACE("(%p) : returning %p\n", This, *ppShader);
4023 return D3D_OK;
4026 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4027 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4029 int i;
4030 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4032 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4033 iface, dstData, srcData, type, start, count, registersize);
4035 if (type != WINESHADERCNST_NONE) {
4036 if (srcData == NULL || cnt < 0) {
4037 return D3DERR_INVALIDCALL;
4040 CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
4043 for (i = start; i < cnt + start; ++i) {
4044 This->updateStateBlock->changed.pixelShaderConstants[i] = TRUE;
4045 This->updateStateBlock->set.pixelShaderConstants[i] = TRUE;
4046 This->updateStateBlock->pixelShaderConstantT[i] = type;
4049 return D3D_OK;
4052 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4053 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4055 int i;
4056 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4058 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4059 iface, dstData, srcData, type, start, count, registersize);
4061 /* Verify that the requested shader constant was populated with the correct type */
4062 for (i = start; i < cnt + start; ++i) {
4063 if (This->updateStateBlock->pixelShaderConstantT[i] != type) {
4064 TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning D3DERR_INVALIDCALL\n",
4065 This, type, This->updateStateBlock->pixelShaderConstantT[i]);
4066 return D3DERR_INVALIDCALL;
4070 if (dstData == NULL || cnt < 0) {
4071 return D3DERR_INVALIDCALL;
4074 CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
4076 return D3D_OK;
4079 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
4080 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4082 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4083 This->updateStateBlock->pixelShaderConstantB,
4084 pConstantData,
4085 WINESHADERCNST_BOOL,
4086 StartRegister,
4087 BoolCount,
4088 sizeof(*pConstantData));
4091 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
4092 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4094 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4095 pConstantData,
4096 This->updateStateBlock->pixelShaderConstantB,
4097 WINESHADERCNST_BOOL,
4098 StartRegister,
4099 BoolCount,
4100 sizeof(*pConstantData));
4103 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
4104 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4106 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4107 This->updateStateBlock->pixelShaderConstantI,
4108 pConstantData,
4109 WINESHADERCNST_INTEGER,
4110 StartRegister,
4111 Vector4iCount,
4112 4 * sizeof(*pConstantData));
4115 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
4116 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4118 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4119 pConstantData,
4120 This->updateStateBlock->pixelShaderConstantI,
4121 WINESHADERCNST_INTEGER,
4122 StartRegister,
4123 Vector4iCount,
4124 4 * sizeof(*pConstantData));
4127 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
4128 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4130 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4131 This->updateStateBlock->pixelShaderConstantF,
4132 pConstantData,
4133 WINESHADERCNST_FLOAT,
4134 StartRegister,
4135 Vector4fCount,
4136 4 * sizeof(*pConstantData));
4139 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
4140 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4142 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4143 pConstantData,
4144 This->updateStateBlock->pixelShaderConstantF,
4145 WINESHADERCNST_FLOAT,
4146 StartRegister,
4147 Vector4fCount,
4148 4 * sizeof(*pConstantData));
4151 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
4152 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4153 NULL,
4154 NULL,
4155 WINESHADERCNST_NONE,
4156 StartRegister,
4157 VectorNCount,
4161 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
4162 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4163 FIXME("(%p) : stub\n", This);
4164 return D3D_OK;
4167 /*****
4168 * Apply / Get / Set Texture Stage States
4169 * TODO: Verify against dx9 definitions
4170 *****/
4172 /* NOTE: It's expected that this function is going to be called lots of times with the same stage active, so make it the callers responsibility to GLACTIVETEXTURE(Stage) for better state management. Set the correct Texture unit active before calling ApplyTextureStageState */
4173 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
4174 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4175 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
4176 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4178 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4180 /* Check that the stage is within limits */
4181 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4182 TRACE("Attempt to access invalid texture rejected\n");
4183 return;
4186 ENTER_GL();
4188 switch (Type) {
4189 case WINED3DTSS_ALPHAOP :
4190 case WINED3DTSS_COLOROP :
4191 /* nothing to do as moved to drawprim for now */
4192 break;
4193 case WINED3DTSS_ADDRESSW :
4194 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
4195 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
4196 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
4198 } else {
4199 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
4200 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
4201 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
4202 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
4204 #endif
4205 case WINED3DTSS_TEXCOORDINDEX :
4207 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
4209 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
4210 one flag, you can still specify an index value, which the system uses to
4211 determine the texture wrapping mode.
4212 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
4213 means use the vertex position (camera-space) as the input texture coordinates
4214 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
4215 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
4216 to the TEXCOORDINDEX value */
4219 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
4221 switch (Value & 0xFFFF0000) {
4222 case D3DTSS_TCI_PASSTHRU:
4223 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
4224 glDisable(GL_TEXTURE_GEN_S);
4225 glDisable(GL_TEXTURE_GEN_T);
4226 glDisable(GL_TEXTURE_GEN_R);
4227 glDisable(GL_TEXTURE_GEN_Q);
4228 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
4229 break;
4231 case D3DTSS_TCI_CAMERASPACEPOSITION:
4232 /* CameraSpacePosition means use the vertex position, transformed to camera space,
4233 as the input texture coordinates for this stage's texture transformation. This
4234 equates roughly to EYE_LINEAR */
4236 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4237 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4238 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4239 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4240 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4242 glMatrixMode(GL_MODELVIEW);
4243 glPushMatrix();
4244 glLoadIdentity();
4245 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4246 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4247 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4248 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4249 glPopMatrix();
4251 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
4252 glEnable(GL_TEXTURE_GEN_S);
4253 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4254 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4255 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4256 glEnable(GL_TEXTURE_GEN_T);
4257 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4258 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4259 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4260 glEnable(GL_TEXTURE_GEN_R);
4261 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4262 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4263 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4265 break;
4267 case D3DTSS_TCI_CAMERASPACENORMAL:
4269 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4270 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4271 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4272 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4273 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4274 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
4276 glMatrixMode(GL_MODELVIEW);
4277 glPushMatrix();
4278 glLoadIdentity();
4279 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4280 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4281 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4282 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4283 glPopMatrix();
4285 glEnable(GL_TEXTURE_GEN_S);
4286 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4287 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4288 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4289 glEnable(GL_TEXTURE_GEN_T);
4290 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4291 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4292 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4293 glEnable(GL_TEXTURE_GEN_R);
4294 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4295 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4296 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4299 break;
4301 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
4303 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4304 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4305 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4306 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4307 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4308 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
4310 glMatrixMode(GL_MODELVIEW);
4311 glPushMatrix();
4312 glLoadIdentity();
4313 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4314 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4315 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4316 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4317 glPopMatrix();
4319 glEnable(GL_TEXTURE_GEN_S);
4320 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4321 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4322 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4323 glEnable(GL_TEXTURE_GEN_T);
4324 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4325 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4326 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4327 glEnable(GL_TEXTURE_GEN_R);
4328 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4329 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4330 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4333 break;
4335 /* Unhandled types: */
4336 default:
4337 /* Todo: */
4338 /* ? disable GL_TEXTURE_GEN_n ? */
4339 glDisable(GL_TEXTURE_GEN_S);
4340 glDisable(GL_TEXTURE_GEN_T);
4341 glDisable(GL_TEXTURE_GEN_R);
4342 glDisable(GL_TEXTURE_GEN_Q);
4343 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
4344 break;
4347 break;
4349 /* Unhandled */
4350 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
4351 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);
4352 break;
4354 case WINED3DTSS_BUMPENVMAT00 :
4355 case WINED3DTSS_BUMPENVMAT01 :
4356 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
4357 break;
4358 case WINED3DTSS_BUMPENVMAT10 :
4359 case WINED3DTSS_BUMPENVMAT11 :
4360 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
4361 break;
4363 case WINED3DTSS_BUMPENVLSCALE :
4364 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4365 break;
4367 case WINED3DTSS_BUMPENVLOFFSET :
4368 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4369 break;
4371 case WINED3DTSS_RESULTARG :
4372 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4373 break;
4375 default:
4376 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
4377 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4380 LEAVE_GL();
4382 return;
4385 /*****
4386 * Get / Set Texture Stage States
4387 * TODO: Verify against dx9 definitions
4388 *****/
4389 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
4390 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4392 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4394 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4396 /* Reject invalid texture units */
4397 if (Stage >= GL_LIMITS(textures)) {
4398 TRACE("Attempt to access invalid texture rejected\n");
4399 return D3DERR_INVALIDCALL;
4402 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
4403 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
4404 This->updateStateBlock->textureState[Stage][Type] = Value;
4406 return D3D_OK;
4409 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4410 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4411 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4412 *pValue = This->updateStateBlock->textureState[Stage][Type];
4413 return D3D_OK;
4416 /*****
4417 * Get / Set Texture
4418 *****/
4419 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4421 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4422 IWineD3DBaseTexture *oldTexture;
4424 oldTexture = This->updateStateBlock->textures[Stage];
4425 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
4427 #if 0 /* TODO: check so vertex textures */
4428 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
4429 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
4430 return D3D_OK;
4432 #endif
4434 /* Reject invalid texture units */
4435 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4436 WARN("Attempt to access invalid texture rejected\n");
4437 return D3DERR_INVALIDCALL;
4440 if(pTexture != NULL) {
4441 /* SetTexture isn't allowed on textures in D3DPOOL_SCRATCH; The same is
4442 * the case for D3DPOOL_SYSTEMMEM textures unless D3DDEVCAPS_TEXTURESYSTEMMORY is set.
4443 * We don't check the caps as GetDeviceCaps is inefficient and we don't set the cap anyway.
4445 if(((IWineD3DTextureImpl*)pTexture)->resource.pool == D3DPOOL_SCRATCH || ((IWineD3DTextureImpl*)pTexture)->resource.pool == D3DPOOL_SYSTEMMEM) {
4446 WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
4447 return D3DERR_INVALIDCALL;
4451 oldTexture = This->updateStateBlock->textures[Stage];
4452 TRACE("GL_LIMITS %d\n",GL_LIMITS(textures));
4453 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
4455 This->updateStateBlock->set.textures[Stage] = TRUE;
4456 This->updateStateBlock->changed.textures[Stage] = TRUE;
4457 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
4458 This->updateStateBlock->textures[Stage] = pTexture;
4460 /* Handle recording of state blocks */
4461 if (This->isRecordingState) {
4462 TRACE("Recording... not performing anything\n");
4463 return D3D_OK;
4466 /** NOTE: MSDN says that setTexture increases the reference count,
4467 * and the the application nust set the texture back to null (or have a leaky application),
4468 * This means we should pass the refcount up to the parent
4469 *******************************/
4470 if (NULL != This->updateStateBlock->textures[Stage]) {
4471 IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
4474 if (NULL != oldTexture) {
4475 IWineD3DBaseTexture_Release(oldTexture);
4478 return D3D_OK;
4481 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4482 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4483 TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
4485 /* Reject invalid texture units */
4486 if (Stage >= GL_LIMITS(textures)) {
4487 TRACE("Attempt to access invalid texture rejected\n");
4488 return D3DERR_INVALIDCALL;
4490 *ppTexture=This->updateStateBlock->textures[Stage];
4491 if (*ppTexture)
4492 IWineD3DBaseTexture_AddRef(*ppTexture);
4493 else
4494 return D3DERR_INVALIDCALL;
4495 return D3D_OK;
4498 /*****
4499 * Get Back Buffer
4500 *****/
4501 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type,
4502 IWineD3DSurface **ppBackBuffer) {
4503 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4504 IWineD3DSwapChain *swapChain;
4505 HRESULT hr;
4507 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4509 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4510 if (hr == D3D_OK) {
4511 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4512 IWineD3DSwapChain_Release(swapChain);
4513 } else {
4514 *ppBackBuffer = NULL;
4516 return hr;
4519 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4520 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4521 WARN("(%p) : stub, calling idirect3d for now\n", This);
4522 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4525 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
4526 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4527 IWineD3DSwapChain *swapChain;
4528 HRESULT hr;
4530 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4531 if (hr == D3D_OK) {
4532 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4533 IWineD3DSwapChain_Release(swapChain);
4534 } else {
4535 FIXME("(%p) Error getting display mode\n", This);
4537 return hr;
4539 /*****
4540 * Stateblock related functions
4541 *****/
4543 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4544 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4545 IWineD3DStateBlockImpl *object;
4546 TRACE("(%p)", This);
4548 if (This->isRecordingState) {
4549 return D3DERR_INVALIDCALL;
4552 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4553 if (NULL == object ) {
4554 FIXME("(%p)Error allocating memory for stateblock\n", This);
4555 return E_OUTOFMEMORY;
4557 TRACE("(%p) creted object %p\n", This, object);
4558 object->wineD3DDevice= This;
4559 /** FIXME: object->parent = parent; **/
4560 object->parent = NULL;
4561 object->blockType = WINED3DSBT_ALL;
4562 object->ref = 1;
4563 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
4565 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4566 This->updateStateBlock = object;
4567 This->isRecordingState = TRUE;
4569 TRACE("(%p) recording stateblock %p\n",This , object);
4570 return D3D_OK;
4573 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4574 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4576 if (!This->isRecordingState) {
4577 FIXME("(%p) not recording! returning error\n", This);
4578 *ppStateBlock = NULL;
4579 return D3DERR_INVALIDCALL;
4582 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4583 This->isRecordingState = FALSE;
4584 This->updateStateBlock = This->stateBlock;
4585 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4586 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4587 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4588 return D3D_OK;
4591 /*****
4592 * Scene related functions
4593 *****/
4594 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4595 /* At the moment we have no need for any functionality at the beginning
4596 of a scene */
4597 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4598 TRACE("(%p) : stub\n", This);
4599 return D3D_OK;
4602 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4603 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4604 TRACE("(%p)\n", This);
4605 ENTER_GL();
4606 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4607 glFlush();
4608 checkGLcall("glFlush");
4610 TRACE("End Scene\n");
4611 if(This->renderTarget != NULL) {
4613 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4614 IUnknown *targetContainer = NULL;
4615 if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
4616 || D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
4617 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
4618 /** always dirtify for now. we must find a better way to see that surface have been modified
4619 (Modifications should will only occur via draw-primitive, but we do need better locking
4620 switching to render-to-texture should remove the overhead though.
4622 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4623 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
4624 IWineD3DSurface_PreLoad(This->renderTarget);
4625 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4626 IUnknown_Release(targetContainer);
4629 This->sceneEnded = TRUE;
4630 LEAVE_GL();
4631 return D3D_OK;
4634 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4635 CONST RECT* pSourceRect, CONST RECT* pDestRect,
4636 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4637 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4638 IWineD3DSwapChain *swapChain = NULL;
4639 int i;
4640 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4642 TRACE("(%p) Presenting the frame\n", This);
4644 for(i = 0 ; i < swapchains ; i ++) {
4646 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4647 TRACE("presentinng chain %d, %p\n", i, swapChain);
4648 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4649 IWineD3DSwapChain_Release(swapChain);
4652 return D3D_OK;
4655 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4656 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4657 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4659 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4660 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4661 when the depth-buffer format does not contain stencil buffer information, this method fails. */
4662 GLbitfield glMask = 0;
4663 GLboolean old_ztest;
4664 GLfloat old_z_clear_value;
4665 GLint old_stencil_clear_value;
4666 GLfloat old_color_clear_value[4];
4667 unsigned int i;
4668 CONST D3DRECT* curRect;
4670 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4671 Count, pRects, Flags, Z, Stencil);
4673 ENTER_GL();
4675 glEnable(GL_SCISSOR_TEST);
4676 checkGLcall("glEnable GL_SCISSOR_TEST");
4678 if (Count > 0 && pRects) {
4679 curRect = pRects;
4680 } else {
4681 curRect = NULL;
4684 /* Only set the values up once, as they are not changing */
4685 if (Flags & D3DCLEAR_STENCIL) {
4686 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4687 glClearStencil(Stencil);
4688 checkGLcall("glClearStencil");
4689 glMask = glMask | GL_STENCIL_BUFFER_BIT;
4690 glStencilMask(0xFFFFFFFF);
4693 if (Flags & D3DCLEAR_ZBUFFER) {
4694 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4695 glDepthMask(GL_TRUE);
4696 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4697 glClearDepth(Z);
4698 checkGLcall("glClearDepth");
4699 glMask = glMask | GL_DEPTH_BUFFER_BIT;
4702 if (Flags & D3DCLEAR_TARGET) {
4703 TRACE("Clearing screen with glClear to color %lx\n", Color);
4704 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4705 glClearColor(D3DCOLOR_R(Color),
4706 D3DCOLOR_G(Color),
4707 D3DCOLOR_B(Color),
4708 D3DCOLOR_A(Color));
4709 checkGLcall("glClearColor");
4711 /* Clear ALL colors! */
4712 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4713 glMask = glMask | GL_COLOR_BUFFER_BIT;
4716 /* Now process each rect in turn */
4717 for (i = 0; i < Count || i == 0; i++) {
4719 if (curRect) {
4720 /* Note gl uses lower left, width/height */
4721 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4722 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4723 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4724 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4725 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4726 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4727 checkGLcall("glScissor");
4728 } else {
4729 glScissor(This->stateBlock->viewport.X,
4730 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
4731 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4732 This->stateBlock->viewport.Width,
4733 This->stateBlock->viewport.Height);
4734 checkGLcall("glScissor");
4737 /* Clear the selected rectangle (or full screen) */
4738 glClear(glMask);
4739 checkGLcall("glClear");
4741 /* Step to the next rectangle */
4742 if (curRect) curRect = curRect + sizeof(D3DRECT);
4745 /* Restore the old values (why..?) */
4746 if (Flags & D3DCLEAR_STENCIL) {
4747 glClearStencil(old_stencil_clear_value);
4748 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4750 if (Flags & D3DCLEAR_ZBUFFER) {
4751 glDepthMask(old_ztest);
4752 glClearDepth(old_z_clear_value);
4754 if (Flags & D3DCLEAR_TARGET) {
4755 glClearColor(old_color_clear_value[0],
4756 old_color_clear_value[1],
4757 old_color_clear_value[2],
4758 old_color_clear_value[3]);
4759 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4760 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4761 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4762 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4765 glDisable(GL_SCISSOR_TEST);
4766 checkGLcall("glDisable");
4767 LEAVE_GL();
4769 return D3D_OK;
4772 /*****
4773 * Drawing functions
4774 *****/
4775 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4776 UINT PrimitiveCount) {
4778 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4779 This->stateBlock->streamIsUP = FALSE;
4781 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4782 debug_d3dprimitivetype(PrimitiveType),
4783 StartVertex, PrimitiveCount);
4784 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
4785 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
4788 return D3D_OK;
4791 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4792 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4793 D3DPRIMITIVETYPE PrimitiveType,
4794 INT baseVIndex, UINT minIndex,
4795 UINT NumVertices, UINT startIndex, UINT primCount) {
4797 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4798 UINT idxStride = 2;
4799 IWineD3DIndexBuffer *pIB;
4800 D3DINDEXBUFFER_DESC IdxBufDsc;
4802 pIB = This->stateBlock->pIndexData;
4803 This->stateBlock->streamIsUP = FALSE;
4805 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
4806 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4807 minIndex, NumVertices, startIndex, baseVIndex, primCount);
4809 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4810 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4811 idxStride = 2;
4812 } else {
4813 idxStride = 4;
4816 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
4817 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
4819 return D3D_OK;
4822 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4823 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4824 UINT VertexStreamZeroStride) {
4825 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4827 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4828 debug_d3dprimitivetype(PrimitiveType),
4829 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4831 /* release the stream source */
4832 if (This->stateBlock->streamSource[0] != NULL) {
4833 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
4836 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4837 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4838 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4839 This->stateBlock->streamIsUP = TRUE;
4841 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
4842 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
4843 /* stream zero settings set to null at end, as per the msdn
4844 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
4846 This->stateBlock->streamStride[0] = 0;
4847 This->stateBlock->streamSource[0] = NULL;
4849 /*stream zero settings set to null at end, as per the msdn */
4850 return D3D_OK;
4853 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4854 UINT MinVertexIndex, UINT NumVertices,
4855 UINT PrimitiveCount, CONST void* pIndexData,
4856 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4857 UINT VertexStreamZeroStride) {
4858 int idxStride;
4859 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4861 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4862 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4863 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
4864 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4866 if (IndexDataFormat == WINED3DFMT_INDEX16) {
4867 idxStride = 2;
4868 } else {
4869 idxStride = 4;
4872 /* release the stream and index data */
4873 if (This->stateBlock->streamSource[0] != NULL) {
4874 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
4876 if (This->stateBlock->pIndexData) {
4877 IWineD3DIndexBuffer_Release(This->stateBlock->pIndexData);
4880 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4881 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4882 This->stateBlock->streamIsUP = TRUE;
4883 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4885 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
4886 /* stream zero settings set to null at end as per the msdn
4887 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
4890 /* stream zero settings set to null at end as per the msdn */
4891 This->stateBlock->streamSource[0] = NULL;
4892 This->stateBlock->streamStride[0] = 0;
4894 return D3D_OK;
4897 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4898 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
4899 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4900 HRESULT hr = D3D_OK;
4901 D3DRESOURCETYPE sourceType;
4902 D3DRESOURCETYPE destinationType;
4903 int i ,levels;
4905 /* TODO: think about moving the code into IWineD3DBaseTexture */
4907 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
4909 /* verify that the source and destination textures aren't NULL */
4910 if (NULL == pSourceTexture || NULL == pDestinationTexture) {
4911 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning D3DERR_INVALIDCALL\n",
4912 This, pSourceTexture, pDestinationTexture);
4913 hr = D3DERR_INVALIDCALL;
4916 if (pSourceTexture == pDestinationTexture) {
4917 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning D3DERR_INVALIDCALL\n",
4918 This, pSourceTexture, pDestinationTexture);
4919 hr = D3DERR_INVALIDCALL;
4921 /* Verify that the source and destination textures are the same type */
4922 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
4923 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
4925 if (sourceType != destinationType) {
4926 WARN("(%p) Sorce and destination types must match, returning D3DERR_INVALIDCALL\n",
4927 This);
4928 hr = D3DERR_INVALIDCALL;
4931 /* check that both textures have the identical numbers of levels */
4932 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
4933 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning D3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
4934 hr = D3DERR_INVALIDCALL;
4937 if (D3D_OK == hr) {
4939 /* Make sure that the destination texture is loaded */
4940 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
4942 /* Update every surface level of the texture */
4943 levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
4945 switch (sourceType) {
4946 case D3DRTYPE_TEXTURE:
4948 IWineD3DSurface *srcSurface;
4949 IWineD3DSurface *destSurface;
4951 for (i = 0 ; i < levels ; ++i) {
4952 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture, i, &srcSurface);
4953 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
4954 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4955 IWineD3DSurface_Release(srcSurface);
4956 IWineD3DSurface_Release(destSurface);
4957 if (D3D_OK != hr) {
4958 WARN("(%p) : Call to update surface failed\n", This);
4959 return hr;
4963 break;
4964 case D3DRTYPE_CUBETEXTURE:
4966 IWineD3DSurface *srcSurface;
4967 IWineD3DSurface *destSurface;
4968 D3DCUBEMAP_FACES faceType;
4970 for (i = 0 ; i < levels ; ++i) {
4971 /* Update each cube face */
4972 for (faceType = D3DCUBEMAP_FACE_POSITIVE_X; faceType <= D3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
4973 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture, faceType, i, &srcSurface);
4974 if (D3D_OK != hr) {
4975 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4976 } else {
4977 TRACE("Got srcSurface %p\n", srcSurface);
4979 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
4980 if (D3D_OK != hr) {
4981 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4982 } else {
4983 TRACE("Got desrSurface %p\n", destSurface);
4985 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4986 IWineD3DSurface_Release(srcSurface);
4987 IWineD3DSurface_Release(destSurface);
4988 if (D3D_OK != hr) {
4989 WARN("(%p) : Call to update surface failed\n", This);
4990 return hr;
4995 break;
4996 #if 0 /* TODO: Add support for volume textures */
4997 case D3DRTYPE_VOLUMETEXTURE:
4999 IWineD3DVolume srcVolume = NULL;
5000 IWineD3DSurface destVolume = NULL;
5002 for (i = 0 ; i < levels ; ++i) {
5003 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture, i, &srcVolume);
5004 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
5005 hr = IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
5006 IWineD3DVolume_Release(srcSurface);
5007 IWineD3DVolume_Release(destSurface);
5008 if (D3D_OK != hr) {
5009 WARN("(%p) : Call to update volume failed\n", This);
5010 return hr;
5014 break;
5015 #endif
5016 default:
5017 FIXME("(%p) : Unsupported source and destination type\n", This);
5018 hr = D3DERR_INVALIDCALL;
5022 return hr;
5025 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
5026 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
5027 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
5028 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5030 TRACE("(%p) : stub\n", This);
5031 return D3D_OK;
5033 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
5034 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5035 /** TODO: remove remove casts to IWineD3DSurfaceImpl *
5036 * NOTE It may be best to move the code into surface to occomplish this
5037 ****************************************/
5039 WINED3DSURFACE_DESC surfaceDesc;
5040 unsigned int surfaceWidth, surfaceHeight;
5041 glDescriptor *targetGlDescription = NULL;
5042 glDescriptor *surfaceGlDescription = NULL;
5043 IWineD3DSwapChainImpl *container = NULL;
5045 IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
5046 IWineD3DSurface_GetGlDesc(pSurface, &surfaceGlDescription);
5047 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5049 surfaceDesc.Width = &surfaceWidth;
5050 surfaceDesc.Height = &surfaceHeight;
5051 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5052 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
5054 /* Ok, I may need to setup some kind of active swapchain reference on the device */
5055 IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
5056 ENTER_GL();
5057 /* TODO: opengl Context switching for swapchains etc... */
5058 if (NULL != container || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
5059 if (NULL != container && (pRenderTarget == container->backBuffer)) {
5060 glReadBuffer(GL_BACK);
5061 vcheckGLcall("glReadBuffer(GL_BACK)");
5062 } else if ((NULL != container && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
5063 glReadBuffer(GL_FRONT);
5064 vcheckGLcall("glReadBuffer(GL_FRONT)");
5065 } else if (pRenderTarget == This->depthStencilBuffer) {
5066 FIXME("Reading of depthstencil not yet supported\n");
5069 glReadPixels(surfaceGlDescription->target,
5070 surfaceGlDescription->level,
5071 surfaceWidth,
5072 surfaceHeight,
5073 surfaceGlDescription->glFormat,
5074 surfaceGlDescription->glType,
5075 (void *)IWineD3DSurface_GetData(pSurface));
5076 vcheckGLcall("glReadPixels(...)");
5077 if(NULL != container ){
5078 IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
5080 } else {
5081 IWineD3DBaseTexture *container;
5082 GLenum textureDimensions = GL_TEXTURE_2D;
5084 if (D3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
5085 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
5086 IWineD3DBaseTexture_Release(container);
5088 /* TODO: 2D -> Cube surface coppies etc.. */
5089 if (surfaceGlDescription->target != textureDimensions) {
5090 FIXME("(%p) : Texture dimension mismatch\n", This);
5092 glEnable(textureDimensions);
5093 vcheckGLcall("glEnable(GL_TEXTURE_...)");
5094 /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
5095 glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
5096 vcheckGLcall("glBindTexture");
5097 glGetTexImage(surfaceGlDescription->target,
5098 surfaceGlDescription->level,
5099 surfaceGlDescription->glFormat,
5100 surfaceGlDescription->glType,
5101 (void *)IWineD3DSurface_GetData(pSurface));
5102 glDisable(textureDimensions);
5103 vcheckGLcall("glDisable(GL_TEXTURE_...)");
5106 LEAVE_GL();
5107 return D3D_OK;
5110 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
5111 IWineD3DSwapChain *swapChain;
5112 HRESULT hr;
5113 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5114 if(hr == D3D_OK) {
5115 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
5116 IWineD3DSwapChain_Release(swapChain);
5118 return hr;
5121 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5122 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5123 /* return a sensible default */
5124 *pNumPasses = 1;
5125 /* TODO: If the window is minimized then validate device should return something other than d3d_ok */
5126 FIXME("(%p) : stub\n", This);
5127 return D3D_OK;
5130 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5131 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5132 int j;
5133 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5134 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5135 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5136 return D3DERR_INVALIDCALL;
5138 for (j = 0; j < 256; ++j) {
5139 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
5140 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5141 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
5142 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5144 TRACE("(%p) : returning\n", This);
5145 return D3D_OK;
5148 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5149 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5150 int j;
5151 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5152 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5153 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5154 return D3DERR_INVALIDCALL;
5156 for (j = 0; j < 256; ++j) {
5157 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
5158 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5159 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
5160 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5162 TRACE("(%p) : returning\n", This);
5163 return D3D_OK;
5166 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5167 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5168 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5169 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5170 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5171 return D3DERR_INVALIDCALL;
5173 /*TODO: stateblocks */
5174 This->currentPalette = PaletteNumber;
5175 TRACE("(%p) : returning\n", This);
5176 return D3D_OK;
5179 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
5180 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5181 if (PaletteNumber == NULL) {
5182 WARN("(%p) : returning Invalid Call\n", This);
5183 return D3DERR_INVALIDCALL;
5185 /*TODO: stateblocks */
5186 *PaletteNumber = This->currentPalette;
5187 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
5188 return D3D_OK;
5191 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
5192 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5193 static BOOL showFixmes = TRUE;
5194 if (showFixmes) {
5195 FIXME("(%p) : stub\n", This);
5196 showFixmes = FALSE;
5199 This->softwareVertexProcessing = bSoftware;
5200 return D3D_OK;
5204 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
5205 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5206 static BOOL showFixmes = TRUE;
5207 if (showFixmes) {
5208 FIXME("(%p) : stub\n", This);
5209 showFixmes = FALSE;
5211 return This->softwareVertexProcessing;
5215 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
5216 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5217 IWineD3DSwapChain *swapChain;
5218 HRESULT hr;
5220 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
5222 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5223 if(hr == D3D_OK){
5224 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
5225 IWineD3DSwapChain_Release(swapChain);
5226 }else{
5227 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
5229 return hr;
5233 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
5234 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5235 static BOOL showfixmes = TRUE;
5236 if(nSegments != 0.0f) {
5237 if( showfixmes) {
5238 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
5239 showfixmes = FALSE;
5242 return D3D_OK;
5245 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
5246 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5247 static BOOL showfixmes = TRUE;
5248 if( showfixmes) {
5249 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
5250 showfixmes = FALSE;
5252 return 0.0f;
5255 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
5256 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5257 /** TODO: remove casts to IWineD3DSurfaceImpl
5258 * NOTE: move code to surface to accomplish this
5259 ****************************************/
5260 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
5261 int srcWidth, srcHeight;
5262 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
5263 WINED3DFORMAT destFormat, srcFormat;
5264 UINT destSize;
5265 int destLeft, destTop;
5266 D3DPOOL srcPool, destPool;
5267 int offset = 0;
5268 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
5269 glDescriptor *glDescription = NULL;
5270 GLenum textureDimensions = GL_TEXTURE_2D;
5271 IWineD3DBaseTexture *baseTexture;
5273 WINED3DSURFACE_DESC winedesc;
5275 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
5276 memset(&winedesc, 0, sizeof(winedesc));
5277 winedesc.Width = &srcSurfaceWidth;
5278 winedesc.Height = &srcSurfaceHeight;
5279 winedesc.Pool = &srcPool;
5280 winedesc.Format = &srcFormat;
5282 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5284 winedesc.Width = &destSurfaceWidth;
5285 winedesc.Height = &destSurfaceHeight;
5286 winedesc.Pool = &destPool;
5287 winedesc.Format = &destFormat;
5288 winedesc.Size = &destSize;
5290 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5292 if(srcPool != D3DPOOL_SYSTEMMEM || destPool != D3DPOOL_DEFAULT){
5293 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning D3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
5294 return D3DERR_INVALIDCALL;
5297 if (destFormat == WINED3DFMT_UNKNOWN) {
5298 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5299 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5301 /* Get the update surface description */
5302 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5305 /* Make sure the surface is loaded and up to date */
5306 IWineD3DSurface_PreLoad(pDestinationSurface);
5308 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
5310 ENTER_GL();
5312 /* this needs to be done in lines if the sourceRect != the sourceWidth */
5313 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
5314 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
5315 destLeft = pDestPoint ? pDestPoint->x : 0;
5316 destTop = pDestPoint ? pDestPoint->y : 0;
5319 /* This function doesn't support compressed textures
5320 the pitch is just bytesPerPixel * width */
5321 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
5322 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
5323 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
5324 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
5326 /* TODO DXT formats */
5328 if(pSourceRect != NULL && pSourceRect->top != 0){
5329 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
5331 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
5332 ,This
5333 ,glDescription->level
5334 ,destLeft
5335 ,destTop
5336 ,srcWidth
5337 ,srcHeight
5338 ,glDescription->glFormat
5339 ,glDescription->glType
5340 ,IWineD3DSurface_GetData(pSourceSurface)
5343 /* Sanity check */
5344 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
5346 /* need to lock the surface to get the data */
5347 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5350 /* TODO: Cube and volume support */
5351 if(rowoffset != 0){
5352 /* not a whole row so we have to do it a line at a time */
5353 int j;
5355 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
5356 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5358 for(j = destTop ; j < (srcHeight + destTop) ; j++){
5360 glTexSubImage2D(glDescription->target
5361 ,glDescription->level
5362 ,destLeft
5364 ,srcWidth
5366 ,glDescription->glFormat
5367 ,glDescription->glType
5368 ,data /* could be quicker using */
5370 data += rowoffset;
5373 } else { /* Full width, so just write out the whole texture */
5375 if (WINED3DFMT_DXT1 == destFormat ||
5376 WINED3DFMT_DXT2 == destFormat ||
5377 WINED3DFMT_DXT3 == destFormat ||
5378 WINED3DFMT_DXT4 == destFormat ||
5379 WINED3DFMT_DXT5 == destFormat) {
5380 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
5381 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
5382 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
5383 FIXME("Updating part of a compressed texture is not supported at the moment\n");
5384 } if (destFormat != srcFormat) {
5385 FIXME("Updating mixed format compressed texture is not curretly support\n");
5386 } else {
5387 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
5388 glDescription->level,
5389 glDescription->glFormatInternal,
5390 srcWidth,
5391 srcHeight,
5393 destSize,
5394 IWineD3DSurface_GetData(pSourceSurface));
5396 } else {
5397 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
5401 } else {
5402 if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
5404 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
5405 to repack the data from pow2Width/Height to expected Width,Height, this makes the
5406 data returned by GetData non-power2 width/height with hardware non-power2
5407 pow2Width/height are set to surface width height, repacking isn't needed so it
5408 doesn't matter which function gets called. */
5409 glTexSubImage2D(glDescription->target
5410 ,glDescription->level
5411 ,destLeft
5412 ,destTop
5413 ,srcWidth
5414 ,srcHeight
5415 ,glDescription->glFormat
5416 ,glDescription->glType
5417 ,IWineD3DSurface_GetData(pSourceSurface)
5419 } else {
5421 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
5422 glTexSubImage2D(glDescription->target
5423 ,glDescription->level
5424 ,destLeft
5425 ,destTop
5426 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
5427 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
5428 ,glDescription->glFormat
5429 ,glDescription->glType
5430 ,IWineD3DSurface_GetData(pSourceSurface)
5436 checkGLcall("glTexSubImage2D");
5438 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
5439 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
5440 * surface bigger than it needs to be hmm.. */
5441 if (D3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
5442 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
5443 IWineD3DBaseTexture_Release(baseTexture);
5446 glDisable(textureDimensions); /* This needs to be managed better.... */
5447 LEAVE_GL();
5449 return D3D_OK;
5452 /* Implementation details at http://developer.nvidia.com/attach/6494
5454 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
5455 hmm.. no longer supported use
5456 OpenGL evaluators or tessellate surfaces within your application.
5459 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
5460 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
5461 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5462 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
5463 FIXME("(%p) : Stub\n", This);
5464 return D3D_OK;
5468 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
5469 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
5470 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5471 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
5472 FIXME("(%p) : Stub\n", This);
5473 return D3D_OK;
5476 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5477 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5478 TRACE("(%p) Handle(%d)\n", This, Handle);
5479 FIXME("(%p) : Stub\n", This);
5480 return D3D_OK;
5483 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
5484 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
5485 fill a surface with a block of color! */
5486 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5487 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
5488 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
5489 IWineD3DSwapChainImpl *container = NULL;
5490 BOOL isRenderTarget = FALSE;
5491 unsigned int width, height;
5492 unsigned int top, left;
5493 unsigned int u, v;
5494 DWORD *data;
5495 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
5497 if (surface->resource.pool != D3DPOOL_DEFAULT) {
5498 FIXME("call to colorfill with non D3DPOOL_DEFAULT surface\n");
5499 return D3DERR_INVALIDCALL;
5502 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
5503 if (D3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
5504 if (D3DUSAGE_RENDERTARGET & surface->resource.usage) {
5505 /* TODO: make sure we set everything back to the way it was, and context management!
5506 glGetIntegerv(GL_READ_BUFFER, &prev_read);
5507 vcheckGLcall("glIntegerv");
5508 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
5509 vcheckGLcall("glIntegerv");
5511 TRACE("Color fill to render targets may cause some graphics issues\n");
5512 if (pSurface == container->frontBuffer) {
5513 glDrawBuffer(GL_FRONT);
5514 } else {
5515 glDrawBuffer(GL_BACK);
5517 } else {
5518 if (D3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
5519 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld\n", surface, surface->resource.usage);
5520 } else {
5521 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
5523 if (container != NULL) {
5524 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5526 /* we can use GL_STENCIL_INDEX etc...*/
5527 return D3D_OK;
5529 if (container != NULL) {
5530 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5532 isRenderTarget = TRUE;
5534 /* TODO: drawing to GL_FRONT and GL_BACK */
5535 /* TODO: see if things can be speeded up by using the correct
5536 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
5537 if (pRect == NULL) {
5538 top = 0;
5539 left = 0;
5540 width = surface->currentDesc.Width;
5541 height = surface->currentDesc.Height;
5542 } else {
5543 left = pRect->x1;
5544 top = pRect->y1;
5545 width = pRect->x2 - left;
5546 height = pRect->y2 - top;
5549 data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
5550 /* Create a 'line' of color color, in the correct format for the surface */
5551 for (u = 0 ; u < width ; u ++) {
5552 data[u] = color;
5555 ENTER_GL();
5556 if (isRenderTarget == FALSE) {
5557 glDescriptor *glDesc;
5558 IWineD3DSurface_PreLoad(pSurface);
5560 /* draw a block of the coloured line on the sufrace */
5561 IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
5562 for (v = 0 ; v< height;v++) {
5563 glTexSubImage2D(glDesc->target
5564 ,glDesc->level /* level */
5565 ,left
5566 ,top + v
5567 ,width
5568 ,1 /* height */
5569 ,GL_RGBA
5570 ,GL_UNSIGNED_BYTE
5571 ,data
5574 checkGLcall("glTexSubImage2D");
5575 /* clean up */
5576 glDisable(glDesc->target);
5577 } else {
5578 /** FIXME: Using GLClear may be faster **/
5579 glRasterPos2i(left, top);
5580 glPixelZoom((float)width ,(float)height);
5581 glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
5582 checkGLcall("glDrawPixels");
5584 HeapFree(GetProcessHeap(), 0, data);
5585 LEAVE_GL();
5586 return D3D_OK;
5590 /* rendertarget and deptth stencil functions */
5591 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
5592 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5594 /* FIXME: Implelent RenderTargetIndex >0 */
5595 if(RenderTargetIndex > 0)
5596 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
5598 *ppRenderTarget = This->renderTarget;
5599 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
5600 /* Note inc ref on returned surface */
5601 if(*ppRenderTarget != NULL)
5602 IWineD3DSurface_AddRef(*ppRenderTarget);
5603 return D3D_OK;
5606 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5607 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5608 *ppZStencilSurface = This->depthStencilBuffer;
5609 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
5611 if(*ppZStencilSurface != NULL) {
5612 /* Note inc ref on returned surface */
5613 IWineD3DSurface_AddRef(*ppZStencilSurface);
5615 return D3D_OK;
5618 /* internal static helper functions */
5619 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5620 IWineD3DSurface *RenderSurface);
5622 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5623 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5624 HRESULT hr = D3D_OK;
5625 WINED3DVIEWPORT viewport;
5627 TRACE("(%p) Swapping rendertarget\n",This);
5628 if (RenderTargetIndex > 0) {
5629 FIXME("(%p) Render targets other than the first are not supported\n",This);
5630 RenderTargetIndex = 0;
5633 /* MSDN says that null disables the render target
5634 but a device must always be associated with a render target
5635 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5637 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5638 for more details
5640 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5641 FIXME("Trying to set render target 0 to NULL\n");
5642 return D3DERR_INVALIDCALL;
5644 /* TODO: replace Impl* usage with interface usage */
5645 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & D3DUSAGE_RENDERTARGET) {
5646 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);
5647 return D3DERR_INVALIDCALL;
5649 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
5650 * builds, but I think wine counts as a 'debug' build for now.
5651 ******************************/
5652 /* If we are trying to set what we already have, don't bother */
5653 if (pRenderTarget == This->renderTarget) {
5654 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5655 } else {
5656 /* Otherwise, set the render target up */
5658 if (FALSE == This->sceneEnded) {
5659 IWineD3DDevice_EndScene(iface);
5661 TRACE("clearing renderer\n");
5662 /* IWineD3DDeviceImpl_CleanRender(iface); */
5663 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5664 depending on the renter target implementation being used.
5665 A shared context implementation will share all buffers between all rendertargets (including swapchains),
5666 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5667 stencil buffer and incure an extra memory overhead */
5668 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
5671 if (SUCCEEDED(hr)) {
5672 /* Finally, reset the viewport as the MSDN states. */
5673 /* TODO: Replace impl usage */
5674 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
5675 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
5676 viewport.X = 0;
5677 viewport.Y = 0;
5678 viewport.MaxZ = 1.0f;
5679 viewport.MinZ = 0.0f;
5680 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
5681 } else {
5682 FIXME("Unknown error setting the render target\n");
5684 This->sceneEnded = FALSE;
5685 return hr;
5688 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
5689 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5690 HRESULT hr = D3D_OK;
5691 IWineD3DSurface *tmp;
5693 TRACE("(%p) Swapping z-buffer\n",This);
5695 if (pNewZStencil == This->stencilBufferTarget) {
5696 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5697 } else {
5698 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5699 * depending on the renter target implementation being used.
5700 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5701 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5702 * stencil buffer and incure an extra memory overhead
5703 ******************************************************/
5706 tmp = This->stencilBufferTarget;
5707 This->stencilBufferTarget = pNewZStencil;
5708 /* should we be calling the parent or the wined3d surface? */
5709 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
5710 if (NULL != tmp) IWineD3DSurface_Release(tmp);
5711 hr = D3D_OK;
5712 /** TODO: glEnable/glDisable on depth/stencil depending on
5713 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
5714 **********************************************************/
5717 return hr;
5721 #ifdef GL_VERSION_1_3
5722 /* Internal functions not in DirectX */
5723 /** TODO: move this off to the opengl context manager
5724 *(the swapchain doesn't need to know anything about offscreen rendering!)
5725 ****************************************************/
5727 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
5729 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5731 TRACE("(%p), %p\n", This, swapchain);
5733 if (swapchain->win != swapchain->drawable) {
5734 /* Set everything back the way it ws */
5735 swapchain->render_ctx = swapchain->glCtx;
5736 swapchain->drawable = swapchain->win;
5738 return D3D_OK;
5741 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
5742 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
5743 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5744 int i;
5745 unsigned int width;
5746 unsigned int height;
5747 WINED3DFORMAT format;
5748 WINED3DSURFACE_DESC surfaceDesc;
5749 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5750 surfaceDesc.Width = &width;
5751 surfaceDesc.Height = &height;
5752 surfaceDesc.Format = &format;
5753 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5754 *context = NULL;
5755 /* I need a get width/height function (and should do something with the format) */
5756 for (i = 0; i < CONTEXT_CACHE; ++i) {
5757 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
5758 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
5759 the pSurface can be set to 0 allowing it to be reused from cache **/
5760 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
5761 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
5762 *context = &This->contextCache[i];
5763 break;
5765 if (This->contextCache[i].Width == 0) {
5766 This->contextCache[i].pSurface = pSurface;
5767 This->contextCache[i].Width = width;
5768 This->contextCache[i].Height = height;
5769 *context = &This->contextCache[i];
5770 break;
5773 if (i == CONTEXT_CACHE) {
5774 int minUsage = 0x7FFFFFFF; /* MAX_INT */
5775 glContext *dropContext = 0;
5776 for (i = 0; i < CONTEXT_CACHE; i++) {
5777 if (This->contextCache[i].usedcount < minUsage) {
5778 dropContext = &This->contextCache[i];
5779 minUsage = This->contextCache[i].usedcount;
5782 /* clean up the context (this doesn't work for ATI at the moment */
5783 #if 0
5784 glXDestroyContext(swapchain->display, dropContext->context);
5785 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
5786 #endif
5787 FIXME("Leak\n");
5788 dropContext->Width = 0;
5789 dropContext->pSurface = pSurface;
5790 *context = dropContext;
5791 } else {
5792 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
5793 for (i = 0; i < CONTEXT_CACHE; i++) {
5794 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
5798 if (*context != NULL)
5799 return D3D_OK;
5800 else
5801 return E_OUTOFMEMORY;
5803 #endif
5805 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
5806 * the functionality needs splitting up so that we don't do more than we should do.
5807 * this only seems to impact performance a little.
5808 ******************************/
5809 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5810 IWineD3DSurface *RenderSurface) {
5811 HRESULT ret = D3DERR_INVALIDCALL;
5814 * Currently only active for GLX >= 1.3
5815 * for others versions we'll have to use GLXPixmaps
5817 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
5818 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
5819 * so only check OpenGL version
5820 * ..........................
5821 * I don't believe that it is a problem with NVidia headers,
5822 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
5823 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
5824 * ATI Note:
5825 * Your application will report GLX version 1.2 on glXQueryVersion.
5826 * However, it is safe to call the GLX 1.3 functions as described below.
5828 #if defined(GL_VERSION_1_3)
5830 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5831 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
5832 IWineD3DSurface *tmp;
5833 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
5834 GLXFBConfig* cfgs = NULL;
5835 int nCfgs = 0;
5836 int attribs[256];
5837 int nAttribs = 0;
5838 IWineD3DSwapChain *currentSwapchain;
5839 IWineD3DSwapChainImpl *swapchain;
5840 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
5841 * but switch them off if the StencilSurface is set to NULL
5842 ** *********************************************************/
5843 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
5844 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
5846 /**TODO:
5847 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
5848 it StencilSurface != NULL && zBufferTarget == NULL switch it on
5851 #define PUSH1(att) attribs[nAttribs++] = (att);
5852 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
5854 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
5856 /** TODO: remove the reff to Impl (context manager should fix this!) **/
5857 IWineD3DSwapChainImpl *impSwapChain;
5858 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
5859 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
5860 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
5863 ENTER_GL();
5865 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
5866 PUSH2(GLX_X_RENDERABLE, TRUE);
5867 PUSH2(GLX_DOUBLEBUFFER, TRUE);
5868 TRACE("calling makeglcfg\n");
5869 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
5870 PUSH1(None);
5872 TRACE("calling chooseFGConfig\n");
5873 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5874 attribs, &nCfgs);
5876 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
5877 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
5878 why we failed and only show this message once! */
5879 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"); /**/
5880 nAttribs = 0;
5881 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
5882 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
5883 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
5884 PUSH2(GLX_DOUBLEBUFFER, FALSE);
5885 TRACE("calling makeglcfg\n");
5886 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
5887 PUSH1(None);
5888 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5889 attribs, &nCfgs);
5892 if (NULL != cfgs) {
5893 #ifdef EXTRA_TRACES
5894 int i;
5895 for (i = 0; i < nCfgs; ++i) {
5896 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
5897 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
5898 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
5901 if (NULL != This->renderTarget) {
5902 glFlush();
5903 vcheckGLcall("glFlush");
5904 /** This is only useful if the old render target was a swapchain,
5905 * we need to supercede this with a function that displays
5906 * the current buffer on the screen. This is easy to do in glx1.3 but
5907 * we need to do copy-write pixels in glx 1.2.
5908 ************************************************/
5909 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
5911 printf("Hit Enter to get next frame ...\n");
5912 getchar();
5914 #endif
5917 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&currentSwapchain) != D3D_OK) {
5918 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
5919 IWineD3DDevice_GetSwapChain(iface, 0, &currentSwapchain);
5923 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
5924 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
5925 **********************************************************************/
5926 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == D3D_OK) {
5927 /* We also need to make sure that the lights &co are also in the context of the swapchains */
5928 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
5929 TRACE("making swapchain active\n");
5930 if (RenderSurface != This->renderTarget) {
5931 if (RenderSurface == swapchain->backBuffer) {
5932 } else {
5933 /* This could be flagged so that some operations work directly with the front buffer */
5934 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
5936 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
5937 == False) {
5938 TRACE("Error in setting current context: context %p drawable %ld !\n",
5939 impSwapChain->glCtx, impSwapChain->win);
5942 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5944 checkGLcall("glXMakeContextCurrent");
5946 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5948 else if (pbuffer_support == TRUE && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
5950 /** ********************************************************************
5951 * This is a quickly hacked out implementation of offscreen textures.
5952 * It will work in most cases but there may be problems if the client
5953 * modifies the texture directly, or expects the contents of the rendertarget
5954 * to be persistent.
5956 * There are some real speed vs compatibility issues here:
5957 * we should really use a new context for every texture, but that eats ram.
5958 * we should also be restoring the texture to the pbuffer but that eats CPU
5959 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
5960 * but if this means reusing the display backbuffer then we need to make sure that
5961 * states are correctly preserved.
5962 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
5963 * and gain a good performance increase at the cost of compatibility.
5964 * I would suggest that, when this is the case, a user configurable flag be made
5965 * available, allowing the user to choose the best emulated experience for them.
5966 *********************************************************************/
5968 XVisualInfo *visinfo;
5969 glContext *newContext;
5971 /* Here were using a shared context model */
5972 if (D3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
5973 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5976 /* If the context doesn't exist then create a new one */
5977 /* TODO: This should really be part of findGlContext */
5978 if (NULL == newContext->context) {
5980 TRACE("making new buffer\n");
5981 nAttribs = 0;
5982 PUSH2(GLX_PBUFFER_WIDTH, newContext->Width);
5983 PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
5984 PUSH1(None);
5986 newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
5988 /** ****************************************
5989 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
5990 *they note:
5991 * In future releases, we may provide the calls glXCreateNewContext,
5992 * glXQueryDrawable and glXMakeContextCurrent.
5993 * so until then we have to use glXGetVisualFromFBConfig &co..
5994 ********************************************/
5997 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
5998 if (!visinfo) {
5999 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
6000 } else {
6001 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
6002 XFree(visinfo);
6005 if (NULL == newContext || NULL == newContext->context) {
6006 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6007 } else {
6008 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
6009 if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
6010 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
6013 /* Clean up the old context */
6014 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
6015 /* Set the current context of the swapchain to the new context */
6016 impSwapChain->drawable = newContext->drawable;
6017 impSwapChain->render_ctx = newContext->context;
6021 #if 1 /* Apply the stateblock to the new context
6022 FIXME: This is a bit of a hack, each context should know it's own state,
6023 the directX current directX state should then be applied to the context */
6025 BOOL oldRecording;
6026 IWineD3DStateBlockImpl *oldUpdateStateBlock;
6027 oldUpdateStateBlock = This->updateStateBlock;
6028 oldRecording= This->isRecordingState;
6029 This->isRecordingState = FALSE;
6030 This->updateStateBlock = This->stateBlock;
6031 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
6033 This->isRecordingState = oldRecording;
6034 This->updateStateBlock = oldUpdateStateBlock;
6036 #endif
6039 /* clean up the current rendertargets swapchain (if it belonged to one) */
6040 if (currentSwapchain != NULL) {
6041 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
6044 /* Were done with the opengl context management, setup the rendertargets */
6046 tmp = This->renderTarget;
6047 This->renderTarget = RenderSurface;
6048 IWineD3DSurface_AddRef(This->renderTarget);
6049 IWineD3DSurface_Release(tmp);
6054 DWORD value;
6055 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
6056 /* Check that the container is not a swapchain member */
6058 IWineD3DSwapChain *tmpSwapChain;
6059 if (D3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
6060 This->renderUpsideDown = TRUE;
6061 }else{
6062 This->renderUpsideDown = FALSE;
6063 IWineD3DSwapChain_Release(tmpSwapChain);
6065 /* Force updating the cull mode */
6066 TRACE("setting render state\n");
6067 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
6068 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
6070 /* Force updating projection matrix */
6071 This->last_was_rhw = FALSE;
6072 This->proj_valid = FALSE;
6075 ret = D3D_OK;
6077 if (cfgs != NULL) {
6078 XFree(cfgs);
6079 } else {
6080 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
6081 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
6084 #undef PUSH1
6085 #undef PUSH2
6086 if ( NULL != impSwapChain) {
6087 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
6089 LEAVE_GL();
6091 #endif
6092 return ret;
6095 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
6096 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
6097 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6098 /* TODO: the use of Impl is deprecated. */
6099 /* some basic validation checks */
6100 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
6102 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
6104 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
6105 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
6106 return D3DERR_INVALIDCALL;
6108 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
6109 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
6110 return D3DERR_INVALIDCALL;
6112 /* TODO: make the cursor 'real' */
6114 This->xHotSpot = XHotSpot;
6115 This->yHotSpot = YHotSpot;
6117 return D3D_OK;
6120 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
6121 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6122 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
6124 This->xScreenSpace = XScreenSpace;
6125 This->yScreenSpace = YScreenSpace;
6127 return;
6131 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
6132 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6133 TRACE("(%p) : visible(%d)\n", This, bShow);
6135 This->bCursorVisible = bShow;
6137 return D3D_OK;
6140 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
6141 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6142 TRACE("(%p) : state (%lu)\n", This, This->state);
6143 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
6144 switch (This->state) {
6145 case D3D_OK:
6146 return D3D_OK;
6147 case D3DERR_DEVICELOST:
6149 ResourceList *resourceList = This->resources;
6150 while (NULL != resourceList) {
6151 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == D3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
6152 return D3DERR_DEVICENOTRESET;
6153 resourceList = resourceList->next;
6155 return D3DERR_DEVICELOST;
6157 case D3DERR_DRIVERINTERNALERROR:
6158 return D3DERR_DRIVERINTERNALERROR;
6161 /* Unknown state */
6162 return D3DERR_DRIVERINTERNALERROR;
6166 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
6167 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6168 /** FIXME: Resource tracking needs to be done,
6169 * The closes we can do to this is set the priorities of all managed textures low
6170 * and then reset them.
6171 ***********************************************************/
6172 FIXME("(%p) : stub\n", This);
6173 return D3D_OK;
6176 HRESULT WINAPI IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
6177 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6178 /** FIXME: Resource trascking needs to be done.
6179 * in effect this pulls all non only default
6180 * textures out of video memory and deletes all glTextures (glDeleteTextures)
6181 * and should clear down the context and set it up according to pPresentationParameters
6182 ***********************************************************/
6183 FIXME("(%p) : stub\n", This);
6184 return D3D_OK;
6187 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
6188 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6189 /** FIXME: always true at the moment **/
6190 if(bEnableDialogs == FALSE) {
6191 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
6193 return D3D_OK;
6197 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
6198 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6200 FIXME("(%p) : stub\n", This);
6201 /* Setup some reasonable defaults */
6202 pParameters->AdapterOrdinal = 0; /* always for now */
6203 pParameters->DeviceType = D3DDEVTYPE_HAL; /* always for now */
6204 pParameters->hFocusWindow = 0;
6205 pParameters->BehaviorFlags =0;
6206 return D3D_OK;
6209 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
6210 IWineD3DSwapChain *swapchain;
6211 HRESULT hrc = D3D_OK;
6213 TRACE("Relaying to swapchain\n");
6215 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
6216 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (D3DGAMMARAMP *)pRamp);
6217 IWineD3DSwapChain_Release(swapchain);
6219 return;
6222 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
6223 IWineD3DSwapChain *swapchain;
6224 HRESULT hrc = D3D_OK;
6226 TRACE("Relaying to swapchain\n");
6228 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
6229 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
6230 IWineD3DSwapChain_Release(swapchain);
6232 return;
6236 /** ********************************************************
6237 * Notification functions
6238 ** ********************************************************/
6239 /** This function must be called in the release of a resource when ref == 0,
6240 * the contents of resource must still be correct,
6241 * any handels to other resource held by the caller must be closed
6242 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
6243 *****************************************************/
6244 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6245 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6246 ResourceList* resourceList;
6248 TRACE("(%p) : resource %p\n", This, resource);
6249 #if 0
6250 EnterCriticalSection(&resourceStoreCriticalSection);
6251 #endif
6252 /* add a new texture to the frot of the linked list */
6253 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
6254 resourceList->resource = resource;
6256 /* Get the old head */
6257 resourceList->next = This->resources;
6259 This->resources = resourceList;
6260 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
6262 #if 0
6263 LeaveCriticalSection(&resourceStoreCriticalSection);
6264 #endif
6265 return;
6268 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6269 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6270 ResourceList* resourceList = NULL;
6271 ResourceList* previousResourceList = NULL;
6273 TRACE("(%p) : resource %p\n", This, resource);
6275 #if 0
6276 EnterCriticalSection(&resourceStoreCriticalSection);
6277 #endif
6278 resourceList = This->resources;
6280 while (resourceList != NULL) {
6281 if(resourceList->resource == resource) break;
6282 previousResourceList = resourceList;
6283 resourceList = resourceList->next;
6286 if (resourceList == NULL) {
6287 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
6288 #if 0
6289 LeaveCriticalSection(&resourceStoreCriticalSection);
6290 #endif
6291 return;
6292 } else {
6293 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
6295 /* make sure we don't leave a hole in the list */
6296 if (previousResourceList != NULL) {
6297 previousResourceList->next = resourceList->next;
6298 } else {
6299 This->resources = resourceList->next;
6302 #if 0
6303 LeaveCriticalSection(&resourceStoreCriticalSection);
6304 #endif
6305 return;
6309 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
6310 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6311 int counter;
6313 TRACE("(%p) : resource %p\n", This, resource);
6314 switch(IWineD3DResource_GetType(resource)){
6315 case D3DRTYPE_SURFACE:
6316 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
6317 break;
6318 case D3DRTYPE_TEXTURE:
6319 case D3DRTYPE_CUBETEXTURE:
6320 case D3DRTYPE_VOLUMETEXTURE:
6321 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
6322 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6323 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6324 This->stateBlock->textures[counter] = NULL;
6326 if (This->updateStateBlock != This->stateBlock ){
6327 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6328 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6329 This->updateStateBlock->textures[counter] = NULL;
6333 break;
6334 case D3DRTYPE_VOLUME:
6335 /* TODO: nothing really? */
6336 break;
6337 case D3DRTYPE_VERTEXBUFFER:
6338 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
6340 int streamNumber;
6341 TRACE("Cleaning up stream pointers\n");
6343 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
6344 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
6345 FINDOUT: should changes.streamSource[StreamNumber] be set ?
6347 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6348 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
6349 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
6350 This->updateStateBlock->streamSource[streamNumber] = 0;
6351 /* Set changed flag? */
6354 if (This->stateBlock != NULL ) { /* only happens if there is an error in the application, or on reset/release (because we don't manage internal tracking properly) */
6355 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
6356 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
6357 This->stateBlock->streamSource[streamNumber] = 0;
6360 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
6361 else { /* This shouldn't happen */
6362 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
6364 #endif
6368 break;
6369 case D3DRTYPE_INDEXBUFFER:
6370 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
6371 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6372 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6373 This->updateStateBlock->pIndexData = NULL;
6376 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
6377 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6378 This->stateBlock->pIndexData = NULL;
6382 break;
6383 default:
6384 FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
6385 break;
6389 /* Remove the resoruce from the resourceStore */
6390 IWineD3DDeviceImpl_RemoveResource(iface, resource);
6392 TRACE("Resource released\n");
6397 /** This function is to be called by the swapchain when it is released and it's ref = 0
6398 *****************************************************/
6399 void WINAPI IWineD3DDeviceImpl_SwapChainReleased(IWineD3DDevice *iface, IWineD3DSwapChain *swapChain){
6400 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6401 SwapChainList **nextSwapchain;
6402 nextSwapchain = &This->swapchains;
6404 /* Check to see if the swapchian is being used as the render target */
6405 if (This->renderTarget != NULL) {
6406 IWineD3DSurface *swapchainBackBuffer;
6408 IWineD3DSwapChain_GetBackBuffer(swapChain, 0 ,( D3DBACKBUFFER_TYPE) 0, &swapchainBackBuffer);
6409 if (This->renderTarget == swapchainBackBuffer) {
6410 /* Don't know what to do, so warn and carry on as usual (which in this case leaves the renderterget in limbo) */
6411 FIXME("Atempting to release a swapchain that is currently beuing used as a render target, behaviour is undefined\n");
6415 /* Go through the swapchain list and try to find the swapchain being released */
6416 while(*nextSwapchain != NULL && (*nextSwapchain)->swapchain != swapChain) {
6417 nextSwapchain = &(*nextSwapchain)->next;
6420 /* Check to see if we found the swapchain */
6421 if (NULL != *nextSwapchain) {
6422 /* We found the swapchain so remove it from the list */
6423 TRACE("(%p) releasing swapchain(%p)\n", iface, swapChain);
6424 HeapFree(GetProcessHeap(), 0 , *nextSwapchain);
6425 *nextSwapchain = (*nextSwapchain)->next;
6426 } else {
6427 /* We didn't find the swapchain on the list, this can only heppen because of a programming error in wined3d */
6428 FIXME("(%p) Attempting to release a swapchain (%p) that hasn't been stored\n", iface, swapChain);
6431 TRACE("swapchain (%p) released\n", swapChain);
6432 return;
6435 /**********************************************************
6436 * IWineD3DDevice VTbl follows
6437 **********************************************************/
6439 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
6441 /*** IUnknown methods ***/
6442 IWineD3DDeviceImpl_QueryInterface,
6443 IWineD3DDeviceImpl_AddRef,
6444 IWineD3DDeviceImpl_Release,
6445 /*** IWineD3DDevice methods ***/
6446 IWineD3DDeviceImpl_GetParent,
6447 /*** Creation methods**/
6448 IWineD3DDeviceImpl_CreateVertexBuffer,
6449 IWineD3DDeviceImpl_CreateIndexBuffer,
6450 IWineD3DDeviceImpl_CreateStateBlock,
6451 IWineD3DDeviceImpl_CreateSurface,
6452 IWineD3DDeviceImpl_CreateTexture,
6453 IWineD3DDeviceImpl_CreateVolumeTexture,
6454 IWineD3DDeviceImpl_CreateVolume,
6455 IWineD3DDeviceImpl_CreateCubeTexture,
6456 IWineD3DDeviceImpl_CreateQuery,
6457 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
6458 IWineD3DDeviceImpl_CreateVertexDeclaration,
6459 IWineD3DDeviceImpl_CreateVertexShader,
6460 IWineD3DDeviceImpl_CreatePixelShader,
6461 /*** Odd functions **/
6462 IWineD3DDeviceImpl_EvictManagedResources,
6463 IWineD3DDeviceImpl_GetAvailableTextureMem,
6464 IWineD3DDeviceImpl_GetBackBuffer,
6465 IWineD3DDeviceImpl_GetCreationParameters,
6466 IWineD3DDeviceImpl_GetDeviceCaps,
6467 IWineD3DDeviceImpl_GetDirect3D,
6468 IWineD3DDeviceImpl_GetDisplayMode,
6469 IWineD3DDeviceImpl_GetNumberOfSwapChains,
6470 IWineD3DDeviceImpl_GetRasterStatus,
6471 IWineD3DDeviceImpl_GetSwapChain,
6472 IWineD3DDeviceImpl_Reset,
6473 IWineD3DDeviceImpl_SetDialogBoxMode,
6474 IWineD3DDeviceImpl_SetCursorProperties,
6475 IWineD3DDeviceImpl_SetCursorPosition,
6476 IWineD3DDeviceImpl_ShowCursor,
6477 IWineD3DDeviceImpl_TestCooperativeLevel,
6478 /*** Getters and setters **/
6479 IWineD3DDeviceImpl_SetClipPlane,
6480 IWineD3DDeviceImpl_GetClipPlane,
6481 IWineD3DDeviceImpl_SetClipStatus,
6482 IWineD3DDeviceImpl_GetClipStatus,
6483 IWineD3DDeviceImpl_SetCurrentTexturePalette,
6484 IWineD3DDeviceImpl_GetCurrentTexturePalette,
6485 IWineD3DDeviceImpl_SetDepthStencilSurface,
6486 IWineD3DDeviceImpl_GetDepthStencilSurface,
6487 IWineD3DDeviceImpl_SetFVF,
6488 IWineD3DDeviceImpl_GetFVF,
6489 IWineD3DDeviceImpl_SetGammaRamp,
6490 IWineD3DDeviceImpl_GetGammaRamp,
6491 IWineD3DDeviceImpl_SetIndices,
6492 IWineD3DDeviceImpl_GetIndices,
6493 IWineD3DDeviceImpl_SetLight,
6494 IWineD3DDeviceImpl_GetLight,
6495 IWineD3DDeviceImpl_SetLightEnable,
6496 IWineD3DDeviceImpl_GetLightEnable,
6497 IWineD3DDeviceImpl_SetMaterial,
6498 IWineD3DDeviceImpl_GetMaterial,
6499 IWineD3DDeviceImpl_SetNPatchMode,
6500 IWineD3DDeviceImpl_GetNPatchMode,
6501 IWineD3DDeviceImpl_SetPaletteEntries,
6502 IWineD3DDeviceImpl_GetPaletteEntries,
6503 IWineD3DDeviceImpl_SetPixelShader,
6504 IWineD3DDeviceImpl_GetPixelShader,
6505 IWineD3DDeviceImpl_SetPixelShaderConstant,
6506 IWineD3DDeviceImpl_GetPixelShaderConstant,
6507 IWineD3DDeviceImpl_SetPixelShaderConstantB,
6508 IWineD3DDeviceImpl_GetPixelShaderConstantB,
6509 IWineD3DDeviceImpl_SetPixelShaderConstantI,
6510 IWineD3DDeviceImpl_GetPixelShaderConstantI,
6511 IWineD3DDeviceImpl_SetPixelShaderConstantF,
6512 IWineD3DDeviceImpl_GetPixelShaderConstantF,
6513 IWineD3DDeviceImpl_SetPixelShaderConstantN,
6514 IWineD3DDeviceImpl_SetRenderState,
6515 IWineD3DDeviceImpl_GetRenderState,
6516 IWineD3DDeviceImpl_SetRenderTarget,
6517 IWineD3DDeviceImpl_GetRenderTarget,
6518 IWineD3DDeviceImpl_SetSamplerState,
6519 IWineD3DDeviceImpl_GetSamplerState,
6520 IWineD3DDeviceImpl_SetScissorRect,
6521 IWineD3DDeviceImpl_GetScissorRect,
6522 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
6523 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
6524 IWineD3DDeviceImpl_SetStreamSource,
6525 IWineD3DDeviceImpl_GetStreamSource,
6526 IWineD3DDeviceImpl_SetStreamSourceFreq,
6527 IWineD3DDeviceImpl_GetStreamSourceFreq,
6528 IWineD3DDeviceImpl_SetTexture,
6529 IWineD3DDeviceImpl_GetTexture,
6530 IWineD3DDeviceImpl_SetTextureStageState,
6531 IWineD3DDeviceImpl_GetTextureStageState,
6532 IWineD3DDeviceImpl_SetTransform,
6533 IWineD3DDeviceImpl_GetTransform,
6534 IWineD3DDeviceImpl_SetVertexDeclaration,
6535 IWineD3DDeviceImpl_GetVertexDeclaration,
6536 IWineD3DDeviceImpl_SetVertexShader,
6537 IWineD3DDeviceImpl_GetVertexShader,
6538 IWineD3DDeviceImpl_SetVertexShaderConstant,
6539 IWineD3DDeviceImpl_GetVertexShaderConstant,
6540 IWineD3DDeviceImpl_SetVertexShaderConstantB,
6541 IWineD3DDeviceImpl_GetVertexShaderConstantB,
6542 IWineD3DDeviceImpl_SetVertexShaderConstantI,
6543 IWineD3DDeviceImpl_GetVertexShaderConstantI,
6544 IWineD3DDeviceImpl_SetVertexShaderConstantF,
6545 IWineD3DDeviceImpl_GetVertexShaderConstantF,
6546 IWineD3DDeviceImpl_SetVertexShaderConstantN,
6547 IWineD3DDeviceImpl_SetViewport,
6548 IWineD3DDeviceImpl_GetViewport,
6549 IWineD3DDeviceImpl_MultiplyTransform,
6550 IWineD3DDeviceImpl_ValidateDevice,
6551 IWineD3DDeviceImpl_ProcessVertices,
6552 /*** State block ***/
6553 IWineD3DDeviceImpl_BeginStateBlock,
6554 IWineD3DDeviceImpl_EndStateBlock,
6555 /*** Scene management ***/
6556 IWineD3DDeviceImpl_BeginScene,
6557 IWineD3DDeviceImpl_EndScene,
6558 IWineD3DDeviceImpl_Present,
6559 IWineD3DDeviceImpl_Clear,
6560 /*** Drawing ***/
6561 IWineD3DDeviceImpl_DrawPrimitive,
6562 IWineD3DDeviceImpl_DrawIndexedPrimitive,
6563 IWineD3DDeviceImpl_DrawPrimitiveUP,
6564 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
6565 IWineD3DDeviceImpl_DrawRectPatch,
6566 IWineD3DDeviceImpl_DrawTriPatch,
6567 IWineD3DDeviceImpl_DeletePatch,
6568 IWineD3DDeviceImpl_ColorFill,
6569 IWineD3DDeviceImpl_UpdateTexture,
6570 IWineD3DDeviceImpl_UpdateSurface,
6571 IWineD3DDeviceImpl_StretchRect,
6572 IWineD3DDeviceImpl_GetRenderTargetData,
6573 IWineD3DDeviceImpl_GetFrontBufferData,
6574 /*** Internal use IWineD3DDevice methods ***/
6575 IWineD3DDeviceImpl_SetupTextureStates,
6576 /*** object tracking ***/
6577 IWineD3DDeviceImpl_SwapChainReleased,
6578 IWineD3DDeviceImpl_ResourceReleased
6582 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
6583 WINED3DRS_ALPHABLENDENABLE ,
6584 WINED3DRS_ALPHAFUNC ,
6585 WINED3DRS_ALPHAREF ,
6586 WINED3DRS_ALPHATESTENABLE ,
6587 WINED3DRS_BLENDOP ,
6588 WINED3DRS_COLORWRITEENABLE ,
6589 WINED3DRS_DESTBLEND ,
6590 WINED3DRS_DITHERENABLE ,
6591 WINED3DRS_FILLMODE ,
6592 WINED3DRS_FOGDENSITY ,
6593 WINED3DRS_FOGEND ,
6594 WINED3DRS_FOGSTART ,
6595 WINED3DRS_LASTPIXEL ,
6596 WINED3DRS_SHADEMODE ,
6597 WINED3DRS_SRCBLEND ,
6598 WINED3DRS_STENCILENABLE ,
6599 WINED3DRS_STENCILFAIL ,
6600 WINED3DRS_STENCILFUNC ,
6601 WINED3DRS_STENCILMASK ,
6602 WINED3DRS_STENCILPASS ,
6603 WINED3DRS_STENCILREF ,
6604 WINED3DRS_STENCILWRITEMASK ,
6605 WINED3DRS_STENCILZFAIL ,
6606 WINED3DRS_TEXTUREFACTOR ,
6607 WINED3DRS_WRAP0 ,
6608 WINED3DRS_WRAP1 ,
6609 WINED3DRS_WRAP2 ,
6610 WINED3DRS_WRAP3 ,
6611 WINED3DRS_WRAP4 ,
6612 WINED3DRS_WRAP5 ,
6613 WINED3DRS_WRAP6 ,
6614 WINED3DRS_WRAP7 ,
6615 WINED3DRS_ZENABLE ,
6616 WINED3DRS_ZFUNC ,
6617 WINED3DRS_ZWRITEENABLE
6620 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
6621 WINED3DTSS_ADDRESSW ,
6622 WINED3DTSS_ALPHAARG0 ,
6623 WINED3DTSS_ALPHAARG1 ,
6624 WINED3DTSS_ALPHAARG2 ,
6625 WINED3DTSS_ALPHAOP ,
6626 WINED3DTSS_BUMPENVLOFFSET ,
6627 WINED3DTSS_BUMPENVLSCALE ,
6628 WINED3DTSS_BUMPENVMAT00 ,
6629 WINED3DTSS_BUMPENVMAT01 ,
6630 WINED3DTSS_BUMPENVMAT10 ,
6631 WINED3DTSS_BUMPENVMAT11 ,
6632 WINED3DTSS_COLORARG0 ,
6633 WINED3DTSS_COLORARG1 ,
6634 WINED3DTSS_COLORARG2 ,
6635 WINED3DTSS_COLOROP ,
6636 WINED3DTSS_RESULTARG ,
6637 WINED3DTSS_TEXCOORDINDEX ,
6638 WINED3DTSS_TEXTURETRANSFORMFLAGS
6641 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
6642 WINED3DSAMP_ADDRESSU ,
6643 WINED3DSAMP_ADDRESSV ,
6644 WINED3DSAMP_ADDRESSW ,
6645 WINED3DSAMP_BORDERCOLOR ,
6646 WINED3DSAMP_MAGFILTER ,
6647 WINED3DSAMP_MINFILTER ,
6648 WINED3DSAMP_MIPFILTER ,
6649 WINED3DSAMP_MIPMAPLODBIAS ,
6650 WINED3DSAMP_MAXMIPLEVEL ,
6651 WINED3DSAMP_MAXANISOTROPY ,
6652 WINED3DSAMP_SRGBTEXTURE ,
6653 WINED3DSAMP_ELEMENTINDEX
6656 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
6657 WINED3DRS_AMBIENT ,
6658 WINED3DRS_AMBIENTMATERIALSOURCE ,
6659 WINED3DRS_CLIPPING ,
6660 WINED3DRS_CLIPPLANEENABLE ,
6661 WINED3DRS_COLORVERTEX ,
6662 WINED3DRS_DIFFUSEMATERIALSOURCE ,
6663 WINED3DRS_EMISSIVEMATERIALSOURCE ,
6664 WINED3DRS_FOGDENSITY ,
6665 WINED3DRS_FOGEND ,
6666 WINED3DRS_FOGSTART ,
6667 WINED3DRS_FOGTABLEMODE ,
6668 WINED3DRS_FOGVERTEXMODE ,
6669 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
6670 WINED3DRS_LIGHTING ,
6671 WINED3DRS_LOCALVIEWER ,
6672 WINED3DRS_MULTISAMPLEANTIALIAS ,
6673 WINED3DRS_MULTISAMPLEMASK ,
6674 WINED3DRS_NORMALIZENORMALS ,
6675 WINED3DRS_PATCHEDGESTYLE ,
6676 WINED3DRS_POINTSCALE_A ,
6677 WINED3DRS_POINTSCALE_B ,
6678 WINED3DRS_POINTSCALE_C ,
6679 WINED3DRS_POINTSCALEENABLE ,
6680 WINED3DRS_POINTSIZE ,
6681 WINED3DRS_POINTSIZE_MAX ,
6682 WINED3DRS_POINTSIZE_MIN ,
6683 WINED3DRS_POINTSPRITEENABLE ,
6684 WINED3DRS_RANGEFOGENABLE ,
6685 WINED3DRS_SPECULARMATERIALSOURCE ,
6686 WINED3DRS_TWEENFACTOR ,
6687 WINED3DRS_VERTEXBLEND
6690 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
6691 WINED3DTSS_TEXCOORDINDEX ,
6692 WINED3DTSS_TEXTURETRANSFORMFLAGS
6695 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
6696 WINED3DSAMP_DMAPOFFSET