2 * IWineD3DDevice implementation
4 * Copyright 2002-2005 Jason Edmeades
5 * Copyright 2003-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include "wined3d_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
31 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
33 /* x11drv GDI escapes */
34 #define X11DRV_ESCAPE 6789
35 enum x11drv_escape_codes
37 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
38 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
39 X11DRV_GET_FONT, /* get current X font for a DC */
42 /* retrieve the X display to use on a given DC */
43 inline static Display *get_display( HDC hdc )
46 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
48 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
49 sizeof(display), (LPSTR)&display )) display = NULL;
53 /* Memory tracking and object counting */
54 static unsigned int emulated_textureram = 64*1024*1024;
56 /* TODO: setup some flags in the regestry to enable, disable pbuffer support */
57 /* enable pbuffer support for offscreen textures */
58 BOOL pbuffer_support = FALSE;
59 /* allocate one pbuffer per surface */
60 BOOL pbuffer_per_surface = FALSE;
62 /* static function declarations */
63 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
65 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type);
68 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return D3DERR_OUTOFVIDEOMEMORY;}
70 #define D3DCREATEOBJECTINSTANCE(object, type) { \
71 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
72 D3DMEMCHECK(object, pp##type); \
73 object->lpVtbl = &IWineD3D##type##_Vtbl; \
74 object->wineD3DDevice = This; \
75 object->parent = parent; \
77 *pp##type = (IWineD3D##type *) object; \
80 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
81 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
82 D3DMEMCHECK(object, pp##type); \
83 object->lpVtbl = &IWineD3D##type##_Vtbl; \
84 object->resource.wineD3DDevice = This; \
85 object->resource.parent = parent; \
86 object->resource.resourceType = d3dtype; \
87 object->resource.ref = 1; \
88 object->resource.pool = Pool; \
89 object->resource.format = Format; \
90 object->resource.usage = Usage; \
91 object->resource.size = _size; \
92 /* Check that we have enough video ram left */ \
93 if (Pool == D3DPOOL_DEFAULT) { \
94 if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
95 WARN("Out of 'bogus' video memory\n"); \
96 HeapFree(GetProcessHeap(), 0, object); \
98 return D3DERR_OUTOFVIDEOMEMORY; \
100 globalChangeGlRam(_size); \
102 object->resource.allocatedMemory = (0 == _size ? NULL : Pool == D3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
103 if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != D3DPOOL_DEFAULT) { \
104 FIXME("Out of memory!\n"); \
105 HeapFree(GetProcessHeap(), 0, object); \
107 return D3DERR_OUTOFVIDEOMEMORY; \
109 *pp##type = (IWineD3D##type *) object; \
110 IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
111 TRACE("(%p) : Created resource %p\n", This, object); \
114 #define D3DINITIALIZEBASETEXTURE(_basetexture) { \
115 _basetexture.levels = Levels; \
116 _basetexture.filterType = (Usage & D3DUSAGE_AUTOGENMIPMAP) ? D3DTEXF_LINEAR : D3DTEXF_NONE; \
117 _basetexture.LOD = 0; \
118 _basetexture.dirty = TRUE; \
121 /**********************************************************
122 * Global variable / Constants follow
123 **********************************************************/
124 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
126 /**********************************************************
127 * Utility functions follow
128 **********************************************************/
129 /* Convert the D3DLIGHT properties into equivalent gl lights */
130 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
133 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
134 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
136 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
137 glMatrixMode(GL_MODELVIEW);
139 glLoadMatrixf((float *)&This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
142 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
143 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
144 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
145 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
146 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
147 checkGLcall("glLightfv");
150 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
151 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
152 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
153 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
154 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
155 checkGLcall("glLightfv");
158 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
159 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
160 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
161 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
162 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
163 checkGLcall("glLightfv");
165 /* Attenuation - Are these right? guessing... */
166 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
167 checkGLcall("glLightf");
168 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
169 checkGLcall("glLightf");
171 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
172 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
174 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
177 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
178 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
179 checkGLcall("glLightf");
181 switch (lightInfo->OriginalParms.Type) {
184 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
185 checkGLcall("glLightfv");
186 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
187 checkGLcall("glLightf");
193 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
194 checkGLcall("glLightfv");
196 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
197 checkGLcall("glLightfv");
198 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
199 checkGLcall("glLightf");
200 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
201 checkGLcall("glLightf");
205 case D3DLIGHT_DIRECTIONAL:
207 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
208 checkGLcall("glLightfv");
209 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
210 checkGLcall("glLightf");
211 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
212 checkGLcall("glLightf");
216 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
219 /* Restore the modelview matrix */
223 /* Apply the current values to the specified texture stage */
224 void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Sampler, DWORD Flags) {
225 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
233 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
234 clamping, MIPLOD, etc. This will work for up to 16 samplers.
237 if (Sampler >= GL_LIMITS(samplers)) {
238 FIXME("Trying to set the state of more samplers %ld than are supported %d by this openGL implementation\n", Sampler, GL_LIMITS(samplers));
241 VTRACE(("Activating appropriate texture state %ld\n", Sampler));
242 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
244 GLACTIVETEXTURE(Sampler);
246 /* Could we use bindTexture and then apply the states instead of GLACTIVETEXTURE */
247 } else if (Sampler > 0) {
248 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
252 /* TODO: change this to a lookup table
253 LOOKUP_TEXTURE_STATES lists all texture states that should be applied.
254 LOOKUP_CONTEXT_SATES list all context applicable states that can be applied
255 etc.... it's a lot cleaner, quicker and possibly easier to maintain than running a switch and setting a skip flag...
256 especially when there are a number of groups of states. */
258 TRACE("-----------------------> Updating the texture at Sampler %ld to have new texture state information\n", Sampler);
260 /* The list of states not to apply is a big as the list of states to apply, so it makes sense to produce an inclusive list */
261 #define APPLY_STATE(_state) IWineD3DDeviceImpl_ApplyTextureUnitState(iface, Sampler, _state)
262 /* these are the only two supported states that need to be applied */
263 APPLY_STATE(WINED3DTSS_TEXCOORDINDEX);
264 APPLY_STATE(WINED3DTSS_TEXTURETRANSFORMFLAGS);
265 #if 0 /* not supported at the moment */
266 APPLY_STATE(WINED3DTSS_BUMPENVMAT00);
267 APPLY_STATE(WINED3DTSS_BUMPENVMAT01);
268 APPLY_STATE(WINED3DTSS_BUMPENVMAT10);
269 APPLY_STATE(WINED3DTSS_BUMPENVMAT11);
270 APPLY_STATE(WINED3DTSS_BUMPENVLSCALE);
271 APPLY_STATE(WINED3DTSS_BUMPENVLOFFSET);
272 APPLY_STATE(WINED3DTSS_RESULTARG);
273 APPLY_STATE(WINED3DTSS_CONSTANT);
275 /* a quick sanity check in case someone forgot to update this function */
276 if (WINED3D_HIGHEST_TEXTURE_STATE > WINED3DTSS_CONSTANT) {
277 FIXME("(%p) : There are more texture states than expected, update device.c to match\n", This);
281 /* apply any sampler states that always need applying */
282 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
283 tmpvalue.d = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPMAPLODBIAS];
284 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
285 GL_TEXTURE_LOD_BIAS_EXT,
287 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
290 /* Note the D3DRS value applies to all textures, but GL has one
291 * per texture, so apply it now ready to be used!
293 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
294 /* Set the default alpha blend color */
295 glBlendColor(col[0], col[1], col[2], col[3]);
296 checkGLcall("glBlendColor");
298 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
299 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
300 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
302 /* TODO: NV_POINT_SPRITE */
303 if (GL_SUPPORT(ARB_POINT_SPRITE)) {
304 if (This->stateBlock->renderState[WINED3DRS_POINTSPRITEENABLE] != FALSE) {
305 /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
306 glDisable(GL_POINT_SMOOTH);
308 /* Centre the texture on the vertex */
309 VTRACE("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
310 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
312 VTRACE("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
313 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
314 checkGLcall("glTexEnvf(...)");
315 VTRACE("glEnable( GL_POINT_SPRITE_ARB )\n");
316 glEnable( GL_POINT_SPRITE_ARB );
317 checkGLcall("glEnable(...)");
319 VTRACE("glDisable( GL_POINT_SPRITE_ARB )\n");
320 glDisable( GL_POINT_SPRITE_ARB );
321 checkGLcall("glEnable(...)");
325 TRACE("-----------------------> Updated the texture at Sampler %ld to have new texture state information\n", Sampler);
328 /**********************************************************
329 * IUnknown parts follows
330 **********************************************************/
332 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
334 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
336 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
337 if (IsEqualGUID(riid, &IID_IUnknown)
338 || IsEqualGUID(riid, &IID_IWineD3DBase)
339 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
340 IUnknown_AddRef(iface);
345 return E_NOINTERFACE;
348 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
349 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
350 ULONG refCount = InterlockedIncrement(&This->ref);
352 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
356 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
357 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
358 ULONG refCount = InterlockedDecrement(&This->ref);
360 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
363 /* TODO: Clean up all the surfaces and textures! */
364 /* FIXME: Create targets and state blocks in d3d8 */
365 if (((IWineD3DImpl *)This->wineD3D)->dxVersion > 8) { /*We don't create a state block in d3d8 yet*/
366 /* NOTE: You must release the parent if the object was created via a callback
367 ** ***************************/
368 /* TODO: this is exactly the same as required by _Reset.., so at some point we need to move the code so that is can be called by reset add release... */
369 /* Release all of the swapchains, except the implicit swapchain */
370 IUnknown* stencilBufferParent;
371 IUnknown* swapChainParent;
373 /* NOTE: Don't release swapchain 0 here, it's 'special' */
374 SwapChainList *nextSwapchain = This->swapchains;
375 if (nextSwapchain != NULL) {
376 nextSwapchain = nextSwapchain->next;
378 WARN("Expected to find the implicit swapchain\n");
381 /* release all the other swapchains */
382 while (nextSwapchain != NULL) {
383 SwapChainList *prevSwapchain = nextSwapchain;
384 nextSwapchain = nextSwapchain->next;
385 IWineD3DSwapChain_Release(prevSwapchain->swapchain);
386 /* NOTE: no need to free the list element, it will be done by the release callback
387 HeapFree(GetProcessHeap(), 0, prevSwapchain); */
389 /* Release the buffers (with sanity checks)*/
390 if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
391 if(This->depthStencilBuffer != This->stencilBufferTarget)
392 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
394 This->stencilBufferTarget = NULL;
396 if(IWineD3DSurface_Release(This->renderTarget) >0){
397 /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
399 This->renderTarget = NULL;
401 IWineD3DSurface_GetParent(This->depthStencilBuffer, &stencilBufferParent);
402 IUnknown_Release(stencilBufferParent); /* once for the get parent */
403 if(IUnknown_Release(stencilBufferParent) >0){ /* the second time for when it was created */
404 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
406 This->depthStencilBuffer = NULL;
408 /* Release the update stateblock */
409 if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){
410 if(This->updateStateBlock != This->stateBlock)
411 FIXME("(%p) Something's still holding the Update stateblock\n",This);
413 This->updateStateBlock = NULL;
414 { /* because were not doing proper internal refcounts releasing the primary state block
415 causes recursion with the extra checks in ResourceReleased, to avoid this we have
416 to set this->stateBlock = NULL; first */
417 IWineD3DStateBlock *stateBlock = (IWineD3DStateBlock *)This->stateBlock;
418 This->stateBlock = NULL;
420 /* Release the stateblock */
421 if(IWineD3DStateBlock_Release(stateBlock) > 0){
422 FIXME("(%p) Something's still holding the Update stateblock\n",This);
426 if (This->swapchains != NULL) {
427 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
428 IWineD3DSwapChain_GetParent(This->swapchains->swapchain, &swapChainParent);
429 IUnknown_Release(swapChainParent); /* once for the get parent */
430 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
431 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
435 if (This->resources != NULL ) {
436 FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This);
438 #if 0 /* TODO: Dump a list of all the resources still bound */
439 dumpResources(This->resources);
441 /* TODO: set the resources to a lost state */
445 IWineD3D_Release(This->wineD3D);
446 This->wineD3D = NULL;
447 HeapFree(GetProcessHeap(), 0, This);
448 TRACE("Freed device %p\n", This);
454 /**********************************************************
455 * IWineD3DDevice implementation follows
456 **********************************************************/
457 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
458 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
459 *pParent = This->parent;
460 IUnknown_AddRef(This->parent);
464 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
465 DWORD FVF, D3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
467 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
468 IWineD3DVertexBufferImpl *object;
469 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
470 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, D3DRTYPE_VERTEXBUFFER, Size)
473 if (Pool == D3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
474 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
478 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
479 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
484 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
485 WINED3DFORMAT Format, D3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
486 HANDLE *sharedHandle, IUnknown *parent) {
487 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
488 IWineD3DIndexBufferImpl *object;
489 TRACE("(%p) Creating index buffer\n", This);
491 /* Allocate the storage for the device */
492 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,D3DRTYPE_INDEXBUFFER, Length)
495 if (Pool == D3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
496 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
499 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
500 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
501 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
506 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
508 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
509 IWineD3DStateBlockImpl *object;
512 D3DCREATEOBJECTINSTANCE(object, StateBlock)
513 object->blockType = Type;
515 /* Special case - Used during initialization to produce a placeholder stateblock
516 so other functions called can update a state block */
517 if (Type == WINED3DSBT_INIT) {
518 /* Don't bother increasing the reference count otherwise a device will never
519 be freed due to circular dependencies */
523 /* Otherwise, might as well set the whole state block to the appropriate values */
524 if ( This->stateBlock != NULL) {
525 memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
527 memset(object->streamFreq, 1, sizeof(object->streamFreq));
530 /* Reset the ref and type after kludging it */
531 object->wineD3DDevice = This;
533 object->blockType = Type;
535 TRACE("Updating changed flags appropriate for type %d\n", Type);
537 if (Type == WINED3DSBT_ALL) {
539 TRACE("ALL => Pretend everything has changed\n");
540 memset(&object->changed, TRUE, sizeof(This->stateBlock->changed));
541 } else if (Type == WINED3DSBT_PIXELSTATE) {
543 TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
544 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
546 object->changed.pixelShader = TRUE;
548 /* Pixel Shader Constants */
549 for (i = 0; i < MAX_PSHADER_CONSTANTS; ++i) {
550 object->changed.pixelShaderConstants[i] = TRUE;
552 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
553 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
555 for (j = 0; j < GL_LIMITS(textures); j++) {
556 for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
557 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
560 for (j = 0 ; j < 16; j++) {
561 for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
563 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
567 } else if (Type == WINED3DSBT_VERTEXSTATE) {
569 TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
570 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
572 object->changed.vertexShader = TRUE;
574 /* Vertex Shader Constants */
575 for (i = 0; i < MAX_VSHADER_CONSTANTS; ++i) {
576 object->changed.vertexShaderConstants[i] = TRUE;
578 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
579 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
581 for (j = 0; j < GL_LIMITS(textures); j++) {
582 for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
583 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
586 for (j = 0 ; j < 16; j++){
587 for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
588 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
592 /* Duplicate light chain */
594 PLIGHTINFOEL *src = NULL;
595 PLIGHTINFOEL *dst = NULL;
596 PLIGHTINFOEL *newEl = NULL;
597 src = This->stateBlock->lights;
598 object->lights = NULL;
602 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
603 if (newEl == NULL) return D3DERR_OUTOFVIDEOMEMORY;
604 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
606 newEl->changed = TRUE;
607 newEl->enabledChanged = TRUE;
609 object->lights = newEl;
620 FIXME("Unrecognized state block type %d\n", Type);
623 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
628 /* ************************************
630 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
633 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
635 If this flag is set, the contents of the depth stencil buffer will be invalid after calling either IDirect3DDevice9::Present or IDirect3DDevice9::SetDepthStencilSurface with a different depth surface.
637 ******************************** */
639 HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height, WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **ppSurface,D3DRESOURCETYPE Type, DWORD Usage, D3DPOOL Pool, D3DMULTISAMPLE_TYPE MultiSample ,DWORD MultisampleQuality, HANDLE* pSharedHandle, IUnknown *parent) {
640 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
641 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
642 unsigned int pow2Width, pow2Height;
643 unsigned int Size = 1;
644 TRACE("(%p) Create surface\n",This);
646 /** FIXME: Check ranges on the inputs are valid
649 * [in] Quality level. The valid range is between zero and one less than the level
650 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
651 * Passing a larger value returns the error D3DERR_INVALIDCALL. The MultisampleQuality
652 * values of paired render targets, depth stencil surfaces, and the MultiSample type
654 *******************************/
659 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
661 * If this flag is set, the contents of the depth stencil buffer will be
662 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
663 * with a different depth surface.
665 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
666 ***************************/
668 if(MultisampleQuality < 0) {
669 FIXME("Invalid multisample level %ld\n", MultisampleQuality);
670 return D3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
673 if(MultisampleQuality > 0) {
674 FIXME("MultisampleQuality set to %ld, substituting 0\n", MultisampleQuality);
675 MultisampleQuality=0;
678 /** FIXME: Check that the format is supported
680 *******************************/
682 /* Non-power2 support */
684 /* Find the nearest pow2 match */
685 pow2Width = pow2Height = 1;
686 while (pow2Width < Width) pow2Width <<= 1;
687 while (pow2Height < Height) pow2Height <<= 1;
689 if (pow2Width > Width || pow2Height > Height) {
690 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
691 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
692 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
693 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
694 This, Width, Height);
695 return D3DERR_NOTAVAILABLE;
699 /* D3D8 doesn't use the opengl capability code from WineD3D and because of this the maximum texture size isn't set. */
700 if (((IWineD3DImpl *)This->wineD3D)->dxVersion == 8 && GL_LIMITS(texture_size) == 0) {
702 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
703 GL_LIMITS(texture_size) = gl_max;
706 /** Check against the maximum texture sizes supported by the video card **/
707 if (pow2Width > GL_LIMITS(texture_size) || pow2Height > GL_LIMITS(texture_size)) {
708 /* one of three options
709 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)
710 2: Set the texture to the maxium size (bad idea)
711 3: WARN and return D3DERR_NOTAVAILABLE;
713 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));
714 return D3DERR_NOTAVAILABLE;
719 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
720 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
722 *********************************/
723 if (WINED3DFMT_UNKNOWN == Format) {
725 } else if (Format == WINED3DFMT_DXT1) {
726 /* DXT1 is half byte per pixel */
727 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4)) >> 1;
729 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
730 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
731 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4));
733 Size = (pow2Width * D3DFmtGetBpp(This, Format)) * pow2Height;
736 /** Create and initialise the surface resource **/
737 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,D3DRTYPE_SURFACE, Size)
738 /* "Standalone" surface */
739 IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL);
741 object->currentDesc.Width = Width;
742 object->currentDesc.Height = Height;
743 object->currentDesc.MultiSampleType = MultiSample;
744 object->currentDesc.MultiSampleQuality = MultisampleQuality;
746 /* Setup some glformat defaults */
747 if (WINED3DFMT_UNKNOWN != Format) {
748 object->glDescription.glFormat = D3DFmt2GLFmt(This, object->resource.format);
749 object->glDescription.glFormatInternal = D3DFmt2GLIntFmt(This, object->resource.format);
750 object->glDescription.glType = D3DFmt2GLType(This, object->resource.format);
752 object->glDescription.glFormat = 0;
753 object->glDescription.glFormatInternal = 0;
754 object->glDescription.glType = 0;
757 object->glDescription.textureName = 0;
758 object->glDescription.level = Level;
759 object->glDescription.target = GL_TEXTURE_2D;
762 object->pow2Width = pow2Width;
763 object->pow2Height = pow2Height;
764 object->nonpow2 = (pow2Width != Width || pow2Height != Height) ? TRUE : FALSE;
765 object->discard = Discard;
766 object->activeLock = FALSE;
768 if (WINED3DFMT_UNKNOWN != Format) {
769 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
770 object->pow2Size = (pow2Width * object->bytesPerPixel) * pow2Height;
772 object->bytesPerPixel = 0;
773 object->pow2Size = 0;
776 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
778 TRACE("Pool %d %d %d %d",Pool, D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM);
780 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
781 * this function is too deap to need to care about things like this.
782 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
783 * ****************************************/
785 case D3DPOOL_SCRATCH:
786 if(Lockable == FALSE)
787 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
788 which are mutually exclusive, setting lockable to true\n");
791 case D3DPOOL_SYSTEMMEM:
792 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
793 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
794 case D3DPOOL_MANAGED:
795 if(Usage == D3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
796 Usage of DYNAMIC which are mutually exclusive, not doing \
797 anything just telling you.\n");
799 case D3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
800 if(!(Usage & D3DUSAGE_DYNAMIC) && !(Usage & D3DUSAGE_RENDERTARGET)
801 && !(Usage && D3DUSAGE_DEPTHSTENCIL ) && Lockable == TRUE)
802 FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
805 FIXME("(%p) Unknown pool %d\n", This, Pool);
809 if (Usage & D3DUSAGE_RENDERTARGET && Pool != D3DPOOL_DEFAULT) {
810 FIXME("Trying to create a render target that isn't in the default pool\n");
814 object->locked = FALSE;
815 object->lockable = (WINED3DFMT_D16_LOCKABLE == Format) ? TRUE : Lockable;
817 /* mark the texture as dirty so that it get's loaded first time around*/
818 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
819 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
820 This, Width, Height, Format, debug_d3dformat(Format),
821 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
826 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
827 DWORD Usage, WINED3DFORMAT Format, D3DPOOL Pool,
828 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
829 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
831 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
832 IWineD3DTextureImpl *object;
837 unsigned int pow2Width = Width;
838 unsigned int pow2Height = Height;
841 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) ....\n", This, Width, Height, Levels, Usage);
843 /* TODO: It should only be possible to create textures for formats
844 that are reported as supported */
845 if (WINED3DFMT_UNKNOWN >= Format) {
846 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
847 return D3DERR_INVALIDCALL;
850 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, D3DRTYPE_TEXTURE, 0);
851 D3DINITIALIZEBASETEXTURE(object->baseTexture);
852 object->width = Width;
853 object->height = Height;
855 /** Non-power2 support **/
856 /* Find the nearest pow2 match */
857 pow2Width = pow2Height = 1;
858 while (pow2Width < Width) pow2Width <<= 1;
859 while (pow2Height < Height) pow2Height <<= 1;
861 /** FIXME: add support for real non-power-two if it's provided by the video card **/
862 /* Precalculated scaling for 'faked' non power of two texture coords */
863 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
864 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
865 TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
867 /* Calculate levels for mip mapping */
869 TRACE("calculating levels %d\n", object->baseTexture.levels);
870 object->baseTexture.levels++;
873 while (tmpW > 1 && tmpH > 1) {
874 tmpW = max(1, tmpW >> 1);
875 tmpH = max(1, tmpH >> 1);
876 object->baseTexture.levels++;
878 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
881 /* Generate all the surfaces */
884 for (i = 0; i < object->baseTexture.levels; i++)
886 /* use the callback to create the texture surface */
887 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
890 FIXME("Failed to create surface %p\n", object);
892 for (j = 0 ; j < i ; j++) {
893 IWineD3DSurface_Release(object->surfaces[j]);
895 /* heap free object */
896 HeapFree(GetProcessHeap(), 0, object);
902 IWineD3DSurface_SetContainer(object->surfaces[i], (IWineD3DBase *)object);
903 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
904 /* calculate the next mipmap level */
905 tmpW = max(1, tmpW >> 1);
906 tmpH = max(1, tmpH >> 1);
909 TRACE("(%p) : Created texture %p\n", This, object);
913 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
914 UINT Width, UINT Height, UINT Depth,
915 UINT Levels, DWORD Usage,
916 WINED3DFORMAT Format, D3DPOOL Pool,
917 IWineD3DVolumeTexture **ppVolumeTexture,
918 HANDLE *pSharedHandle, IUnknown *parent,
919 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
921 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
922 IWineD3DVolumeTextureImpl *object;
928 /* TODO: It should only be possible to create textures for formats
929 that are reported as supported */
930 if (WINED3DFMT_UNKNOWN >= Format) {
931 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
932 return D3DERR_INVALIDCALL;
935 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, D3DRTYPE_VOLUMETEXTURE, 0);
936 D3DINITIALIZEBASETEXTURE(object->baseTexture);
938 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
939 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
941 object->width = Width;
942 object->height = Height;
943 object->depth = Depth;
945 /* Calculate levels for mip mapping */
947 object->baseTexture.levels++;
951 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
952 tmpW = max(1, tmpW >> 1);
953 tmpH = max(1, tmpH >> 1);
954 tmpD = max(1, tmpD >> 1);
955 object->baseTexture.levels++;
957 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
960 /* Generate all the surfaces */
965 for (i = 0; i < object->baseTexture.levels; i++)
967 /* Create the volume */
968 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
969 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
971 /* Set it's container to this object */
972 IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)object);
974 /* calcualte the next mipmap level */
975 tmpW = max(1, tmpW >> 1);
976 tmpH = max(1, tmpH >> 1);
977 tmpD = max(1, tmpD >> 1);
980 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
981 TRACE("(%p) : Created volume texture %p\n", This, object);
985 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
986 UINT Width, UINT Height, UINT Depth,
988 WINED3DFORMAT Format, D3DPOOL Pool,
989 IWineD3DVolume** ppVolume,
990 HANDLE* pSharedHandle, IUnknown *parent) {
992 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
993 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
995 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, D3DRTYPE_VOLUME, ((Width * D3DFmtGetBpp(This, Format)) * Height * Depth))
997 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
998 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
1000 object->currentDesc.Width = Width;
1001 object->currentDesc.Height = Height;
1002 object->currentDesc.Depth = Depth;
1003 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
1005 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
1006 object->lockable = TRUE;
1007 object->locked = FALSE;
1008 memset(&object->lockedBox, 0, sizeof(D3DBOX));
1009 object->dirty = TRUE;
1011 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
1014 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
1015 UINT Levels, DWORD Usage,
1016 WINED3DFORMAT Format, D3DPOOL Pool,
1017 IWineD3DCubeTexture **ppCubeTexture,
1018 HANDLE *pSharedHandle, IUnknown *parent,
1019 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1021 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1022 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1026 unsigned int pow2EdgeLength = EdgeLength;
1028 /* TODO: It should only be possible to create textures for formats
1029 that are reported as supported */
1030 if (WINED3DFMT_UNKNOWN >= Format) {
1031 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
1032 return D3DERR_INVALIDCALL;
1035 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, D3DRTYPE_CUBETEXTURE, 0);
1036 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1038 TRACE("(%p) Create Cube Texture\n", This);
1040 /** Non-power2 support **/
1042 /* Find the nearest pow2 match */
1044 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
1046 object->edgeLength = EdgeLength;
1047 /* TODO: support for native non-power 2 */
1048 /* Precalculated scaling for 'faked' non power of two texture coords */
1049 object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
1051 /* Calculate levels for mip mapping */
1053 object->baseTexture.levels++;
1056 tmpW = max(1, tmpW >> 1);
1057 object->baseTexture.levels++;
1059 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1062 /* Generate all the surfaces */
1064 for (i = 0; i < object->baseTexture.levels; i++) {
1066 /* Create the 6 faces */
1067 for (j = 0; j < 6; j++) {
1069 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
1070 i /* Level */, &object->surfaces[j][i],pSharedHandle);
1076 for (l = 0; l < j; l++) {
1077 IWineD3DSurface_Release(object->surfaces[j][i]);
1079 for (k = 0; k < i; k++) {
1080 for (l = 0; l < 6; l++) {
1081 IWineD3DSurface_Release(object->surfaces[l][j]);
1085 FIXME("(%p) Failed to create surface\n",object);
1086 HeapFree(GetProcessHeap(),0,object);
1087 *ppCubeTexture = NULL;
1090 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IWineD3DBase *)object);
1091 TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1093 tmpW = max(1, tmpW >> 1);
1096 TRACE("(%p) : Created Cube Texture %p\n", This, object);
1097 *ppCubeTexture = (IWineD3DCubeTexture *) object;
1101 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1102 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1103 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1105 if (NULL == ppQuery) {
1106 /* Just a check to see if we support this type of query */
1107 HRESULT hr = D3DERR_NOTAVAILABLE;
1109 case WINED3DQUERYTYPE_OCCLUSION:
1110 TRACE("(%p) occlusion query\n", This);
1111 if (GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY))
1114 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1116 case WINED3DQUERYTYPE_VCACHE:
1117 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1118 case WINED3DQUERYTYPE_VERTEXSTATS:
1119 case WINED3DQUERYTYPE_EVENT:
1120 case WINED3DQUERYTYPE_TIMESTAMP:
1121 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1122 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1123 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1124 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1125 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1126 case WINED3DQUERYTYPE_PIXELTIMINGS:
1127 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1128 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1130 FIXME("(%p) Unhandled query type %d\n", This, Type);
1135 D3DCREATEOBJECTINSTANCE(object, Query)
1136 object->type = Type;
1137 /* allocated the 'extended' data based on the type of query requested */
1139 case D3DQUERYTYPE_OCCLUSION:
1140 if(GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY)) {
1141 TRACE("(%p) Allocating data for an occlusion query\n", This);
1142 object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1145 case D3DQUERYTYPE_VCACHE:
1146 case D3DQUERYTYPE_RESOURCEMANAGER:
1147 case D3DQUERYTYPE_VERTEXSTATS:
1148 case D3DQUERYTYPE_EVENT:
1149 case D3DQUERYTYPE_TIMESTAMP:
1150 case D3DQUERYTYPE_TIMESTAMPDISJOINT:
1151 case D3DQUERYTYPE_TIMESTAMPFREQ:
1152 case D3DQUERYTYPE_PIPELINETIMINGS:
1153 case D3DQUERYTYPE_INTERFACETIMINGS:
1154 case D3DQUERYTYPE_VERTEXTIMINGS:
1155 case D3DQUERYTYPE_PIXELTIMINGS:
1156 case D3DQUERYTYPE_BANDWIDTHTIMINGS:
1157 case D3DQUERYTYPE_CACHEUTILIZATION:
1159 object->extendedData = 0;
1160 FIXME("(%p) Unhandled query type %d\n",This , Type);
1162 TRACE("(%p) : Created Query %p\n", This, object);
1166 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1167 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1169 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1170 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1171 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1174 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1176 XVisualInfo template;
1177 GLXContext oldContext;
1178 Drawable oldDrawable;
1179 HRESULT hr = D3D_OK;
1181 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1183 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1184 * does a device hold a reference to a swap chain giving them a lifetime of the device
1185 * or does the swap chain notify the device of its destruction.
1186 *******************************/
1188 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1190 /* Initialize other useful values */
1191 object->presentParms.BackBufferCount = 1; /* TODO:? support for gl_aux buffers */
1193 /*********************
1194 * Lookup the window Handle and the relating X window handle
1195 ********************/
1197 /* Setup hwnd we are using, plus which display this equates to */
1198 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1199 if (!object->win_handle) {
1200 object->win_handle = This->createParms.hFocusWindow;
1203 object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window" );
1204 hDc = GetDC(object->win_handle);
1205 object->display = get_display(hDc);
1206 ReleaseDC(object->win_handle, hDc);
1207 TRACE("Using a display of %p %p\n", object->display, hDc);
1209 if (NULL == object->display || NULL == hDc) {
1210 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1211 return D3DERR_NOTAVAILABLE;
1214 if (object->win == 0) {
1215 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1216 return D3DERR_NOTAVAILABLE;
1219 * Create an opengl context for the display visual
1220 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1221 * use different properties after that point in time. FIXME: How to handle when requested format
1222 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1223 * it chooses is identical to the one already being used!
1224 **********************************/
1226 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1229 /* Create a new context for this swapchain */
1230 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1231 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1232 (or the best possible if none is requested) */
1233 TRACE("Found x visual ID : %ld\n", template.visualid);
1235 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1236 if (NULL == object->visInfo) {
1237 ERR("cannot really get XVisual\n");
1239 return D3DERR_NOTAVAILABLE;
1242 /* Write out some debug info about the visual/s */
1243 TRACE("Using x visual ID : %ld\n", template.visualid);
1244 TRACE(" visual info: %p\n", object->visInfo);
1245 TRACE(" num items : %d\n", num);
1246 for (n = 0;n < num; n++) {
1247 TRACE("=====item=====: %d\n", n + 1);
1248 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1249 TRACE(" screen : %d\n", object->visInfo[n].screen);
1250 TRACE(" depth : %u\n", object->visInfo[n].depth);
1251 TRACE(" class : %d\n", object->visInfo[n].class);
1252 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1253 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1254 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1255 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1256 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1257 /* log some extra glx info */
1258 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1259 TRACE(" gl_aux_buffers : %d\n", value);
1260 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1261 TRACE(" gl_buffer_size : %d\n", value);
1262 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1263 TRACE(" gl_red_size : %d\n", value);
1264 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1265 TRACE(" gl_green_size : %d\n", value);
1266 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1267 TRACE(" gl_blue_size : %d\n", value);
1268 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1269 TRACE(" gl_alpha_size : %d\n", value);
1270 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1271 TRACE(" gl_depth_size : %d\n", value);
1272 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1273 TRACE(" gl_stencil_size : %d\n", value);
1275 /* Now choose a simila visual ID*/
1277 #ifdef USE_CONTEXT_MANAGER
1279 /** TODO: use a context mamager **/
1283 IWineD3DSwapChain *implSwapChain;
1284 if (D3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1285 /* The first time around we create the context that is shared with all other swapchains and render targets */
1286 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1287 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1290 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1291 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1292 /* and create a new context with the implicit swapchains context as the shared context */
1293 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1294 IWineD3DSwapChain_Release(implSwapChain);
1299 XFree(object->visInfo);
1300 object->visInfo = NULL;
1302 if (NULL == object->glCtx) {
1303 ERR("cannot create glxContext\n");
1305 return D3DERR_NOTAVAILABLE;
1309 if (object->glCtx == NULL) {
1310 ERR("Error in context creation !\n");
1311 return D3DERR_INVALIDCALL;
1313 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1314 object->win_handle, object->glCtx, object->win, object->visInfo);
1317 /*********************
1318 * Windowed / Fullscreen
1319 *******************/
1322 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1323 * so we should really check to see if there is a fullscreen swapchain already
1324 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1325 **************************************/
1327 if (!*(pPresentationParameters->Windowed)) {
1333 /* Get info on the current display setup */
1334 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1335 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1338 /* Change the display settings */
1339 memset(&devmode, 0, sizeof(DEVMODEW));
1340 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1341 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1342 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1343 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1344 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1345 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1347 /* Make popup window */
1348 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1349 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1350 *(pPresentationParameters->BackBufferWidth),
1351 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1357 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1358 * then the corresponding dimension of the client area of the hDeviceWindow
1359 * (or the focus window, if hDeviceWindow is NULL) is taken.
1360 **********************/
1362 if (*(pPresentationParameters->Windowed) &&
1363 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1364 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1367 GetClientRect(object->win_handle, &Rect);
1369 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1370 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1371 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1373 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1374 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1375 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1379 /*********************
1380 * finish off parameter initialization
1381 *******************/
1383 /* Put the correct figures in the presentation parameters */
1384 TRACE("Coppying accross presentaion paraneters\n");
1385 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1386 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1387 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1388 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1389 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1390 object->presentParms.MultiSampleQuality = NULL == pPresentationParameters->MultiSampleQuality ? 0 : *(pPresentationParameters->MultiSampleQuality);
1391 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1392 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1393 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1394 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1395 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1396 object->presentParms.Flags = *(pPresentationParameters->Flags);
1397 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1398 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1401 /*********************
1402 * Create the back, front and stencil buffers
1403 *******************/
1404 TRACE("calling rendertarget CB\n");
1405 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1406 object->presentParms.BackBufferWidth,
1407 object->presentParms.BackBufferHeight,
1408 object->presentParms.BackBufferFormat,
1409 object->presentParms.MultiSampleType,
1410 object->presentParms.MultiSampleQuality,
1411 TRUE /* Lockable */,
1412 &object->frontBuffer,
1413 NULL /* pShared (always null)*/);
1414 if (object->frontBuffer != NULL)
1415 IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
1416 TRACE("calling rendertarget CB\n");
1417 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1418 object->presentParms.BackBufferWidth,
1419 object->presentParms.BackBufferHeight,
1420 object->presentParms.BackBufferFormat,
1421 object->presentParms.MultiSampleType,
1422 object->presentParms.MultiSampleQuality,
1423 TRUE /* Lockable */,
1424 &object->backBuffer,
1425 NULL /* pShared (always null)*/);
1426 if (object->backBuffer != NULL)
1427 IWineD3DSurface_SetContainer(object->backBuffer, (IWineD3DBase *)object);
1429 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1430 if (pPresentationParameters->EnableAutoDepthStencil) {
1431 TRACE("Creating depth stencil buffer\n");
1432 if (This->depthStencilBuffer == NULL ) {
1433 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1434 object->presentParms.BackBufferWidth,
1435 object->presentParms.BackBufferHeight,
1436 object->presentParms.AutoDepthStencilFormat,
1437 object->presentParms.MultiSampleType,
1438 object->presentParms.MultiSampleQuality,
1439 FALSE /* FIXME: Discard */,
1440 &This->depthStencilBuffer,
1441 NULL /* pShared (always null)*/ );
1442 if (This->depthStencilBuffer != NULL)
1443 IWineD3DSurface_SetContainer(This->depthStencilBuffer, (IWineD3DBase *)iface);
1446 /** TODO: A check on width, height and multisample types
1447 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1448 ****************************/
1449 object->wantsDepthStencilBuffer = TRUE;
1451 object->wantsDepthStencilBuffer = FALSE;
1454 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1457 /*********************
1458 * init the default renderTarget management
1459 *******************/
1460 object->drawable = object->win;
1461 object->render_ctx = object->glCtx;
1464 /*********************
1465 * Setup some defaults and clear down the buffers
1466 *******************/
1468 /** save current context and drawable **/
1469 oldContext = glXGetCurrentContext();
1470 oldDrawable = glXGetCurrentDrawable();
1472 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1473 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1474 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1476 checkGLcall("glXMakeCurrent");
1478 TRACE("Setting up the screen\n");
1479 /* Clear the screen */
1480 glClearColor(1.0, 0.0, 0.0, 0.0);
1481 checkGLcall("glClearColor");
1484 glClearStencil(0xffff);
1486 checkGLcall("glClear");
1488 glColor3f(1.0, 1.0, 1.0);
1489 checkGLcall("glColor3f");
1491 glEnable(GL_LIGHTING);
1492 checkGLcall("glEnable");
1494 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1495 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1497 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1498 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1500 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1501 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1503 /* switch back to the original context (if there was one)*/
1504 if (This->swapchains != NULL) {
1505 /** TODO: restore the context and drawable **/
1506 glXMakeCurrent(object->display, oldDrawable, oldContext);
1511 { /* Finally add the swapchain to the end of the devices' swapchain list */
1512 SwapChainList **nextSwapchain;
1513 nextSwapchain = &This->swapchains;
1514 while (*nextSwapchain != NULL) {
1515 nextSwapchain = &((*nextSwapchain)->next);
1517 (*nextSwapchain) = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->swapchains));
1518 (*nextSwapchain)->swapchain = (IWineD3DSwapChain *)object;
1520 TRACE("Set swapchain to %p\n", object);
1521 } else { /* something went wrong so clean up */
1522 IUnknown* bufferParent;
1523 if (object->frontBuffer) {
1525 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1526 IUnknown_Release(bufferParent); /* once for the get parent */
1527 if (IUnknown_Release(bufferParent) > 0) {
1528 FIXME("(%p) Something's still holding the front buffer\n",This);
1531 if (object->backBuffer) {
1532 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1533 IUnknown_Release(bufferParent); /* once for the get parent */
1534 if (IUnknown_Release(bufferParent) > 0) {
1535 FIXME("(%p) Something's still holding the back buffer\n",This);
1538 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1539 /* Clean up the context */
1540 /* check that we are the current context first (we shouldn't be though!) */
1541 if (object->glCtx != 0) {
1542 if(glXGetCurrentContext() == object->glCtx) {
1543 glXMakeCurrent(object->display, None, NULL);
1545 glXDestroyContext(object->display, object->glCtx);
1547 HeapFree(GetProcessHeap(), 0, object);
1554 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1555 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1556 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1557 unsigned int numberOfSwapChains = 0;
1558 SwapChainList *swapchain;
1560 swapchain = This->swapchains;
1561 /* itterate through the list to get a count */
1562 while (swapchain != NULL) {
1563 swapchain = swapchain->next;
1564 numberOfSwapChains++;
1567 TRACE("(%p) returning %d\n", This, numberOfSwapChains);
1568 return numberOfSwapChains;
1571 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1572 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1573 SwapChainList *swapchain;
1575 HRESULT hr = D3DERR_INVALIDCALL;
1576 swapchain = This->swapchains;
1577 TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1580 TRACE("(%p) Finding swapchain %d\n", This, iSwapChain);
1581 while (i > 0 && swapchain != NULL) {
1582 swapchain = swapchain->next;
1587 FIXME("(%p) Unable to find swapchain %d\n", This, iSwapChain);
1589 } else if (swapchain != NULL) {
1590 /** TODO: move off to a linkesList implementation **/
1591 *pSwapChain = swapchain->swapchain;
1592 IWineD3DSwapChain_AddRef(*pSwapChain);
1596 TRACE("(%p) returning %p\n", This, *pSwapChain);
1600 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
1601 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1603 FIXME("(%p) : Stub\n",This);
1609 * Vertex Declaration
1611 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1612 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1613 IWineD3DVertexDeclarationImpl *object = NULL;
1614 HRESULT hr = D3D_OK;
1615 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1616 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1619 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1624 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1625 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pDeclaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1626 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1627 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1628 HRESULT hr = D3D_OK;
1629 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1631 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1632 hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1635 FIXME("(%p) : Failed to set the function, returning D3DERR_INVALIDCALL\n", iface);
1636 IWineD3DVertexShader_Release(*ppVertexShader);
1637 return D3DERR_INVALIDCALL;
1640 #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. */
1641 if(Usage == WINED3DUSAGE_SOFTWAREVERTEXPROCESSING) {
1650 /* If a vertex declaration has been passed, save it to the vertex shader, this affects d3d8 only. */
1651 if (pDeclaration != NULL) {
1652 IWineD3DVertexDeclaration *vertexDeclaration;
1653 hr = IWineD3DDevice_CreateVertexDeclaration(iface, pDeclaration, &vertexDeclaration ,NULL);
1655 TRACE("(%p) : Setting vertex declaration to %p\n", This, vertexDeclaration);
1656 object->vertexDeclaration = vertexDeclaration;
1658 FIXME("(%p) : Failed to set the declaration, returning D3DERR_INVALIDCALL\n", iface);
1659 IWineD3DVertexShader_Release(*ppVertexShader);
1660 return D3DERR_INVALIDCALL;
1667 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
1668 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1669 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1670 HRESULT hr = D3D_OK;
1672 D3DCREATEOBJECTINSTANCE(object, PixelShader)
1673 hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
1675 TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
1677 WARN("(%p) : Failed to create pixel shader\n", This);
1683 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
1684 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1685 *ppD3D= This->wineD3D;
1686 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1687 IWineD3D_AddRef(*ppD3D);
1691 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1692 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1693 * Into the video ram as possible and seeing how many fit
1694 * you can also get the correct initial value from via X and ATI's driver
1695 *******************/
1696 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1697 static BOOL showfixmes = TRUE;
1699 FIXME("(%p) : stub, emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1700 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1703 TRACE("(%p) : emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1704 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1705 /* videomemory is simulated videomemory + AGP memory left */
1706 return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1714 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1715 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1716 HRESULT hr = D3D_OK;
1718 /* Update the current state block */
1719 This->updateStateBlock->fvf = fvf;
1720 This->updateStateBlock->changed.fvf = TRUE;
1721 This->updateStateBlock->set.fvf = TRUE;
1723 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1726 /* clear down the vertex declaration
1727 NOTE: Axis and Allies doesn't work properly otherwise
1728 (may be a stateblock problem though!)
1730 hr = IWineD3DDevice_SetVertexDeclaration(iface, NULL);
1737 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1738 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1739 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1740 *pfvf = This->stateBlock->fvf;
1745 * Get / Set Stream Source
1747 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1748 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1749 IWineD3DVertexBuffer *oldSrc;
1751 /**TODO: instance and index data, see
1752 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1754 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
1757 /* D3d9 only, but shouldn't hurt d3d8 */
1760 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1762 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1763 FIXME("stream index data not supported\n");
1765 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1766 FIXME("stream instance data not supported\n");
1770 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1772 if (StreamNumber >= MAX_STREAMS) {
1773 WARN("Stream out of range %d\n", StreamNumber);
1774 return D3DERR_INVALIDCALL;
1777 oldSrc = This->stateBlock->streamSource[StreamNumber];
1778 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1780 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
1781 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
1782 This->updateStateBlock->streamStride[StreamNumber] = Stride;
1783 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
1784 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
1785 This->updateStateBlock->streamFlags[StreamNumber] = streamFlags;
1787 /* Handle recording of state blocks */
1788 if (This->isRecordingState) {
1789 TRACE("Recording... not performing anything\n");
1793 /* Not recording... */
1794 /* Need to do a getParent and pass the reffs up */
1795 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
1796 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
1797 so for now, just count internally */
1798 if (pStreamData != NULL) {
1799 IWineD3DVertexBuffer_AddRef(pStreamData);
1801 if (oldSrc != NULL) {
1802 IWineD3DVertexBuffer_Release(oldSrc);
1808 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
1809 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1812 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
1813 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
1816 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1818 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1819 FIXME("stream index data not supported\n");
1821 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1822 FIXME("stream instance data not supported\n");
1826 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1828 if (StreamNumber >= MAX_STREAMS) {
1829 WARN("Stream out of range %d\n", StreamNumber);
1830 return D3DERR_INVALIDCALL;
1832 *pStream = This->stateBlock->streamSource[StreamNumber];
1833 *pStride = This->stateBlock->streamStride[StreamNumber];
1834 *pOffset = This->stateBlock->streamOffset[StreamNumber];
1836 if (*pStream == NULL) {
1837 FIXME("Attempting to get an empty stream %d, returning D3DERR_INVALIDCALL\n", StreamNumber);
1838 return D3DERR_INVALIDCALL;
1841 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
1845 /*Should be quite easy, just an extension of vertexdata
1847 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1849 The divider is a bit odd though
1851 VertexOffset = StartVertex / Divider * StreamStride +
1852 VertexIndex / Divider * StreamStride + StreamOffset
1855 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
1856 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1858 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
1859 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (D3DSTREAMSOURCE_INSTANCEDATA | D3DSTREAMSOURCE_INDEXEDDATA );
1861 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
1862 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
1863 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
1865 if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
1866 FIXME("Stream indexing not fully supported\n");
1872 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
1873 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1875 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
1876 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
1878 TRACE("(%p) : returning %d\n", This, *Divider);
1884 * Get / Set & Multiply Transform
1886 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1887 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1889 /* Most of this routine, comments included copied from ddraw tree initially: */
1890 TRACE("(%p) : Transform State=%d\n", This, d3dts);
1892 /* Handle recording of state blocks */
1893 if (This->isRecordingState) {
1894 TRACE("Recording... not performing anything\n");
1895 This->updateStateBlock->changed.transform[d3dts] = TRUE;
1896 This->updateStateBlock->set.transform[d3dts] = TRUE;
1897 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1902 * If the new matrix is the same as the current one,
1903 * we cut off any further processing. this seems to be a reasonable
1904 * optimization because as was noticed, some apps (warcraft3 for example)
1905 * tend towards setting the same matrix repeatedly for some reason.
1907 * From here on we assume that the new matrix is different, wherever it matters.
1909 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1910 TRACE("The app is setting the same matrix over again\n");
1913 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1917 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1918 where ViewMat = Camera space, WorldMat = world space.
1920 In OpenGL, camera and world space is combined into GL_MODELVIEW
1921 matrix. The Projection matrix stay projection matrix.
1924 /* Capture the times we can just ignore the change for now */
1925 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1926 This->modelview_valid = FALSE;
1929 } else if (d3dts == D3DTS_PROJECTION) {
1930 This->proj_valid = FALSE;
1933 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1934 /* Indexed Vertex Blending Matrices 256 -> 511 */
1935 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1936 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1940 /* Now we really are going to have to change a matrix */
1943 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1944 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
1945 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1948 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1949 * NOTE: We have to reset the positions even if the light/plane is not currently
1950 * enabled, since the call to enable it will not reset the position.
1951 * NOTE2: Apparently texture transforms do NOT need reapplying
1954 PLIGHTINFOEL *lightChain = NULL;
1955 This->modelview_valid = FALSE;
1956 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
1958 glMatrixMode(GL_MODELVIEW);
1959 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1961 glLoadMatrixf((float *)lpmatrix);
1962 checkGLcall("glLoadMatrixf(...)");
1965 lightChain = This->stateBlock->lights;
1966 while (lightChain && lightChain->glIndex != -1) {
1967 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1968 checkGLcall("glLightfv posn");
1969 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1970 checkGLcall("glLightfv dirn");
1971 lightChain = lightChain->next;
1974 /* Reset Clipping Planes if clipping is enabled */
1975 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1976 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1977 checkGLcall("glClipPlane");
1981 } else { /* What was requested!?? */
1982 WARN("invalid matrix specified: %i\n", d3dts);
1985 /* Release lock, all done */
1990 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1991 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1992 TRACE("(%p) : for Transform State %d\n", This, State);
1993 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1997 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1998 D3DMATRIX *mat = NULL;
2001 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2002 * below means it will be recorded in a state block change, but it
2003 * works regardless where it is recorded.
2004 * If this is found to be wrong, change to StateBlock.
2006 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2007 TRACE("(%p) : For state %u\n", This, State);
2009 if (State < HIGHEST_TRANSFORMSTATE)
2011 mat = &This->updateStateBlock->transforms[State];
2013 FIXME("Unhandled transform state!!\n");
2016 /* Copied from ddraw code: */
2017 temp.u.s._11 = (mat->u.s._11 * pMatrix->u.s._11) + (mat->u.s._21 * pMatrix->u.s._12) +
2018 (mat->u.s._31 * pMatrix->u.s._13) + (mat->u.s._41 * pMatrix->u.s._14);
2019 temp.u.s._21 = (mat->u.s._11 * pMatrix->u.s._21) + (mat->u.s._21 * pMatrix->u.s._22) +
2020 (mat->u.s._31 * pMatrix->u.s._23) + (mat->u.s._41 * pMatrix->u.s._24);
2021 temp.u.s._31 = (mat->u.s._11 * pMatrix->u.s._31) + (mat->u.s._21 * pMatrix->u.s._32) +
2022 (mat->u.s._31 * pMatrix->u.s._33) + (mat->u.s._41 * pMatrix->u.s._34);
2023 temp.u.s._41 = (mat->u.s._11 * pMatrix->u.s._41) + (mat->u.s._21 * pMatrix->u.s._42) +
2024 (mat->u.s._31 * pMatrix->u.s._43) + (mat->u.s._41 * pMatrix->u.s._44);
2026 temp.u.s._12 = (mat->u.s._12 * pMatrix->u.s._11) + (mat->u.s._22 * pMatrix->u.s._12) +
2027 (mat->u.s._32 * pMatrix->u.s._13) + (mat->u.s._42 * pMatrix->u.s._14);
2028 temp.u.s._22 = (mat->u.s._12 * pMatrix->u.s._21) + (mat->u.s._22 * pMatrix->u.s._22) +
2029 (mat->u.s._32 * pMatrix->u.s._23) + (mat->u.s._42 * pMatrix->u.s._24);
2030 temp.u.s._32 = (mat->u.s._12 * pMatrix->u.s._31) + (mat->u.s._22 * pMatrix->u.s._32) +
2031 (mat->u.s._32 * pMatrix->u.s._33) + (mat->u.s._42 * pMatrix->u.s._34);
2032 temp.u.s._42 = (mat->u.s._12 * pMatrix->u.s._41) + (mat->u.s._22 * pMatrix->u.s._42) +
2033 (mat->u.s._32 * pMatrix->u.s._43) + (mat->u.s._42 * pMatrix->u.s._44);
2035 temp.u.s._13 = (mat->u.s._13 * pMatrix->u.s._11) + (mat->u.s._23 * pMatrix->u.s._12) +
2036 (mat->u.s._33 * pMatrix->u.s._13) + (mat->u.s._43 * pMatrix->u.s._14);
2037 temp.u.s._23 = (mat->u.s._13 * pMatrix->u.s._21) + (mat->u.s._23 * pMatrix->u.s._22) +
2038 (mat->u.s._33 * pMatrix->u.s._23) + (mat->u.s._43 * pMatrix->u.s._24);
2039 temp.u.s._33 = (mat->u.s._13 * pMatrix->u.s._31) + (mat->u.s._23 * pMatrix->u.s._32) +
2040 (mat->u.s._33 * pMatrix->u.s._33) + (mat->u.s._43 * pMatrix->u.s._34);
2041 temp.u.s._43 = (mat->u.s._13 * pMatrix->u.s._41) + (mat->u.s._23 * pMatrix->u.s._42) +
2042 (mat->u.s._33 * pMatrix->u.s._43) + (mat->u.s._43 * pMatrix->u.s._44);
2044 temp.u.s._14 = (mat->u.s._14 * pMatrix->u.s._11) + (mat->u.s._24 * pMatrix->u.s._12) +
2045 (mat->u.s._34 * pMatrix->u.s._13) + (mat->u.s._44 * pMatrix->u.s._14);
2046 temp.u.s._24 = (mat->u.s._14 * pMatrix->u.s._21) + (mat->u.s._24 * pMatrix->u.s._22) +
2047 (mat->u.s._34 * pMatrix->u.s._23) + (mat->u.s._44 * pMatrix->u.s._24);
2048 temp.u.s._34 = (mat->u.s._14 * pMatrix->u.s._31) + (mat->u.s._24 * pMatrix->u.s._32) +
2049 (mat->u.s._34 * pMatrix->u.s._33) + (mat->u.s._44 * pMatrix->u.s._34);
2050 temp.u.s._44 = (mat->u.s._14 * pMatrix->u.s._41) + (mat->u.s._24 * pMatrix->u.s._42) +
2051 (mat->u.s._34 * pMatrix->u.s._43) + (mat->u.s._44 * pMatrix->u.s._44);
2053 /* Apply change via set transform - will reapply to eg. lights this way */
2054 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2059 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
2061 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2062 you can reference any indexes you want as long as that number max are enabled at any
2063 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2064 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2065 but when recording, just build a chain pretty much of commands to be replayed. */
2067 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2069 PLIGHTINFOEL *object, *temp;
2071 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2072 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2074 /* If recording state block, just add to end of lights chain */
2075 if (This->isRecordingState) {
2076 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2077 if (NULL == object) {
2078 return D3DERR_OUTOFVIDEOMEMORY;
2080 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2081 object->OriginalIndex = Index;
2082 object->glIndex = -1;
2083 object->changed = TRUE;
2085 /* Add to the END of the chain of lights changes to be replayed */
2086 if (This->updateStateBlock->lights == NULL) {
2087 This->updateStateBlock->lights = object;
2089 temp = This->updateStateBlock->lights;
2090 while (temp->next != NULL) temp=temp->next;
2091 temp->next = object;
2093 TRACE("Recording... not performing anything more\n");
2097 /* Ok, not recording any longer so do real work */
2098 object = This->stateBlock->lights;
2099 while (object != NULL && object->OriginalIndex != Index) object = object->next;
2101 /* If we didn't find it in the list of lights, time to add it */
2102 if (object == NULL) {
2103 PLIGHTINFOEL *insertAt,*prevPos;
2105 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2106 if (NULL == object) {
2107 return D3DERR_OUTOFVIDEOMEMORY;
2109 object->OriginalIndex = Index;
2110 object->glIndex = -1;
2112 /* Add it to the front of list with the idea that lights will be changed as needed
2113 BUT after any lights currently assigned GL indexes */
2114 insertAt = This->stateBlock->lights;
2116 while (insertAt != NULL && insertAt->glIndex != -1) {
2118 insertAt = insertAt->next;
2121 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2122 This->stateBlock->lights = object;
2123 } else if (insertAt == NULL) { /* End of list */
2124 prevPos->next = object;
2125 object->prev = prevPos;
2126 } else { /* Middle of chain */
2127 if (prevPos == NULL) {
2128 This->stateBlock->lights = object;
2130 prevPos->next = object;
2132 object->prev = prevPos;
2133 object->next = insertAt;
2134 insertAt->prev = object;
2138 /* Initialize the object */
2139 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,
2140 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2141 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2142 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2143 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2144 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2145 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2147 /* Save away the information */
2148 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2150 switch (pLight->Type) {
2151 case D3DLIGHT_POINT:
2153 object->lightPosn[0] = pLight->Position.x;
2154 object->lightPosn[1] = pLight->Position.y;
2155 object->lightPosn[2] = pLight->Position.z;
2156 object->lightPosn[3] = 1.0f;
2157 object->cutoff = 180.0f;
2161 case D3DLIGHT_DIRECTIONAL:
2163 object->lightPosn[0] = -pLight->Direction.x;
2164 object->lightPosn[1] = -pLight->Direction.y;
2165 object->lightPosn[2] = -pLight->Direction.z;
2166 object->lightPosn[3] = 0.0;
2167 object->exponent = 0.0f;
2168 object->cutoff = 180.0f;
2173 object->lightPosn[0] = pLight->Position.x;
2174 object->lightPosn[1] = pLight->Position.y;
2175 object->lightPosn[2] = pLight->Position.z;
2176 object->lightPosn[3] = 1.0;
2179 object->lightDirn[0] = pLight->Direction.x;
2180 object->lightDirn[1] = pLight->Direction.y;
2181 object->lightDirn[2] = pLight->Direction.z;
2182 object->lightDirn[3] = 1.0;
2185 * opengl-ish and d3d-ish spot lights use too different models for the
2186 * light "intensity" as a function of the angle towards the main light direction,
2187 * so we only can approximate very roughly.
2188 * however spot lights are rather rarely used in games (if ever used at all).
2189 * furthermore if still used, probably nobody pays attention to such details.
2191 if (pLight->Falloff == 0) {
2194 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2196 if (rho < 0.0001) rho = 0.0001f;
2197 object->exponent = -0.3/log(cos(rho/2));
2198 object->cutoff = pLight->Phi*90/M_PI;
2204 FIXME("Unrecognized light type %d\n", pLight->Type);
2207 /* Update the live definitions if the light is currently assigned a glIndex */
2208 if (object->glIndex != -1) {
2209 setup_light(iface, object->glIndex, object);
2214 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2215 PLIGHTINFOEL *lightInfo = NULL;
2216 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2217 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2219 /* Locate the light in the live lights */
2220 lightInfo = This->stateBlock->lights;
2221 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2223 if (lightInfo == NULL) {
2224 TRACE("Light information requested but light not defined\n");
2225 return D3DERR_INVALIDCALL;
2228 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
2233 * Get / Set Light Enable
2234 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2236 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2237 PLIGHTINFOEL *lightInfo = NULL;
2238 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2239 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2241 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2242 if (This->isRecordingState) {
2243 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2244 if (NULL == lightInfo) {
2245 return D3DERR_OUTOFVIDEOMEMORY;
2247 lightInfo->OriginalIndex = Index;
2248 lightInfo->glIndex = -1;
2249 lightInfo->enabledChanged = TRUE;
2251 /* Add to the END of the chain of lights changes to be replayed */
2252 if (This->updateStateBlock->lights == NULL) {
2253 This->updateStateBlock->lights = lightInfo;
2255 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2256 while (temp->next != NULL) temp=temp->next;
2257 temp->next = lightInfo;
2259 TRACE("Recording... not performing anything more\n");
2263 /* Not recording... So, locate the light in the live lights */
2264 lightInfo = This->stateBlock->lights;
2265 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2267 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2268 if (lightInfo == NULL) {
2269 D3DLIGHT9 lightParms;
2270 /* Warning - untested code :-) Prob safe to change fixme to a trace but
2271 wait until someone confirms it seems to work! */
2272 TRACE("Light enabled requested but light not defined, so defining one!\n");
2273 lightParms.Type = D3DLIGHT_DIRECTIONAL;
2274 lightParms.Diffuse.r = 1.0;
2275 lightParms.Diffuse.g = 1.0;
2276 lightParms.Diffuse.b = 1.0;
2277 lightParms.Diffuse.a = 0.0;
2278 lightParms.Specular.r = 0.0;
2279 lightParms.Specular.g = 0.0;
2280 lightParms.Specular.b = 0.0;
2281 lightParms.Specular.a = 0.0;
2282 lightParms.Ambient.r = 0.0;
2283 lightParms.Ambient.g = 0.0;
2284 lightParms.Ambient.b = 0.0;
2285 lightParms.Ambient.a = 0.0;
2286 lightParms.Position.x = 0.0;
2287 lightParms.Position.y = 0.0;
2288 lightParms.Position.z = 0.0;
2289 lightParms.Direction.x = 0.0;
2290 lightParms.Direction.y = 0.0;
2291 lightParms.Direction.z = 1.0;
2292 lightParms.Range = 0.0;
2293 lightParms.Falloff = 0.0;
2294 lightParms.Attenuation0 = 0.0;
2295 lightParms.Attenuation1 = 0.0;
2296 lightParms.Attenuation2 = 0.0;
2297 lightParms.Theta = 0.0;
2298 lightParms.Phi = 0.0;
2299 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
2301 /* Search for it again! Should be fairly quick as near head of list */
2302 lightInfo = This->stateBlock->lights;
2303 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2304 if (lightInfo == NULL) {
2305 FIXME("Adding default lights has failed dismally\n");
2306 return D3DERR_INVALIDCALL;
2310 /* OK, we now have a light... */
2311 if (Enable == FALSE) {
2313 /* If we are disabling it, check it was enabled, and
2314 still only do something if it has assigned a glIndex (which it should have!) */
2315 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2316 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2318 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2319 checkGLcall("glDisable GL_LIGHT0+Index");
2322 TRACE("Nothing to do as light was not enabled\n");
2324 lightInfo->lightEnabled = FALSE;
2327 /* We are enabling it. If it is enabled, it's really simple */
2328 if (lightInfo->lightEnabled) {
2330 TRACE("Nothing to do as light was enabled\n");
2332 /* If it already has a glIndex, it's still simple */
2333 } else if (lightInfo->glIndex != -1) {
2334 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2335 lightInfo->lightEnabled = TRUE;
2337 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2338 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2341 /* Otherwise got to find space - lights are ordered gl indexes first */
2343 PLIGHTINFOEL *bsf = NULL;
2344 PLIGHTINFOEL *pos = This->stateBlock->lights;
2345 PLIGHTINFOEL *prev = NULL;
2349 /* Try to minimize changes as much as possible */
2350 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2352 /* Try to remember which index can be replaced if necessary */
2353 if (bsf==NULL && pos->lightEnabled == FALSE) {
2354 /* Found a light we can replace, save as best replacement */
2358 /* Step to next space */
2364 /* If we have too many active lights, fail the call */
2365 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2366 FIXME("Program requests too many concurrent lights\n");
2367 return D3DERR_INVALIDCALL;
2369 /* If we have allocated all lights, but not all are enabled,
2370 reuse one which is not enabled */
2371 } else if (Index == This->maxConcurrentLights) {
2372 /* use bsf - Simply swap the new light and the BSF one */
2373 PLIGHTINFOEL *bsfNext = bsf->next;
2374 PLIGHTINFOEL *bsfPrev = bsf->prev;
2377 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2378 if (bsf->prev != NULL) {
2379 bsf->prev->next = lightInfo;
2381 This->stateBlock->lights = lightInfo;
2384 /* If not side by side, lots of chains to update */
2385 if (bsf->next != lightInfo) {
2386 lightInfo->prev->next = bsf;
2387 bsf->next->prev = lightInfo;
2388 bsf->next = lightInfo->next;
2389 bsf->prev = lightInfo->prev;
2390 lightInfo->next = bsfNext;
2391 lightInfo->prev = bsfPrev;
2395 bsf->prev = lightInfo;
2396 bsf->next = lightInfo->next;
2397 lightInfo->next = bsf;
2398 lightInfo->prev = bsfPrev;
2403 glIndex = bsf->glIndex;
2405 lightInfo->glIndex = glIndex;
2406 lightInfo->lightEnabled = TRUE;
2408 /* Finally set up the light in gl itself */
2409 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2411 setup_light(iface, glIndex, lightInfo);
2412 glEnable(GL_LIGHT0 + glIndex);
2413 checkGLcall("glEnable GL_LIGHT0 new setup");
2416 /* If we reached the end of the allocated lights, with space in the
2417 gl lights, setup a new light */
2418 } else if (pos->glIndex == -1) {
2420 /* We reached the end of the allocated gl lights, so already
2421 know the index of the next one! */
2423 lightInfo->glIndex = glIndex;
2424 lightInfo->lightEnabled = TRUE;
2426 /* In an ideal world, it's already in the right place */
2427 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2428 /* No need to move it */
2430 /* Remove this light from the list */
2431 lightInfo->prev->next = lightInfo->next;
2432 if (lightInfo->next != NULL) {
2433 lightInfo->next->prev = lightInfo->prev;
2436 /* Add in at appropriate place (inbetween prev and pos) */
2437 lightInfo->prev = prev;
2438 lightInfo->next = pos;
2440 This->stateBlock->lights = lightInfo;
2442 prev->next = lightInfo;
2445 pos->prev = lightInfo;
2449 /* Finally set up the light in gl itself */
2450 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2452 setup_light(iface, glIndex, lightInfo);
2453 glEnable(GL_LIGHT0 + glIndex);
2454 checkGLcall("glEnable GL_LIGHT0 new setup");
2463 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2465 PLIGHTINFOEL *lightInfo = NULL;
2466 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2467 TRACE("(%p) : for idx(%ld)\n", This, Index);
2469 /* Locate the light in the live lights */
2470 lightInfo = This->stateBlock->lights;
2471 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2473 if (lightInfo == NULL) {
2474 TRACE("Light enabled state requested but light not defined\n");
2475 return D3DERR_INVALIDCALL;
2477 *pEnable = lightInfo->lightEnabled;
2482 * Get / Set Clip Planes
2484 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2485 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2486 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2488 /* Validate Index */
2489 if (Index >= GL_LIMITS(clipplanes)) {
2490 TRACE("Application has requested clipplane this device doesn't support\n");
2491 return D3DERR_INVALIDCALL;
2494 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2495 This->updateStateBlock->set.clipplane[Index] = TRUE;
2496 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2497 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2498 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2499 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2501 /* Handle recording of state blocks */
2502 if (This->isRecordingState) {
2503 TRACE("Recording... not performing anything\n");
2511 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2512 glMatrixMode(GL_MODELVIEW);
2514 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2516 TRACE("Clipplane [%f,%f,%f,%f]\n",
2517 This->updateStateBlock->clipplane[Index][0],
2518 This->updateStateBlock->clipplane[Index][1],
2519 This->updateStateBlock->clipplane[Index][2],
2520 This->updateStateBlock->clipplane[Index][3]);
2521 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2522 checkGLcall("glClipPlane");
2530 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2531 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2532 TRACE("(%p) : for idx %ld\n", This, Index);
2534 /* Validate Index */
2535 if (Index >= GL_LIMITS(clipplanes)) {
2536 TRACE("Application has requested clipplane this device doesn't support\n");
2537 return D3DERR_INVALIDCALL;
2540 pPlane[0] = This->stateBlock->clipplane[Index][0];
2541 pPlane[1] = This->stateBlock->clipplane[Index][1];
2542 pPlane[2] = This->stateBlock->clipplane[Index][2];
2543 pPlane[3] = This->stateBlock->clipplane[Index][3];
2548 * Get / Set Clip Plane Status
2549 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2551 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2552 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2553 FIXME("(%p) : stub\n", This);
2554 if (NULL == pClipStatus) {
2555 return D3DERR_INVALIDCALL;
2557 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2558 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2562 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2563 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2564 FIXME("(%p) : stub\n", This);
2565 if (NULL == pClipStatus) {
2566 return D3DERR_INVALIDCALL;
2568 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2569 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2574 * Get / Set Material
2575 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2577 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2578 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2580 This->updateStateBlock->changed.material = TRUE;
2581 This->updateStateBlock->set.material = TRUE;
2582 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2584 /* Handle recording of state blocks */
2585 if (This->isRecordingState) {
2586 TRACE("Recording... not performing anything\n");
2591 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2592 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2593 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2594 pMaterial->Ambient.b, pMaterial->Ambient.a);
2595 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2596 pMaterial->Specular.b, pMaterial->Specular.a);
2597 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2598 pMaterial->Emissive.b, pMaterial->Emissive.a);
2599 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2601 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2602 checkGLcall("glMaterialfv(GL_AMBIENT)");
2603 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2604 checkGLcall("glMaterialfv(GL_DIFFUSE)");
2606 /* Only change material color if specular is enabled, otherwise it is set to black */
2607 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2608 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2609 checkGLcall("glMaterialfv(GL_SPECULAR");
2611 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2612 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2613 checkGLcall("glMaterialfv(GL_SPECULAR");
2615 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2616 checkGLcall("glMaterialfv(GL_EMISSION)");
2617 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2618 checkGLcall("glMaterialf(GL_SHININESS");
2624 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2625 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2626 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2627 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2628 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2629 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2630 pMaterial->Ambient.b, pMaterial->Ambient.a);
2631 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2632 pMaterial->Specular.b, pMaterial->Specular.a);
2633 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2634 pMaterial->Emissive.b, pMaterial->Emissive.a);
2635 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2643 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2644 UINT BaseVertexIndex) {
2645 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2646 IWineD3DIndexBuffer *oldIdxs;
2648 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2649 oldIdxs = This->updateStateBlock->pIndexData;
2651 This->updateStateBlock->changed.indices = TRUE;
2652 This->updateStateBlock->set.indices = TRUE;
2653 This->updateStateBlock->pIndexData = pIndexData;
2654 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2656 /* Handle recording of state blocks */
2657 if (This->isRecordingState) {
2658 TRACE("Recording... not performing anything\n");
2662 if (NULL != pIndexData) {
2663 IWineD3DIndexBuffer_AddRef(pIndexData);
2665 if (NULL != oldIdxs) {
2666 IWineD3DIndexBuffer_Release(oldIdxs);
2671 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2672 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2674 *ppIndexData = This->stateBlock->pIndexData;
2676 /* up ref count on ppindexdata */
2678 IWineD3DIndexBuffer_AddRef(*ppIndexData);
2679 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2680 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
2682 TRACE("(%p) No index data set\n", This);
2684 TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
2690 * Get / Set Viewports
2692 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2693 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2695 TRACE("(%p)\n", This);
2696 This->updateStateBlock->changed.viewport = TRUE;
2697 This->updateStateBlock->set.viewport = TRUE;
2698 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2700 /* Handle recording of state blocks */
2701 if (This->isRecordingState) {
2702 TRACE("Recording... not performing anything\n");
2705 This->viewport_changed = TRUE;
2709 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2710 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2712 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2713 checkGLcall("glDepthRange");
2714 /* Note: GL requires lower left, DirectX supplies upper left */
2715 /* TODO: replace usage of renderTarget with context management */
2716 glViewport(pViewport->X,
2717 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2718 pViewport->Width, pViewport->Height);
2720 checkGLcall("glViewport");
2728 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2729 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2730 TRACE("(%p)\n", This);
2731 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2736 * Get / Set Render States
2737 * TODO: Verify against dx9 definitions
2739 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2741 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2742 DWORD OldValue = This->stateBlock->renderState[State];
2744 /* Simple way of referring to either a DWORD or a 4 byte float */
2750 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2751 This->updateStateBlock->changed.renderState[State] = TRUE;
2752 This->updateStateBlock->set.renderState[State] = TRUE;
2753 This->updateStateBlock->renderState[State] = Value;
2755 /* Handle recording of state blocks */
2756 if (This->isRecordingState) {
2757 TRACE("Recording... not performing anything\n");
2764 case WINED3DRS_FILLMODE :
2765 switch ((D3DFILLMODE) Value) {
2766 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2767 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2768 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2770 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
2772 checkGLcall("glPolygonMode (fillmode)");
2775 case WINED3DRS_LIGHTING :
2777 glEnable(GL_LIGHTING);
2778 checkGLcall("glEnable GL_LIGHTING");
2780 glDisable(GL_LIGHTING);
2781 checkGLcall("glDisable GL_LIGHTING");
2785 case WINED3DRS_ZENABLE :
2786 switch ((D3DZBUFFERTYPE) Value) {
2788 glDisable(GL_DEPTH_TEST);
2789 checkGLcall("glDisable GL_DEPTH_TEST");
2792 glEnable(GL_DEPTH_TEST);
2793 checkGLcall("glEnable GL_DEPTH_TEST");
2796 glEnable(GL_DEPTH_TEST);
2797 checkGLcall("glEnable GL_DEPTH_TEST");
2798 FIXME("W buffer is not well handled\n");
2801 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2805 case WINED3DRS_CULLMODE :
2807 /* If we are culling "back faces with clockwise vertices" then
2808 set front faces to be counter clockwise and enable culling
2810 switch ((D3DCULL) Value) {
2812 glDisable(GL_CULL_FACE);
2813 checkGLcall("glDisable GL_CULL_FACE");
2816 glEnable(GL_CULL_FACE);
2817 checkGLcall("glEnable GL_CULL_FACE");
2818 if (This->renderUpsideDown) {
2820 checkGLcall("glFrontFace GL_CW");
2822 glFrontFace(GL_CCW);
2823 checkGLcall("glFrontFace GL_CCW");
2825 glCullFace(GL_BACK);
2828 glEnable(GL_CULL_FACE);
2829 checkGLcall("glEnable GL_CULL_FACE");
2830 if (This->renderUpsideDown) {
2831 glFrontFace(GL_CCW);
2832 checkGLcall("glFrontFace GL_CCW");
2835 checkGLcall("glFrontFace GL_CW");
2837 glCullFace(GL_BACK);
2840 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2844 case WINED3DRS_SHADEMODE :
2845 switch ((D3DSHADEMODE) Value) {
2847 glShadeModel(GL_FLAT);
2848 checkGLcall("glShadeModel");
2850 case D3DSHADE_GOURAUD:
2851 glShadeModel(GL_SMOOTH);
2852 checkGLcall("glShadeModel");
2854 case D3DSHADE_PHONG:
2855 FIXME("D3DSHADE_PHONG isn't supported?\n");
2858 return D3DERR_INVALIDCALL;
2860 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2864 case WINED3DRS_DITHERENABLE :
2866 glEnable(GL_DITHER);
2867 checkGLcall("glEnable GL_DITHER");
2869 glDisable(GL_DITHER);
2870 checkGLcall("glDisable GL_DITHER");
2874 case WINED3DRS_ZWRITEENABLE :
2877 checkGLcall("glDepthMask");
2880 checkGLcall("glDepthMask");
2884 case WINED3DRS_ZFUNC :
2886 int glParm = GL_LESS;
2888 switch ((D3DCMPFUNC) Value) {
2889 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2890 case D3DCMP_LESS: glParm=GL_LESS; break;
2891 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2892 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2893 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2894 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2895 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2896 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2898 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2900 glDepthFunc(glParm);
2901 checkGLcall("glDepthFunc");
2905 case WINED3DRS_AMBIENT :
2908 D3DCOLORTOGLFLOAT4(Value, col);
2909 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2910 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2911 checkGLcall("glLightModel for MODEL_AMBIENT");
2916 case WINED3DRS_ALPHABLENDENABLE :
2919 checkGLcall("glEnable GL_BLEND");
2921 glDisable(GL_BLEND);
2922 checkGLcall("glDisable GL_BLEND");
2926 case WINED3DRS_SRCBLEND :
2927 case WINED3DRS_DESTBLEND :
2929 int newVal = GL_ZERO;
2931 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2932 case D3DBLEND_ONE : newVal = GL_ONE; break;
2933 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2934 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2935 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2936 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2937 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2938 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2939 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2940 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2941 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2943 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2944 This->srcBlend = newVal;
2945 This->dstBlend = newVal;
2948 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2949 This->srcBlend = newVal;
2950 This->dstBlend = newVal;
2953 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2956 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2957 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2958 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2959 glBlendFunc(This->srcBlend, This->dstBlend);
2961 checkGLcall("glBlendFunc");
2965 case WINED3DRS_ALPHATESTENABLE :
2967 glEnable(GL_ALPHA_TEST);
2968 checkGLcall("glEnable GL_ALPHA_TEST");
2970 glDisable(GL_ALPHA_TEST);
2971 checkGLcall("glDisable GL_ALPHA_TEST");
2975 case WINED3DRS_ALPHAFUNC :
2977 int glParm = GL_LESS;
2978 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2980 switch ((D3DCMPFUNC) Value) {
2981 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2982 case D3DCMP_LESS: glParm = GL_LESS; break;
2983 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2984 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2985 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2986 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2987 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2988 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2990 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2992 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2993 glAlphaFunc(glParm, ref);
2994 This->alphafunc = glParm;
2995 checkGLcall("glAlphaFunc");
2999 case WINED3DRS_ALPHAREF :
3001 int glParm = This->alphafunc;
3004 ref = ((float) Value) / 255.0f;
3005 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
3006 glAlphaFunc(glParm, ref);
3007 checkGLcall("glAlphaFunc");
3011 case WINED3DRS_CLIPPLANEENABLE :
3012 case WINED3DRS_CLIPPING :
3014 /* Ensure we only do the changed clip planes */
3015 DWORD enable = 0xFFFFFFFF;
3016 DWORD disable = 0x00000000;
3018 /* If enabling / disabling all */
3019 if (State == WINED3DRS_CLIPPING) {
3021 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3024 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3028 enable = Value & ~OldValue;
3029 disable = ~Value & OldValue;
3032 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
3033 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
3034 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
3035 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
3036 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
3037 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
3039 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
3040 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
3041 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
3042 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
3043 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
3044 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
3046 /** update clipping status */
3048 This->stateBlock->clip_status.ClipUnion = 0;
3049 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
3051 This->stateBlock->clip_status.ClipUnion = 0;
3052 This->stateBlock->clip_status.ClipIntersection = 0;
3057 case WINED3DRS_BLENDOP :
3059 int glParm = GL_FUNC_ADD;
3061 switch ((D3DBLENDOP) Value) {
3062 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
3063 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
3064 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3065 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
3066 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
3068 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
3070 TRACE("glBlendEquation(%x)\n", glParm);
3071 glBlendEquation(glParm);
3072 checkGLcall("glBlendEquation");
3076 case WINED3DRS_TEXTUREFACTOR :
3080 /* Note the texture color applies to all textures whereas
3081 GL_TEXTURE_ENV_COLOR applies to active only */
3083 D3DCOLORTOGLFLOAT4(Value, col);
3084 /* Set the default alpha blend color */
3085 glBlendColor(col[0], col[1], col[2], col[3]);
3086 checkGLcall("glBlendColor");
3088 /* And now the default texture color as well */
3089 for (i = 0; i < GL_LIMITS(textures); i++) {
3091 /* Note the D3DRS value applies to all textures, but GL has one
3092 per texture, so apply it now ready to be used! */
3093 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3096 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3099 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3100 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3105 case WINED3DRS_SPECULARENABLE :
3107 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3108 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3109 specular color. This is wrong:
3110 Separate specular color means the specular colour is maintained separately, whereas
3111 single color means it is merged in. However in both cases they are being used to
3113 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3114 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3118 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3119 checkGLcall("glMaterialfv");
3120 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3121 glEnable(GL_COLOR_SUM_EXT);
3123 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3125 checkGLcall("glEnable(GL_COLOR_SUM)");
3127 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3129 /* for the case of enabled lighting: */
3130 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3131 checkGLcall("glMaterialfv");
3133 /* for the case of disabled lighting: */
3134 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3135 glDisable(GL_COLOR_SUM_EXT);
3137 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3139 checkGLcall("glDisable(GL_COLOR_SUM)");
3144 case WINED3DRS_STENCILENABLE :
3146 glEnable(GL_STENCIL_TEST);
3147 checkGLcall("glEnable GL_STENCIL_TEST");
3149 glDisable(GL_STENCIL_TEST);
3150 checkGLcall("glDisable GL_STENCIL_TEST");
3154 case WINED3DRS_STENCILFUNC :
3156 int glParm = GL_ALWAYS;
3157 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3158 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3160 switch ((D3DCMPFUNC) Value) {
3161 case D3DCMP_NEVER: glParm=GL_NEVER; break;
3162 case D3DCMP_LESS: glParm=GL_LESS; break;
3163 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
3164 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
3165 case D3DCMP_GREATER: glParm=GL_GREATER; break;
3166 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
3167 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
3168 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
3170 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3172 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3173 This->stencilfunc = glParm;
3174 glStencilFunc(glParm, ref, mask);
3175 checkGLcall("glStencilFunc");
3179 case WINED3DRS_STENCILREF :
3181 int glParm = This->stencilfunc;
3183 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3186 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3187 glStencilFunc(glParm, ref, mask);
3188 checkGLcall("glStencilFunc");
3192 case WINED3DRS_STENCILMASK :
3194 int glParm = This->stencilfunc;
3195 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3196 GLuint mask = Value;
3198 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3199 glStencilFunc(glParm, ref, mask);
3200 checkGLcall("glStencilFunc");
3204 case WINED3DRS_STENCILFAIL :
3210 fail = StencilOp(Value);
3211 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
3212 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
3213 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
3214 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
3216 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3217 glStencilOp(fail, zfail, zpass);
3218 checkGLcall("glStencilOp(fail, zfail, zpass);");
3221 case WINED3DRS_STENCILZFAIL :
3227 glGetIntegerv(GL_STENCIL_FAIL, &fail);
3228 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
3229 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
3230 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
3231 zfail = StencilOp(Value);
3233 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3234 glStencilOp(fail, zfail, zpass);
3235 checkGLcall("glStencilOp(fail, zfail, zpass);");
3238 case WINED3DRS_STENCILPASS :
3244 glGetIntegerv(GL_STENCIL_FAIL, &fail);
3245 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
3246 zpass = StencilOp(Value);
3247 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
3248 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
3250 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3251 glStencilOp(fail, zfail, zpass);
3252 checkGLcall("glStencilOp(fail, zfail, zpass);");
3256 case WINED3DRS_STENCILWRITEMASK :
3258 glStencilMask(Value);
3259 TRACE("glStencilMask(%lu)\n", Value);
3260 checkGLcall("glStencilMask");
3264 case WINED3DRS_FOGENABLE :
3266 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
3268 checkGLcall("glEnable GL_FOG");
3271 checkGLcall("glDisable GL_FOG");
3276 case WINED3DRS_RANGEFOGENABLE :
3279 TRACE("Enabled RANGEFOG");
3281 TRACE("Disabled RANGEFOG");
3286 case WINED3DRS_FOGCOLOR :
3289 D3DCOLORTOGLFLOAT4(Value, col);
3290 /* Set the default alpha blend color */
3291 glFogfv(GL_FOG_COLOR, &col[0]);
3292 checkGLcall("glFog GL_FOG_COLOR");
3296 case WINED3DRS_FOGTABLEMODE :
3298 glHint(GL_FOG_HINT, GL_NICEST);
3300 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3301 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3302 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3303 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3305 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3307 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3308 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3313 case WINED3DRS_FOGVERTEXMODE :
3315 glHint(GL_FOG_HINT, GL_FASTEST);
3317 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3318 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3319 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3320 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3322 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3324 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3325 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
3330 case WINED3DRS_FOGSTART :
3333 glFogfv(GL_FOG_START, &tmpvalue.f);
3334 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3335 TRACE("Fog Start == %f\n", tmpvalue.f);
3339 case WINED3DRS_FOGEND :
3342 glFogfv(GL_FOG_END, &tmpvalue.f);
3343 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3344 TRACE("Fog End == %f\n", tmpvalue.f);
3348 case WINED3DRS_FOGDENSITY :
3351 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3352 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3356 case WINED3DRS_VERTEXBLEND :
3358 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3359 TRACE("Vertex Blending state to %ld\n", Value);
3363 case WINED3DRS_TWEENFACTOR :
3366 This->updateStateBlock->tween_factor = tmpvalue.f;
3367 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3371 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
3373 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3377 case WINED3DRS_COLORVERTEX :
3378 case WINED3DRS_DIFFUSEMATERIALSOURCE :
3379 case WINED3DRS_SPECULARMATERIALSOURCE :
3380 case WINED3DRS_AMBIENTMATERIALSOURCE :
3381 case WINED3DRS_EMISSIVEMATERIALSOURCE :
3383 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3385 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3386 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3387 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3388 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3389 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3390 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3392 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3393 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3394 Parm = GL_AMBIENT_AND_DIFFUSE;
3398 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3400 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3402 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3409 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3411 This->tracking_color = NEEDS_TRACKING;
3412 This->tracking_parm = Parm;
3416 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3421 case WINED3DRS_LINEPATTERN :
3427 tmppattern.d = Value;
3429 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3431 if (tmppattern.lp.wRepeatFactor) {
3432 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3433 checkGLcall("glLineStipple(repeat, linepattern)");
3434 glEnable(GL_LINE_STIPPLE);
3435 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3437 glDisable(GL_LINE_STIPPLE);
3438 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3443 case WINED3DRS_ZBIAS : /* D3D8 only */
3447 TRACE("ZBias value %f\n", tmpvalue.f);
3448 glPolygonOffset(0, -tmpvalue.f);
3449 checkGLcall("glPolygonOffset(0, -Value)");
3450 glEnable(GL_POLYGON_OFFSET_FILL);
3451 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3452 glEnable(GL_POLYGON_OFFSET_LINE);
3453 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3454 glEnable(GL_POLYGON_OFFSET_POINT);
3455 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3457 glDisable(GL_POLYGON_OFFSET_FILL);
3458 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3459 glDisable(GL_POLYGON_OFFSET_LINE);
3460 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3461 glDisable(GL_POLYGON_OFFSET_POINT);
3462 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3467 case WINED3DRS_NORMALIZENORMALS :
3469 glEnable(GL_NORMALIZE);
3470 checkGLcall("glEnable(GL_NORMALIZE);");
3472 glDisable(GL_NORMALIZE);
3473 checkGLcall("glDisable(GL_NORMALIZE);");
3477 case WINED3DRS_POINTSIZE :
3478 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
3480 TRACE("Set point size to %f\n", tmpvalue.f);
3481 glPointSize(tmpvalue.f);
3482 checkGLcall("glPointSize(...);");
3485 case WINED3DRS_POINTSIZE_MIN :
3486 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3488 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3489 checkGLcall("glPointParameterfEXT(...);");
3491 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3495 case WINED3DRS_POINTSIZE_MAX :
3496 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3498 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3499 checkGLcall("glPointParameterfEXT(...);");
3501 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3505 case WINED3DRS_POINTSCALE_A :
3506 case WINED3DRS_POINTSCALE_B :
3507 case WINED3DRS_POINTSCALE_C :
3508 case WINED3DRS_POINTSCALEENABLE :
3511 * POINTSCALEENABLE controls how point size value is treated. If set to
3512 * true, the point size is scaled with repsect to height of viewport.
3513 * When set to false point size is in pixels.
3515 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
3518 /* Default values */
3519 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3522 * Minium valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
3523 * This means that OpenGL will clamp really small point sizes to 1.0f.
3524 * To correct for this we need to multiply by the scale factor when sizes
3525 * are less than 1.0f. scale_factor = 1.0f / point_size.
3527 GLfloat pointSize = *((float*)&This->stateBlock->renderState[D3DRS_POINTSIZE]);
3528 GLfloat scaleFactor;
3529 if(pointSize < 1.0f) {
3530 scaleFactor = pointSize * pointSize;
3535 if(This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3536 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]) /
3537 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3538 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]) /
3539 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3540 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) /
3541 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3544 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
3545 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
3546 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
3548 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3549 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3550 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
3552 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
3556 case WINED3DRS_COLORWRITEENABLE :
3558 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3559 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3560 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3561 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3562 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3563 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3564 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3565 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3566 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3567 checkGLcall("glColorMask(...)");
3571 case WINED3DRS_LOCALVIEWER :
3573 GLint state = (Value) ? 1 : 0;
3574 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3575 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3579 case WINED3DRS_LASTPIXEL :
3582 TRACE("Last Pixel Drawing Enabled\n");
3584 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3589 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3592 TRACE("Software Processing Enabled\n");
3594 TRACE("Software Processing Disabled\n");
3599 /** not supported */
3600 case WINED3DRS_ZVISIBLE :
3603 return D3DERR_INVALIDCALL;
3605 case WINED3DRS_POINTSPRITEENABLE :
3607 /* TODO: NV_POINT_SPRITE */
3608 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
3609 TRACE("Point sprites not supported\n");
3614 * Point sprites are always enabled. Value controls texture coordinate
3615 * replacement mode. Must be set true for point sprites to use
3618 glEnable(GL_POINT_SPRITE_ARB);
3619 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
3622 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
3623 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, TRUE)");
3625 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, FALSE);
3626 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, FALSE)");
3630 case WINED3DRS_EDGEANTIALIAS :
3633 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3635 checkGLcall("glEnable(GL_BLEND)");
3636 glEnable(GL_LINE_SMOOTH);
3637 checkGLcall("glEnable(GL_LINE_SMOOTH)");
3639 glDisable(GL_BLEND);
3640 checkGLcall("glDisable(GL_BLEND)");
3641 glDisable(GL_LINE_SMOOTH);
3642 checkGLcall("glDisable(GL_LINE_SMOOTH)");
3646 case WINED3DRS_WRAP0 :
3647 case WINED3DRS_WRAP1 :
3648 case WINED3DRS_WRAP2 :
3649 case WINED3DRS_WRAP3 :
3650 case WINED3DRS_WRAP4 :
3651 case WINED3DRS_WRAP5 :
3652 case WINED3DRS_WRAP6 :
3653 case WINED3DRS_WRAP7 :
3655 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
3656 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
3657 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
3658 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
3659 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
3661 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
3663 TRACE("(%p)->(%d,%ld) Texture wraping not yet supported\n",This, State, Value);
3665 case WINED3DRS_MULTISAMPLEANTIALIAS :
3667 if (!GL_SUPPORT(ARB_MULTISAMPLE)) {
3668 TRACE("Multisample antialiasing not supported\n");
3673 glEnable(GL_MULTISAMPLE_ARB);
3674 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
3676 glDisable(GL_MULTISAMPLE_ARB);
3677 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
3681 case WINED3DRS_MULTISAMPLEMASK :
3682 case WINED3DRS_PATCHEDGESTYLE :
3683 case WINED3DRS_PATCHSEGMENTS :
3684 case WINED3DRS_DEBUGMONITORTOKEN :
3685 case WINED3DRS_POSITIONORDER :
3686 case WINED3DRS_NORMALORDER :
3687 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3688 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3691 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3699 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3700 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3701 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3702 *pValue = This->stateBlock->renderState[State];
3707 * Get / Set Sampler States
3708 * TODO: Verify against dx9 definitions
3711 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3712 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3714 * SetSampler is designed to allow for more than the standard up to 8 textures
3715 * and Geforce has stopped supporting more than 6 standard textures in openGL.
3716 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3718 * http://developer.nvidia.com/object/General_FAQ.html#t6
3720 * There are two new settings for GForce
3722 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3723 * and the texture one:
3724 * GL_MAX_TEXTURE_COORDS_ARB.
3725 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3727 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
3728 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
3730 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
3731 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE, Sampler, Type);
3732 return D3DERR_INVALIDCALL;
3734 TRACE("Setting sampler %ld %d to %ld\n", Sampler, Type, Value);
3735 This->updateStateBlock->samplerState[Sampler][Type] = Value;
3736 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
3737 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
3739 /* Handle recording of state blocks */
3740 if (This->isRecordingState) {
3741 TRACE("Recording... not performing anything\n");
3748 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3749 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3750 /** TODO: check that sampler is in range **/
3751 *Value = This->updateStateBlock->samplerState[Sampler][Type];
3752 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
3757 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3758 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3761 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3762 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3763 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3769 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3770 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3771 GLint scissorBox[4];
3774 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3775 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
3776 pRect->left = scissorBox[1];
3777 pRect->top = scissorBox[2];
3778 pRect->right = scissorBox[1] + scissorBox[3];
3779 pRect->bottom = scissorBox[2] + scissorBox[4];
3780 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3785 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3786 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3787 IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
3789 TRACE("(%p) : pDecl=%p\n", This, pDecl);
3791 This->updateStateBlock->vertexDecl = pDecl;
3792 This->updateStateBlock->changed.vertexDecl = TRUE;
3793 This->updateStateBlock->set.vertexDecl = TRUE;
3795 if (This->isRecordingState) {
3796 TRACE("Recording... not performing anything\n");
3799 if (NULL != pDecl) {
3800 IWineD3DVertexDeclaration_AddRef(pDecl);
3802 if (NULL != oldDecl) {
3803 IWineD3DVertexDeclaration_Release(oldDecl);
3808 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3809 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3811 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3813 *ppDecl = This->stateBlock->vertexDecl;
3814 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3818 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
3819 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3820 IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
3822 This->updateStateBlock->vertexShader = pShader;
3823 This->updateStateBlock->changed.vertexShader = TRUE;
3824 This->updateStateBlock->set.vertexShader = TRUE;
3826 if (This->isRecordingState) {
3827 TRACE("Recording... not performing anything\n");
3830 if (NULL != pShader) {
3831 IWineD3DVertexShader_AddRef(pShader);
3833 if (NULL != oldShader) {
3834 IWineD3DVertexShader_Release(oldShader);
3837 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3839 * TODO: merge HAL shaders context switching from prototype
3844 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
3845 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3847 if (NULL == ppShader) {
3848 return D3DERR_INVALIDCALL;
3850 *ppShader = This->stateBlock->vertexShader;
3851 if( NULL != *ppShader)
3852 IWineD3DVertexShader_AddRef(*ppShader);
3854 TRACE("(%p) : returning %p\n", This, *ppShader);
3858 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
3859 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3862 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
3864 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
3865 iface, dstData, srcData, type, start, count, registersize);
3867 if (type != WINESHADERCNST_NONE) {
3868 if (srcData == NULL || cnt < 0) {
3869 return D3DERR_INVALIDCALL;
3872 CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
3875 for (i = start; i < cnt + start; ++i) {
3876 This->updateStateBlock->changed.vertexShaderConstants[i] = TRUE;
3877 This->updateStateBlock->set.vertexShaderConstants[i] = TRUE;
3878 This->updateStateBlock->vertexShaderConstantT[i] = type;
3884 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
3885 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3888 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
3890 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
3891 iface, dstData, srcData, type, start, count, registersize);
3893 /* Verify that the requested shader constant was populated with the correct type */
3894 for (i = start; i < cnt + start; ++i) {
3895 if (This->updateStateBlock->vertexShaderConstantT[i] != type) {
3896 TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning D3DERR_INVALIDCALL\n",
3897 This, type, This->updateStateBlock->vertexShaderConstantT[i]);
3898 return D3DERR_INVALIDCALL;
3902 if (dstData == NULL || cnt < 0) {
3903 return D3DERR_INVALIDCALL;
3906 CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
3911 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
3912 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3914 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
3915 This->updateStateBlock->vertexShaderConstantB,
3917 WINESHADERCNST_BOOL,
3920 sizeof(*pConstantData));
3923 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
3924 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3926 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
3928 This->updateStateBlock->vertexShaderConstantB,
3929 WINESHADERCNST_BOOL,
3932 sizeof(*pConstantData));
3935 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
3936 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3938 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
3939 This->updateStateBlock->vertexShaderConstantI,
3941 WINESHADERCNST_INTEGER,
3944 4 * sizeof(*pConstantData));
3947 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
3948 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3950 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
3952 This->updateStateBlock->vertexShaderConstantI,
3953 WINESHADERCNST_INTEGER,
3956 4 * sizeof(*pConstantData));
3960 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
3961 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3963 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
3964 This->updateStateBlock->vertexShaderConstantF,
3966 WINESHADERCNST_FLOAT,
3969 4 * sizeof(*pConstantData));
3972 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
3973 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3975 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
3977 This->updateStateBlock->vertexShaderConstantF,
3978 WINESHADERCNST_FLOAT,
3981 4 * sizeof(*pConstantData));
3984 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
3985 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
3988 WINESHADERCNST_NONE,
3994 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
3995 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3996 IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader;
3997 This->updateStateBlock->pixelShader = pShader;
3998 This->updateStateBlock->changed.pixelShader = TRUE;
3999 This->updateStateBlock->set.pixelShader = TRUE;
4001 /* Handle recording of state blocks */
4002 if (This->isRecordingState) {
4003 TRACE("Recording... not performing anything\n");
4006 if (NULL != pShader) {
4007 IWineD3DPixelShader_AddRef(pShader);
4009 if (NULL != oldShader) {
4010 IWineD3DPixelShader_Release(oldShader);
4013 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4015 * TODO: merge HAL shaders context switching from prototype
4020 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
4021 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4023 if (NULL == ppShader) {
4024 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
4025 return D3DERR_INVALIDCALL;
4028 *ppShader = This->stateBlock->pixelShader;
4029 if (NULL != ppShader) {
4030 IWineD3DPixelShader_AddRef(*ppShader);
4032 TRACE("(%p) : returning %p\n", This, *ppShader);
4036 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4037 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4040 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4042 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4043 iface, dstData, srcData, type, start, count, registersize);
4045 if (type != WINESHADERCNST_NONE) {
4046 if (srcData == NULL || cnt < 0) {
4047 return D3DERR_INVALIDCALL;
4050 CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
4053 for (i = start; i < cnt + start; ++i) {
4054 This->updateStateBlock->changed.pixelShaderConstants[i] = TRUE;
4055 This->updateStateBlock->set.pixelShaderConstants[i] = TRUE;
4056 This->updateStateBlock->pixelShaderConstantT[i] = type;
4062 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4063 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4066 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4068 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4069 iface, dstData, srcData, type, start, count, registersize);
4071 /* Verify that the requested shader constant was populated with the correct type */
4072 for (i = start; i < cnt + start; ++i) {
4073 if (This->updateStateBlock->pixelShaderConstantT[i] != type) {
4074 TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning D3DERR_INVALIDCALL\n",
4075 This, type, This->updateStateBlock->pixelShaderConstantT[i]);
4076 return D3DERR_INVALIDCALL;
4080 if (dstData == NULL || cnt < 0) {
4081 return D3DERR_INVALIDCALL;
4084 CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
4089 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
4090 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4092 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4093 This->updateStateBlock->pixelShaderConstantB,
4095 WINESHADERCNST_BOOL,
4098 sizeof(*pConstantData));
4101 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
4102 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4104 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4106 This->updateStateBlock->pixelShaderConstantB,
4107 WINESHADERCNST_BOOL,
4110 sizeof(*pConstantData));
4113 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
4114 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4116 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4117 This->updateStateBlock->pixelShaderConstantI,
4119 WINESHADERCNST_INTEGER,
4122 4 * sizeof(*pConstantData));
4125 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
4126 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4128 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4130 This->updateStateBlock->pixelShaderConstantI,
4131 WINESHADERCNST_INTEGER,
4134 4 * sizeof(*pConstantData));
4137 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
4138 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4140 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4141 This->updateStateBlock->pixelShaderConstantF,
4143 WINESHADERCNST_FLOAT,
4146 4 * sizeof(*pConstantData));
4149 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
4150 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4152 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4154 This->updateStateBlock->pixelShaderConstantF,
4155 WINESHADERCNST_FLOAT,
4158 4 * sizeof(*pConstantData));
4161 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
4162 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4165 WINESHADERCNST_NONE,
4171 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
4172 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4173 FIXME("(%p) : stub\n", This);
4178 * Apply / Get / Set Texture Stage States
4179 * TODO: Verify against dx9 definitions
4182 /* 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 */
4183 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
4184 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4185 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
4186 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4188 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4190 /* Check that the stage is within limits */
4191 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4192 TRACE("Attempt to access invalid texture rejected\n");
4199 case WINED3DTSS_ALPHAOP :
4200 case WINED3DTSS_COLOROP :
4201 /* nothing to do as moved to drawprim for now */
4203 case WINED3DTSS_ADDRESSW :
4204 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
4205 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
4206 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
4209 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
4210 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
4211 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
4212 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
4215 case WINED3DTSS_TEXCOORDINDEX :
4217 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
4219 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
4220 one flag, you can still specify an index value, which the system uses to
4221 determine the texture wrapping mode.
4222 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
4223 means use the vertex position (camera-space) as the input texture coordinates
4224 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
4225 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
4226 to the TEXCOORDINDEX value */
4229 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
4231 switch (Value & 0xFFFF0000) {
4232 case D3DTSS_TCI_PASSTHRU:
4233 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
4234 glDisable(GL_TEXTURE_GEN_S);
4235 glDisable(GL_TEXTURE_GEN_T);
4236 glDisable(GL_TEXTURE_GEN_R);
4237 glDisable(GL_TEXTURE_GEN_Q);
4238 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
4241 case D3DTSS_TCI_CAMERASPACEPOSITION:
4242 /* CameraSpacePosition means use the vertex position, transformed to camera space,
4243 as the input texture coordinates for this stage's texture transformation. This
4244 equates roughly to EYE_LINEAR */
4246 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4247 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4248 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4249 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4250 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4252 glMatrixMode(GL_MODELVIEW);
4255 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4256 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4257 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4258 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4261 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
4262 glEnable(GL_TEXTURE_GEN_S);
4263 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4264 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4265 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4266 glEnable(GL_TEXTURE_GEN_T);
4267 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4268 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4269 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4270 glEnable(GL_TEXTURE_GEN_R);
4271 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4272 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4273 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4277 case D3DTSS_TCI_CAMERASPACENORMAL:
4279 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4280 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4281 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4282 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4283 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4284 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
4286 glMatrixMode(GL_MODELVIEW);
4289 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4290 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4291 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4292 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4295 glEnable(GL_TEXTURE_GEN_S);
4296 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4297 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4298 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4299 glEnable(GL_TEXTURE_GEN_T);
4300 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4301 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4302 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4303 glEnable(GL_TEXTURE_GEN_R);
4304 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4305 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4306 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4311 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
4313 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4314 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4315 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4316 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4317 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4318 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
4320 glMatrixMode(GL_MODELVIEW);
4323 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4324 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4325 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4326 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4329 glEnable(GL_TEXTURE_GEN_S);
4330 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4331 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4332 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4333 glEnable(GL_TEXTURE_GEN_T);
4334 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4335 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4336 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4337 glEnable(GL_TEXTURE_GEN_R);
4338 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4339 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4340 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4345 /* Unhandled types: */
4348 /* ? disable GL_TEXTURE_GEN_n ? */
4349 glDisable(GL_TEXTURE_GEN_S);
4350 glDisable(GL_TEXTURE_GEN_T);
4351 glDisable(GL_TEXTURE_GEN_R);
4352 glDisable(GL_TEXTURE_GEN_Q);
4353 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
4360 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
4361 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);
4364 case WINED3DTSS_BUMPENVMAT00 :
4365 case WINED3DTSS_BUMPENVMAT01 :
4366 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
4368 case WINED3DTSS_BUMPENVMAT10 :
4369 case WINED3DTSS_BUMPENVMAT11 :
4370 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
4373 case WINED3DTSS_BUMPENVLSCALE :
4374 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4377 case WINED3DTSS_BUMPENVLOFFSET :
4378 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4381 case WINED3DTSS_RESULTARG :
4382 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4386 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
4387 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4396 * Get / Set Texture Stage States
4397 * TODO: Verify against dx9 definitions
4399 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
4400 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4402 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4404 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4406 /* Reject invalid texture units */
4407 if (Stage >= GL_LIMITS(textures)) {
4408 TRACE("Attempt to access invalid texture rejected\n");
4409 return D3DERR_INVALIDCALL;
4412 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
4413 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
4414 This->updateStateBlock->textureState[Stage][Type] = Value;
4419 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4420 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4421 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4422 *pValue = This->updateStateBlock->textureState[Stage][Type];
4429 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4431 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4432 IWineD3DBaseTexture *oldTexture;
4434 oldTexture = This->updateStateBlock->textures[Stage];
4435 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
4437 #if 0 /* TODO: check so vertex textures */
4438 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
4439 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
4444 /* Reject invalid texture units */
4445 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4446 WARN("Attempt to access invalid texture rejected\n");
4447 return D3DERR_INVALIDCALL;
4450 if(pTexture != NULL) {
4451 /* SetTexture isn't allowed on textures in D3DPOOL_SCRATCH; The same is
4452 * the case for D3DPOOL_SYSTEMMEM textures unless D3DDEVCAPS_TEXTURESYSTEMMORY is set.
4453 * We don't check the caps as GetDeviceCaps is inefficient and we don't set the cap anyway.
4455 if(((IWineD3DTextureImpl*)pTexture)->resource.pool == D3DPOOL_SCRATCH || ((IWineD3DTextureImpl*)pTexture)->resource.pool == D3DPOOL_SYSTEMMEM) {
4456 WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
4457 return D3DERR_INVALIDCALL;
4461 oldTexture = This->updateStateBlock->textures[Stage];
4462 TRACE("GL_LIMITS %d\n",GL_LIMITS(textures));
4463 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
4465 This->updateStateBlock->set.textures[Stage] = TRUE;
4466 This->updateStateBlock->changed.textures[Stage] = TRUE;
4467 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
4468 This->updateStateBlock->textures[Stage] = pTexture;
4470 /* Handle recording of state blocks */
4471 if (This->isRecordingState) {
4472 TRACE("Recording... not performing anything\n");
4476 /** NOTE: MSDN says that setTexture increases the reference count,
4477 * and the the application nust set the texture back to null (or have a leaky application),
4478 * This means we should pass the refcount up to the parent
4479 *******************************/
4480 if (NULL != This->updateStateBlock->textures[Stage]) {
4481 IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
4484 if (NULL != oldTexture) {
4485 IWineD3DBaseTexture_Release(oldTexture);
4491 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4492 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4493 TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
4495 /* Reject invalid texture units */
4496 if (Stage >= GL_LIMITS(textures)) {
4497 TRACE("Attempt to access invalid texture rejected\n");
4498 return D3DERR_INVALIDCALL;
4500 *ppTexture=This->updateStateBlock->textures[Stage];
4502 IWineD3DBaseTexture_AddRef(*ppTexture);
4504 return D3DERR_INVALIDCALL;
4511 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type,
4512 IWineD3DSurface **ppBackBuffer) {
4513 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4514 IWineD3DSwapChain *swapChain;
4517 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4519 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4521 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4522 IWineD3DSwapChain_Release(swapChain);
4524 *ppBackBuffer = NULL;
4529 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4530 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4531 WARN("(%p) : stub, calling idirect3d for now\n", This);
4532 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4535 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
4536 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4537 IWineD3DSwapChain *swapChain;
4540 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4542 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4543 IWineD3DSwapChain_Release(swapChain);
4545 FIXME("(%p) Error getting display mode\n", This);
4550 * Stateblock related functions
4553 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4554 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4555 IWineD3DStateBlockImpl *object;
4556 TRACE("(%p)", This);
4558 if (This->isRecordingState) {
4559 return D3DERR_INVALIDCALL;
4562 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4563 if (NULL == object ) {
4564 FIXME("(%p)Error allocating memory for stateblock\n", This);
4565 return E_OUTOFMEMORY;
4567 TRACE("(%p) creted object %p\n", This, object);
4568 object->wineD3DDevice= This;
4569 /** FIXME: object->parent = parent; **/
4570 object->parent = NULL;
4571 object->blockType = WINED3DSBT_ALL;
4573 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
4575 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4576 This->updateStateBlock = object;
4577 This->isRecordingState = TRUE;
4579 TRACE("(%p) recording stateblock %p\n",This , object);
4583 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4584 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4586 if (!This->isRecordingState) {
4587 FIXME("(%p) not recording! returning error\n", This);
4588 *ppStateBlock = NULL;
4589 return D3DERR_INVALIDCALL;
4592 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4593 This->isRecordingState = FALSE;
4594 This->updateStateBlock = This->stateBlock;
4595 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4596 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4597 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4602 * Scene related functions
4604 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4605 /* At the moment we have no need for any functionality at the beginning
4607 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4608 TRACE("(%p) : stub\n", This);
4612 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4613 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4614 TRACE("(%p)\n", This);
4616 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4618 checkGLcall("glFlush");
4620 TRACE("End Scene\n");
4621 if(This->renderTarget != NULL) {
4623 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4624 IUnknown *targetContainer = NULL;
4625 if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
4626 || D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
4627 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
4628 /** always dirtify for now. we must find a better way to see that surface have been modified
4629 (Modifications should will only occur via draw-primitive, but we do need better locking
4630 switching to render-to-texture should remove the overhead though.
4632 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4633 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
4634 IWineD3DSurface_PreLoad(This->renderTarget);
4635 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4636 IUnknown_Release(targetContainer);
4639 This->sceneEnded = TRUE;
4644 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4645 CONST RECT* pSourceRect, CONST RECT* pDestRect,
4646 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4647 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4648 IWineD3DSwapChain *swapChain = NULL;
4650 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4652 TRACE("(%p) Presenting the frame\n", This);
4654 for(i = 0 ; i < swapchains ; i ++) {
4656 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4657 TRACE("presentinng chain %d, %p\n", i, swapChain);
4658 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4659 IWineD3DSwapChain_Release(swapChain);
4665 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4666 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4667 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4669 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4670 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4671 when the depth-buffer format does not contain stencil buffer information, this method fails. */
4672 GLbitfield glMask = 0;
4673 GLboolean old_ztest;
4674 GLfloat old_z_clear_value;
4675 GLint old_stencil_clear_value;
4676 GLfloat old_color_clear_value[4];
4678 CONST D3DRECT* curRect;
4680 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4681 Count, pRects, Flags, Z, Stencil);
4685 glEnable(GL_SCISSOR_TEST);
4686 checkGLcall("glEnable GL_SCISSOR_TEST");
4688 if (Count > 0 && pRects) {
4694 /* Only set the values up once, as they are not changing */
4695 if (Flags & D3DCLEAR_STENCIL) {
4696 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4697 glClearStencil(Stencil);
4698 checkGLcall("glClearStencil");
4699 glMask = glMask | GL_STENCIL_BUFFER_BIT;
4700 glStencilMask(0xFFFFFFFF);
4703 if (Flags & D3DCLEAR_ZBUFFER) {
4704 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4705 glDepthMask(GL_TRUE);
4706 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4708 checkGLcall("glClearDepth");
4709 glMask = glMask | GL_DEPTH_BUFFER_BIT;
4712 if (Flags & D3DCLEAR_TARGET) {
4713 TRACE("Clearing screen with glClear to color %lx\n", Color);
4714 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4715 glClearColor(D3DCOLOR_R(Color),
4719 checkGLcall("glClearColor");
4721 /* Clear ALL colors! */
4722 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4723 glMask = glMask | GL_COLOR_BUFFER_BIT;
4726 /* Now process each rect in turn */
4727 for (i = 0; i < Count || i == 0; i++) {
4730 /* Note gl uses lower left, width/height */
4731 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4732 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4733 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4734 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4735 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4736 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4737 checkGLcall("glScissor");
4739 glScissor(This->stateBlock->viewport.X,
4740 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
4741 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4742 This->stateBlock->viewport.Width,
4743 This->stateBlock->viewport.Height);
4744 checkGLcall("glScissor");
4747 /* Clear the selected rectangle (or full screen) */
4749 checkGLcall("glClear");
4751 /* Step to the next rectangle */
4752 if (curRect) curRect = curRect + sizeof(D3DRECT);
4755 /* Restore the old values (why..?) */
4756 if (Flags & D3DCLEAR_STENCIL) {
4757 glClearStencil(old_stencil_clear_value);
4758 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4760 if (Flags & D3DCLEAR_ZBUFFER) {
4761 glDepthMask(old_ztest);
4762 glClearDepth(old_z_clear_value);
4764 if (Flags & D3DCLEAR_TARGET) {
4765 glClearColor(old_color_clear_value[0],
4766 old_color_clear_value[1],
4767 old_color_clear_value[2],
4768 old_color_clear_value[3]);
4769 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4770 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4771 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4772 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4775 glDisable(GL_SCISSOR_TEST);
4776 checkGLcall("glDisable");
4785 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4786 UINT PrimitiveCount) {
4788 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4789 This->stateBlock->streamIsUP = FALSE;
4791 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4792 debug_d3dprimitivetype(PrimitiveType),
4793 StartVertex, PrimitiveCount);
4794 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
4795 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
4801 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4802 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4803 D3DPRIMITIVETYPE PrimitiveType,
4804 INT baseVIndex, UINT minIndex,
4805 UINT NumVertices, UINT startIndex, UINT primCount) {
4807 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4809 IWineD3DIndexBuffer *pIB;
4810 D3DINDEXBUFFER_DESC IdxBufDsc;
4812 pIB = This->stateBlock->pIndexData;
4813 This->stateBlock->streamIsUP = FALSE;
4815 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
4816 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4817 minIndex, NumVertices, startIndex, baseVIndex, primCount);
4819 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4820 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4826 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
4827 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
4832 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4833 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4834 UINT VertexStreamZeroStride) {
4835 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4837 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4838 debug_d3dprimitivetype(PrimitiveType),
4839 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4841 /* release the stream source */
4842 if (This->stateBlock->streamSource[0] != NULL) {
4843 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
4846 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4847 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4848 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4849 This->stateBlock->streamIsUP = TRUE;
4851 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
4852 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
4853 /* stream zero settings set to null at end, as per the msdn
4854 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
4856 This->stateBlock->streamStride[0] = 0;
4857 This->stateBlock->streamSource[0] = NULL;
4859 /*stream zero settings set to null at end, as per the msdn */
4863 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4864 UINT MinVertexIndex, UINT NumVertices,
4865 UINT PrimitiveCount, CONST void* pIndexData,
4866 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4867 UINT VertexStreamZeroStride) {
4869 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4871 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4872 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4873 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
4874 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4876 if (IndexDataFormat == WINED3DFMT_INDEX16) {
4882 /* release the stream and index data */
4883 if (This->stateBlock->streamSource[0] != NULL) {
4884 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
4886 if (This->stateBlock->pIndexData) {
4887 IWineD3DIndexBuffer_Release(This->stateBlock->pIndexData);
4890 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4891 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4892 This->stateBlock->streamIsUP = TRUE;
4893 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4895 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
4896 /* stream zero settings set to null at end as per the msdn
4897 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
4900 /* stream zero settings set to null at end as per the msdn */
4901 This->stateBlock->streamSource[0] = NULL;
4902 This->stateBlock->streamStride[0] = 0;
4907 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4908 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
4909 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4910 HRESULT hr = D3D_OK;
4911 D3DRESOURCETYPE sourceType;
4912 D3DRESOURCETYPE destinationType;
4915 /* TODO: think about moving the code into IWineD3DBaseTexture */
4917 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
4919 /* verify that the source and destination textures aren't NULL */
4920 if (NULL == pSourceTexture || NULL == pDestinationTexture) {
4921 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning D3DERR_INVALIDCALL\n",
4922 This, pSourceTexture, pDestinationTexture);
4923 hr = D3DERR_INVALIDCALL;
4926 if (pSourceTexture == pDestinationTexture) {
4927 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning D3DERR_INVALIDCALL\n",
4928 This, pSourceTexture, pDestinationTexture);
4929 hr = D3DERR_INVALIDCALL;
4931 /* Verify that the source and destination textures are the same type */
4932 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
4933 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
4935 if (sourceType != destinationType) {
4936 WARN("(%p) Sorce and destination types must match, returning D3DERR_INVALIDCALL\n",
4938 hr = D3DERR_INVALIDCALL;
4941 /* check that both textures have the identical numbers of levels */
4942 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
4943 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning D3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
4944 hr = D3DERR_INVALIDCALL;
4949 /* Make sure that the destination texture is loaded */
4950 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
4952 /* Update every surface level of the texture */
4953 levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
4955 switch (sourceType) {
4956 case D3DRTYPE_TEXTURE:
4958 IWineD3DSurface *srcSurface;
4959 IWineD3DSurface *destSurface;
4961 for (i = 0 ; i < levels ; ++i) {
4962 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture, i, &srcSurface);
4963 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
4964 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4965 IWineD3DSurface_Release(srcSurface);
4966 IWineD3DSurface_Release(destSurface);
4968 WARN("(%p) : Call to update surface failed\n", This);
4974 case D3DRTYPE_CUBETEXTURE:
4976 IWineD3DSurface *srcSurface;
4977 IWineD3DSurface *destSurface;
4978 D3DCUBEMAP_FACES faceType;
4980 for (i = 0 ; i < levels ; ++i) {
4981 /* Update each cube face */
4982 for (faceType = D3DCUBEMAP_FACE_POSITIVE_X; faceType <= D3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
4983 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture, faceType, i, &srcSurface);
4985 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4987 TRACE("Got srcSurface %p\n", srcSurface);
4989 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
4991 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4993 TRACE("Got desrSurface %p\n", destSurface);
4995 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4996 IWineD3DSurface_Release(srcSurface);
4997 IWineD3DSurface_Release(destSurface);
4999 WARN("(%p) : Call to update surface failed\n", This);
5006 #if 0 /* TODO: Add support for volume textures */
5007 case D3DRTYPE_VOLUMETEXTURE:
5009 IWineD3DVolume srcVolume = NULL;
5010 IWineD3DSurface destVolume = NULL;
5012 for (i = 0 ; i < levels ; ++i) {
5013 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture, i, &srcVolume);
5014 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
5015 hr = IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
5016 IWineD3DVolume_Release(srcSurface);
5017 IWineD3DVolume_Release(destSurface);
5019 WARN("(%p) : Call to update volume failed\n", This);
5027 FIXME("(%p) : Unsupported source and destination type\n", This);
5028 hr = D3DERR_INVALIDCALL;
5035 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
5036 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
5037 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
5038 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5040 TRACE("(%p) : stub\n", This);
5043 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
5044 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5045 /** TODO: remove remove casts to IWineD3DSurfaceImpl *
5046 * NOTE It may be best to move the code into surface to occomplish this
5047 ****************************************/
5049 WINED3DSURFACE_DESC surfaceDesc;
5050 unsigned int surfaceWidth, surfaceHeight;
5051 glDescriptor *targetGlDescription = NULL;
5052 glDescriptor *surfaceGlDescription = NULL;
5053 IWineD3DSwapChainImpl *container = NULL;
5055 IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
5056 IWineD3DSurface_GetGlDesc(pSurface, &surfaceGlDescription);
5057 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5059 surfaceDesc.Width = &surfaceWidth;
5060 surfaceDesc.Height = &surfaceHeight;
5061 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5062 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
5064 /* Ok, I may need to setup some kind of active swapchain reference on the device */
5065 IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
5067 /* TODO: opengl Context switching for swapchains etc... */
5068 if (NULL != container || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
5069 if (NULL != container && (pRenderTarget == container->backBuffer)) {
5070 glReadBuffer(GL_BACK);
5071 vcheckGLcall("glReadBuffer(GL_BACK)");
5072 } else if ((NULL != container && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
5073 glReadBuffer(GL_FRONT);
5074 vcheckGLcall("glReadBuffer(GL_FRONT)");
5075 } else if (pRenderTarget == This->depthStencilBuffer) {
5076 FIXME("Reading of depthstencil not yet supported\n");
5079 glReadPixels(surfaceGlDescription->target,
5080 surfaceGlDescription->level,
5083 surfaceGlDescription->glFormat,
5084 surfaceGlDescription->glType,
5085 (void *)IWineD3DSurface_GetData(pSurface));
5086 vcheckGLcall("glReadPixels(...)");
5087 if(NULL != container ){
5088 IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
5091 IWineD3DBaseTexture *container;
5092 GLenum textureDimensions = GL_TEXTURE_2D;
5094 if (D3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
5095 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
5096 IWineD3DBaseTexture_Release(container);
5098 /* TODO: 2D -> Cube surface coppies etc.. */
5099 if (surfaceGlDescription->target != textureDimensions) {
5100 FIXME("(%p) : Texture dimension mismatch\n", This);
5102 glEnable(textureDimensions);
5103 vcheckGLcall("glEnable(GL_TEXTURE_...)");
5104 /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
5105 glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
5106 vcheckGLcall("glBindTexture");
5107 glGetTexImage(surfaceGlDescription->target,
5108 surfaceGlDescription->level,
5109 surfaceGlDescription->glFormat,
5110 surfaceGlDescription->glType,
5111 (void *)IWineD3DSurface_GetData(pSurface));
5112 glDisable(textureDimensions);
5113 vcheckGLcall("glDisable(GL_TEXTURE_...)");
5120 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
5121 IWineD3DSwapChain *swapChain;
5123 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5125 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
5126 IWineD3DSwapChain_Release(swapChain);
5131 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5132 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5133 /* return a sensible default */
5135 /* TODO: If the window is minimized then validate device should return something other than d3d_ok */
5136 FIXME("(%p) : stub\n", This);
5140 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5141 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5143 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5144 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5145 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5146 return D3DERR_INVALIDCALL;
5148 for (j = 0; j < 256; ++j) {
5149 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
5150 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5151 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
5152 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5154 TRACE("(%p) : returning\n", This);
5158 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5159 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5161 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5162 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5163 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5164 return D3DERR_INVALIDCALL;
5166 for (j = 0; j < 256; ++j) {
5167 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
5168 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5169 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
5170 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5172 TRACE("(%p) : returning\n", This);
5176 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5177 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5178 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5179 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5180 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5181 return D3DERR_INVALIDCALL;
5183 /*TODO: stateblocks */
5184 This->currentPalette = PaletteNumber;
5185 TRACE("(%p) : returning\n", This);
5189 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
5190 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5191 if (PaletteNumber == NULL) {
5192 WARN("(%p) : returning Invalid Call\n", This);
5193 return D3DERR_INVALIDCALL;
5195 /*TODO: stateblocks */
5196 *PaletteNumber = This->currentPalette;
5197 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
5201 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
5202 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5203 static BOOL showFixmes = TRUE;
5205 FIXME("(%p) : stub\n", This);
5209 This->softwareVertexProcessing = bSoftware;
5214 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
5215 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5216 static BOOL showFixmes = TRUE;
5218 FIXME("(%p) : stub\n", This);
5221 return This->softwareVertexProcessing;
5225 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
5226 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5227 IWineD3DSwapChain *swapChain;
5230 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
5232 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5234 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
5235 IWineD3DSwapChain_Release(swapChain);
5237 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
5243 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
5244 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5245 static BOOL showfixmes = TRUE;
5246 if(nSegments != 0.0f) {
5248 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
5255 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
5256 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5257 static BOOL showfixmes = TRUE;
5259 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
5265 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
5266 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5267 /** TODO: remove casts to IWineD3DSurfaceImpl
5268 * NOTE: move code to surface to accomplish this
5269 ****************************************/
5270 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
5271 int srcWidth, srcHeight;
5272 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
5273 WINED3DFORMAT destFormat, srcFormat;
5275 int destLeft, destTop;
5276 D3DPOOL srcPool, destPool;
5278 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
5279 glDescriptor *glDescription = NULL;
5280 GLenum textureDimensions = GL_TEXTURE_2D;
5281 IWineD3DBaseTexture *baseTexture;
5283 WINED3DSURFACE_DESC winedesc;
5285 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
5286 memset(&winedesc, 0, sizeof(winedesc));
5287 winedesc.Width = &srcSurfaceWidth;
5288 winedesc.Height = &srcSurfaceHeight;
5289 winedesc.Pool = &srcPool;
5290 winedesc.Format = &srcFormat;
5292 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5294 winedesc.Width = &destSurfaceWidth;
5295 winedesc.Height = &destSurfaceHeight;
5296 winedesc.Pool = &destPool;
5297 winedesc.Format = &destFormat;
5298 winedesc.Size = &destSize;
5300 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5302 if(srcPool != D3DPOOL_SYSTEMMEM || destPool != D3DPOOL_DEFAULT){
5303 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning D3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
5304 return D3DERR_INVALIDCALL;
5307 if (destFormat == WINED3DFMT_UNKNOWN) {
5308 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5309 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5311 /* Get the update surface description */
5312 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5315 /* Make sure the surface is loaded and up to date */
5316 IWineD3DSurface_PreLoad(pDestinationSurface);
5318 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
5322 /* this needs to be done in lines if the sourceRect != the sourceWidth */
5323 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
5324 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
5325 destLeft = pDestPoint ? pDestPoint->x : 0;
5326 destTop = pDestPoint ? pDestPoint->y : 0;
5329 /* This function doesn't support compressed textures
5330 the pitch is just bytesPerPixel * width */
5331 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
5332 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
5333 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
5334 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
5336 /* TODO DXT formats */
5338 if(pSourceRect != NULL && pSourceRect->top != 0){
5339 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
5341 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
5343 ,glDescription->level
5348 ,glDescription->glFormat
5349 ,glDescription->glType
5350 ,IWineD3DSurface_GetData(pSourceSurface)
5354 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
5356 /* need to lock the surface to get the data */
5357 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5360 /* TODO: Cube and volume support */
5362 /* not a whole row so we have to do it a line at a time */
5365 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
5366 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5368 for(j = destTop ; j < (srcHeight + destTop) ; j++){
5370 glTexSubImage2D(glDescription->target
5371 ,glDescription->level
5376 ,glDescription->glFormat
5377 ,glDescription->glType
5378 ,data /* could be quicker using */
5383 } else { /* Full width, so just write out the whole texture */
5385 if (WINED3DFMT_DXT1 == destFormat ||
5386 WINED3DFMT_DXT2 == destFormat ||
5387 WINED3DFMT_DXT3 == destFormat ||
5388 WINED3DFMT_DXT4 == destFormat ||
5389 WINED3DFMT_DXT5 == destFormat) {
5390 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
5391 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
5392 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
5393 FIXME("Updating part of a compressed texture is not supported at the moment\n");
5394 } if (destFormat != srcFormat) {
5395 FIXME("Updating mixed format compressed texture is not curretly support\n");
5397 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
5398 glDescription->level,
5399 glDescription->glFormatInternal,
5404 IWineD3DSurface_GetData(pSourceSurface));
5407 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
5412 if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
5414 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
5415 to repack the data from pow2Width/Height to expected Width,Height, this makes the
5416 data returned by GetData non-power2 width/height with hardware non-power2
5417 pow2Width/height are set to surface width height, repacking isn't needed so it
5418 doesn't matter which function gets called. */
5419 glTexSubImage2D(glDescription->target
5420 ,glDescription->level
5425 ,glDescription->glFormat
5426 ,glDescription->glType
5427 ,IWineD3DSurface_GetData(pSourceSurface)
5431 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
5432 glTexSubImage2D(glDescription->target
5433 ,glDescription->level
5436 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
5437 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
5438 ,glDescription->glFormat
5439 ,glDescription->glType
5440 ,IWineD3DSurface_GetData(pSourceSurface)
5446 checkGLcall("glTexSubImage2D");
5448 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
5449 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
5450 * surface bigger than it needs to be hmm.. */
5451 if (D3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
5452 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
5453 IWineD3DBaseTexture_Release(baseTexture);
5456 glDisable(textureDimensions); /* This needs to be managed better.... */
5462 /* Used by DirectX 8 */
5463 HRESULT WINAPI IWineD3DDeviceImpl_CopyRects(IWineD3DDevice *iface,
5464 IWineD3DSurface* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
5465 IWineD3DSurface* pDestinationSurface, CONST POINT* pDestPointsArray) {
5467 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5468 HRESULT hr = D3D_OK;
5469 WINED3DFORMAT srcFormat, destFormat;
5470 UINT srcWidth, destWidth;
5471 UINT srcHeight, destHeight;
5473 WINED3DSURFACE_DESC winedesc;
5475 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
5476 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
5479 /* Check that the source texture is in D3DPOOL_SYSTEMMEM and the destination texture is in D3DPOOL_DEFAULT */
5480 memset(&winedesc, 0, sizeof(winedesc));
5482 winedesc.Format = &srcFormat;
5483 winedesc.Width = &srcWidth;
5484 winedesc.Height = &srcHeight;
5485 winedesc.Size = &srcSize;
5486 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5488 winedesc.Format = &destFormat;
5489 winedesc.Width = &destWidth;
5490 winedesc.Height = &destHeight;
5491 winedesc.Size = NULL;
5492 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5494 /* Check that the source and destination formats match */
5495 if (srcFormat != destFormat && WINED3DFMT_UNKNOWN != destFormat) {
5496 WARN("(%p) source %p format must match the dest %p format, returning D3DERR_INVALIDCALL\n", This, pSourceSurface, pDestinationSurface);
5497 return D3DERR_INVALIDCALL;
5498 } else if (WINED3DFMT_UNKNOWN == destFormat) {
5499 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5500 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5501 destFormat = srcFormat;
5504 /* Quick if complete copy ... */
5505 if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
5507 if (srcWidth == destWidth && srcHeight == destHeight) {
5508 D3DLOCKED_RECT lrSrc;
5509 D3DLOCKED_RECT lrDst;
5510 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, NULL, D3DLOCK_READONLY);
5511 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, NULL, 0L);
5512 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", srcWidth, srcHeight);
5514 memcpy(lrDst.pBits, lrSrc.pBits, srcSize);
5516 IWineD3DSurface_UnlockRect(pSourceSurface);
5517 IWineD3DSurface_UnlockRect(pDestinationSurface);
5518 TRACE("Unlocked src and dst\n");
5522 FIXME("Wanted to copy all surfaces but size not compatible, returning D3DERR_INVALIDCALL\n");
5523 hr = D3DERR_INVALIDCALL;
5528 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
5530 int bytesPerPixel = ((IWineD3DSurfaceImpl *) pSourceSurface)->bytesPerPixel;
5533 /* Copy rect by rect */
5534 for (i = 0; i < cRects; ++i) {
5535 CONST RECT* r = &pSourceRectsArray[i];
5536 CONST POINT* p = &pDestPointsArray[i];
5539 D3DLOCKED_RECT lrSrc;
5540 D3DLOCKED_RECT lrDst;
5543 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
5544 if (srcFormat == WINED3DFMT_DXT1) {
5545 copyperline = ((r->right - r->left) * bytesPerPixel) / 2; /* DXT1 is half byte per pixel */
5547 copyperline = ((r->right - r->left) * bytesPerPixel);
5550 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, r, D3DLOCK_READONLY);
5551 dest_rect.left = p->x;
5552 dest_rect.top = p->y;
5553 dest_rect.right = p->x + (r->right - r->left);
5554 dest_rect.bottom= p->y + (r->bottom - r->top);
5555 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, &dest_rect, 0L);
5556 TRACE("Locked src and dst\n");
5558 /* Find where to start */
5559 for (j = 0; j < (r->bottom - r->top - 1); ++j) {
5560 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
5562 IWineD3DSurface_UnlockRect(pSourceSurface);
5563 IWineD3DSurface_UnlockRect(pDestinationSurface);
5564 TRACE("Unlocked src and dst\n");
5567 FIXME("Wanted to copy partial surfaces not implemented, returning D3DERR_INVALIDCALL\n");
5568 hr = D3DERR_INVALIDCALL;
5575 /* Implementation details at http://developer.nvidia.com/attach/6494
5577 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
5578 hmm.. no longer supported use
5579 OpenGL evaluators or tessellate surfaces within your application.
5582 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
5583 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
5584 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5585 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
5586 FIXME("(%p) : Stub\n", This);
5591 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
5592 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
5593 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5594 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
5595 FIXME("(%p) : Stub\n", This);
5599 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5600 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5601 TRACE("(%p) Handle(%d)\n", This, Handle);
5602 FIXME("(%p) : Stub\n", This);
5606 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
5607 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
5608 fill a surface with a block of color! */
5609 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5610 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
5611 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
5612 IWineD3DSwapChainImpl *container = NULL;
5613 BOOL isRenderTarget = FALSE;
5614 unsigned int width, height;
5615 unsigned int top, left;
5618 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
5620 if (surface->resource.pool != D3DPOOL_DEFAULT) {
5621 FIXME("call to colorfill with non D3DPOOL_DEFAULT surface\n");
5622 return D3DERR_INVALIDCALL;
5625 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
5626 if (D3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
5627 if (D3DUSAGE_RENDERTARGET & surface->resource.usage) {
5628 /* TODO: make sure we set everything back to the way it was, and context management!
5629 glGetIntegerv(GL_READ_BUFFER, &prev_read);
5630 vcheckGLcall("glIntegerv");
5631 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
5632 vcheckGLcall("glIntegerv");
5634 TRACE("Color fill to render targets may cause some graphics issues\n");
5635 if (pSurface == container->frontBuffer) {
5636 glDrawBuffer(GL_FRONT);
5638 glDrawBuffer(GL_BACK);
5641 if (D3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
5642 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld\n", surface, surface->resource.usage);
5644 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
5646 if (container != NULL) {
5647 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5649 /* we can use GL_STENCIL_INDEX etc...*/
5652 if (container != NULL) {
5653 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5655 isRenderTarget = TRUE;
5657 /* TODO: drawing to GL_FRONT and GL_BACK */
5658 /* TODO: see if things can be speeded up by using the correct
5659 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
5660 if (pRect == NULL) {
5663 width = surface->currentDesc.Width;
5664 height = surface->currentDesc.Height;
5668 width = pRect->x2 - left;
5669 height = pRect->y2 - top;
5672 data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
5673 /* Create a 'line' of color color, in the correct format for the surface */
5674 for (u = 0 ; u < width ; u ++) {
5679 if (isRenderTarget == FALSE) {
5680 glDescriptor *glDesc;
5681 IWineD3DSurface_PreLoad(pSurface);
5683 /* draw a block of the coloured line on the sufrace */
5684 IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
5685 for (v = 0 ; v< height;v++) {
5686 glTexSubImage2D(glDesc->target
5687 ,glDesc->level /* level */
5697 checkGLcall("glTexSubImage2D");
5699 glDisable(glDesc->target);
5701 /** FIXME: Using GLClear may be faster **/
5702 glRasterPos2i(left, top);
5703 glPixelZoom((float)width ,(float)height);
5704 glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
5705 checkGLcall("glDrawPixels");
5707 HeapFree(GetProcessHeap(), 0, data);
5713 /* rendertarget and deptth stencil functions */
5714 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
5715 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5717 /* FIXME: Implelent RenderTargetIndex >0 */
5718 if(RenderTargetIndex > 0)
5719 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
5721 *ppRenderTarget = This->renderTarget;
5722 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
5723 /* Note inc ref on returned surface */
5724 if(*ppRenderTarget != NULL)
5725 IWineD3DSurface_AddRef(*ppRenderTarget);
5729 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5730 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5731 *ppZStencilSurface = This->depthStencilBuffer;
5732 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
5734 if(*ppZStencilSurface != NULL) {
5735 /* Note inc ref on returned surface */
5736 IWineD3DSurface_AddRef(*ppZStencilSurface);
5741 /* internal static helper functions */
5742 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5743 IWineD3DSurface *RenderSurface);
5745 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5746 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5747 HRESULT hr = D3D_OK;
5748 WINED3DVIEWPORT viewport;
5750 TRACE("(%p) Swapping rendertarget\n",This);
5751 if (RenderTargetIndex > 0) {
5752 FIXME("(%p) Render targets other than the first are not supported\n",This);
5753 RenderTargetIndex = 0;
5756 /* MSDN says that null disables the render target
5757 but a device must always be associated with a render target
5758 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5760 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5763 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5764 FIXME("Trying to set render target 0 to NULL\n");
5765 return D3DERR_INVALIDCALL;
5767 /* TODO: replace Impl* usage with interface usage */
5768 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & D3DUSAGE_RENDERTARGET) {
5769 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);
5770 return D3DERR_INVALIDCALL;
5772 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
5773 * builds, but I think wine counts as a 'debug' build for now.
5774 ******************************/
5775 /* If we are trying to set what we already have, don't bother */
5776 if (pRenderTarget == This->renderTarget) {
5777 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5779 /* Otherwise, set the render target up */
5781 if (FALSE == This->sceneEnded) {
5782 IWineD3DDevice_EndScene(iface);
5784 TRACE("clearing renderer\n");
5785 /* IWineD3DDeviceImpl_CleanRender(iface); */
5786 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5787 depending on the renter target implementation being used.
5788 A shared context implementation will share all buffers between all rendertargets (including swapchains),
5789 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5790 stencil buffer and incure an extra memory overhead */
5791 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
5794 if (SUCCEEDED(hr)) {
5795 /* Finally, reset the viewport as the MSDN states. */
5796 /* TODO: Replace impl usage */
5797 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
5798 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
5801 viewport.MaxZ = 1.0f;
5802 viewport.MinZ = 0.0f;
5803 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
5805 FIXME("Unknown error setting the render target\n");
5807 This->sceneEnded = FALSE;
5811 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
5812 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5813 HRESULT hr = D3D_OK;
5814 IWineD3DSurface *tmp;
5816 TRACE("(%p) Swapping z-buffer\n",This);
5818 if (pNewZStencil == This->stencilBufferTarget) {
5819 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5821 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5822 * depending on the renter target implementation being used.
5823 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5824 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5825 * stencil buffer and incure an extra memory overhead
5826 ******************************************************/
5829 tmp = This->stencilBufferTarget;
5830 This->stencilBufferTarget = pNewZStencil;
5831 /* should we be calling the parent or the wined3d surface? */
5832 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
5833 if (NULL != tmp) IWineD3DSurface_Release(tmp);
5835 /** TODO: glEnable/glDisable on depth/stencil depending on
5836 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
5837 **********************************************************/
5844 #ifdef GL_VERSION_1_3
5845 /* Internal functions not in DirectX */
5846 /** TODO: move this off to the opengl context manager
5847 *(the swapchain doesn't need to know anything about offscreen rendering!)
5848 ****************************************************/
5850 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
5852 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5854 TRACE("(%p), %p\n", This, swapchain);
5856 if (swapchain->win != swapchain->drawable) {
5857 /* Set everything back the way it ws */
5858 swapchain->render_ctx = swapchain->glCtx;
5859 swapchain->drawable = swapchain->win;
5864 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
5865 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
5866 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5869 unsigned int height;
5870 WINED3DFORMAT format;
5871 WINED3DSURFACE_DESC surfaceDesc;
5872 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5873 surfaceDesc.Width = &width;
5874 surfaceDesc.Height = &height;
5875 surfaceDesc.Format = &format;
5876 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5878 /* I need a get width/height function (and should do something with the format) */
5879 for (i = 0; i < CONTEXT_CACHE; ++i) {
5880 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
5881 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
5882 the pSurface can be set to 0 allowing it to be reused from cache **/
5883 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
5884 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
5885 *context = &This->contextCache[i];
5888 if (This->contextCache[i].Width == 0) {
5889 This->contextCache[i].pSurface = pSurface;
5890 This->contextCache[i].Width = width;
5891 This->contextCache[i].Height = height;
5892 *context = &This->contextCache[i];
5896 if (i == CONTEXT_CACHE) {
5897 int minUsage = 0x7FFFFFFF; /* MAX_INT */
5898 glContext *dropContext = 0;
5899 for (i = 0; i < CONTEXT_CACHE; i++) {
5900 if (This->contextCache[i].usedcount < minUsage) {
5901 dropContext = &This->contextCache[i];
5902 minUsage = This->contextCache[i].usedcount;
5905 /* clean up the context (this doesn't work for ATI at the moment */
5907 glXDestroyContext(swapchain->display, dropContext->context);
5908 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
5911 dropContext->Width = 0;
5912 dropContext->pSurface = pSurface;
5913 *context = dropContext;
5915 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
5916 for (i = 0; i < CONTEXT_CACHE; i++) {
5917 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
5921 if (*context != NULL)
5924 return E_OUTOFMEMORY;
5928 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
5929 * the functionality needs splitting up so that we don't do more than we should do.
5930 * this only seems to impact performance a little.
5931 ******************************/
5932 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5933 IWineD3DSurface *RenderSurface) {
5934 HRESULT ret = D3DERR_INVALIDCALL;
5937 * Currently only active for GLX >= 1.3
5938 * for others versions we'll have to use GLXPixmaps
5940 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
5941 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
5942 * so only check OpenGL version
5943 * ..........................
5944 * I don't believe that it is a problem with NVidia headers,
5945 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
5946 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
5948 * Your application will report GLX version 1.2 on glXQueryVersion.
5949 * However, it is safe to call the GLX 1.3 functions as described below.
5951 #if defined(GL_VERSION_1_3)
5953 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5954 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
5955 IWineD3DSurface *tmp;
5956 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
5957 GLXFBConfig* cfgs = NULL;
5961 IWineD3DSwapChain *currentSwapchain;
5962 IWineD3DSwapChainImpl *swapchain;
5963 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
5964 * but switch them off if the StencilSurface is set to NULL
5965 ** *********************************************************/
5966 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
5967 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
5970 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
5971 it StencilSurface != NULL && zBufferTarget == NULL switch it on
5974 #define PUSH1(att) attribs[nAttribs++] = (att);
5975 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
5977 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
5979 /** TODO: remove the reff to Impl (context manager should fix this!) **/
5980 IWineD3DSwapChainImpl *impSwapChain;
5981 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
5982 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
5983 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
5988 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
5989 PUSH2(GLX_X_RENDERABLE, TRUE);
5990 PUSH2(GLX_DOUBLEBUFFER, TRUE);
5991 TRACE("calling makeglcfg\n");
5992 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
5995 TRACE("calling chooseFGConfig\n");
5996 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5999 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
6000 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
6001 why we failed and only show this message once! */
6002 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"); /**/
6004 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
6005 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
6006 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
6007 PUSH2(GLX_DOUBLEBUFFER, FALSE);
6008 TRACE("calling makeglcfg\n");
6009 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
6011 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
6018 for (i = 0; i < nCfgs; ++i) {
6019 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
6020 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
6021 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
6024 if (NULL != This->renderTarget) {
6026 vcheckGLcall("glFlush");
6027 /** This is only useful if the old render target was a swapchain,
6028 * we need to supercede this with a function that displays
6029 * the current buffer on the screen. This is easy to do in glx1.3 but
6030 * we need to do copy-write pixels in glx 1.2.
6031 ************************************************/
6032 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
6034 printf("Hit Enter to get next frame ...\n");
6040 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain) != D3D_OK) {
6041 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
6042 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
6046 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
6047 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
6048 **********************************************************************/
6049 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == D3D_OK) {
6050 /* We also need to make sure that the lights &co are also in the context of the swapchains */
6051 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
6052 TRACE("making swapchain active\n");
6053 if (RenderSurface != This->renderTarget) {
6054 if (RenderSurface == swapchain->backBuffer) {
6056 /* This could be flagged so that some operations work directly with the front buffer */
6057 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
6059 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
6061 TRACE("Error in setting current context: context %p drawable %ld !\n",
6062 impSwapChain->glCtx, impSwapChain->win);
6065 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
6067 checkGLcall("glXMakeContextCurrent");
6069 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
6071 else if (pbuffer_support == TRUE && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
6073 /** ********************************************************************
6074 * This is a quickly hacked out implementation of offscreen textures.
6075 * It will work in most cases but there may be problems if the client
6076 * modifies the texture directly, or expects the contents of the rendertarget
6079 * There are some real speed vs compatibility issues here:
6080 * we should really use a new context for every texture, but that eats ram.
6081 * we should also be restoring the texture to the pbuffer but that eats CPU
6082 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
6083 * but if this means reusing the display backbuffer then we need to make sure that
6084 * states are correctly preserved.
6085 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
6086 * and gain a good performance increase at the cost of compatibility.
6087 * I would suggest that, when this is the case, a user configurable flag be made
6088 * available, allowing the user to choose the best emulated experience for them.
6089 *********************************************************************/
6091 XVisualInfo *visinfo;
6092 glContext *newContext;
6094 /* Here were using a shared context model */
6095 if (D3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
6096 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6099 /* If the context doesn't exist then create a new one */
6100 /* TODO: This should really be part of findGlContext */
6101 if (NULL == newContext->context) {
6103 TRACE("making new buffer\n");
6105 PUSH2(GLX_PBUFFER_WIDTH, newContext->Width);
6106 PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
6109 newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
6111 /** ****************************************
6112 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
6114 * In future releases, we may provide the calls glXCreateNewContext,
6115 * glXQueryDrawable and glXMakeContextCurrent.
6116 * so until then we have to use glXGetVisualFromFBConfig &co..
6117 ********************************************/
6120 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
6122 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
6124 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
6128 if (NULL == newContext || NULL == newContext->context) {
6129 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6131 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
6132 if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
6133 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
6136 /* Clean up the old context */
6137 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
6138 /* Set the current context of the swapchain to the new context */
6139 impSwapChain->drawable = newContext->drawable;
6140 impSwapChain->render_ctx = newContext->context;
6144 #if 1 /* Apply the stateblock to the new context
6145 FIXME: This is a bit of a hack, each context should know it's own state,
6146 the directX current directX state should then be applied to the context */
6149 IWineD3DStateBlockImpl *oldUpdateStateBlock;
6150 oldUpdateStateBlock = This->updateStateBlock;
6151 oldRecording= This->isRecordingState;
6152 This->isRecordingState = FALSE;
6153 This->updateStateBlock = This->stateBlock;
6154 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
6156 This->isRecordingState = oldRecording;
6157 This->updateStateBlock = oldUpdateStateBlock;
6162 /* clean up the current rendertargets swapchain (if it belonged to one) */
6163 if (currentSwapchain != NULL) {
6164 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
6167 /* Were done with the opengl context management, setup the rendertargets */
6169 tmp = This->renderTarget;
6170 This->renderTarget = RenderSurface;
6171 IWineD3DSurface_AddRef(This->renderTarget);
6172 IWineD3DSurface_Release(tmp);
6178 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
6179 /* Check that the container is not a swapchain member */
6181 IWineD3DSwapChain *tmpSwapChain;
6182 if (D3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
6183 This->renderUpsideDown = TRUE;
6185 This->renderUpsideDown = FALSE;
6186 IWineD3DSwapChain_Release(tmpSwapChain);
6188 /* Force updating the cull mode */
6189 TRACE("setting render state\n");
6190 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
6191 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
6193 /* Force updating projection matrix */
6194 This->last_was_rhw = FALSE;
6195 This->proj_valid = FALSE;
6203 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
6204 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
6209 if ( NULL != impSwapChain) {
6210 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
6218 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
6219 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
6220 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6221 /* TODO: the use of Impl is deprecated. */
6222 /* some basic validation checks */
6223 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
6225 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
6227 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
6228 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
6229 return D3DERR_INVALIDCALL;
6231 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
6232 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
6233 return D3DERR_INVALIDCALL;
6235 /* TODO: make the cursor 'real' */
6237 This->xHotSpot = XHotSpot;
6238 This->yHotSpot = YHotSpot;
6243 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
6244 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6245 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
6247 This->xScreenSpace = XScreenSpace;
6248 This->yScreenSpace = YScreenSpace;
6254 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
6255 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6256 TRACE("(%p) : visible(%d)\n", This, bShow);
6258 This->bCursorVisible = bShow;
6263 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
6264 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6265 TRACE("(%p) : state (%lu)\n", This, This->state);
6266 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
6267 switch (This->state) {
6270 case D3DERR_DEVICELOST:
6272 ResourceList *resourceList = This->resources;
6273 while (NULL != resourceList) {
6274 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == D3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
6275 return D3DERR_DEVICENOTRESET;
6276 resourceList = resourceList->next;
6278 return D3DERR_DEVICELOST;
6280 case D3DERR_DRIVERINTERNALERROR:
6281 return D3DERR_DRIVERINTERNALERROR;
6285 return D3DERR_DRIVERINTERNALERROR;
6289 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
6290 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6291 /** FIXME: Resource tracking needs to be done,
6292 * The closes we can do to this is set the priorities of all managed textures low
6293 * and then reset them.
6294 ***********************************************************/
6295 FIXME("(%p) : stub\n", This);
6299 HRESULT WINAPI IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
6300 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6301 /** FIXME: Resource trascking needs to be done.
6302 * in effect this pulls all non only default
6303 * textures out of video memory and deletes all glTextures (glDeleteTextures)
6304 * and should clear down the context and set it up according to pPresentationParameters
6305 ***********************************************************/
6306 FIXME("(%p) : stub\n", This);
6310 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
6311 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6312 /** FIXME: always true at the moment **/
6313 if(bEnableDialogs == FALSE) {
6314 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
6320 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
6321 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6323 FIXME("(%p) : stub\n", This);
6324 /* Setup some reasonable defaults */
6325 pParameters->AdapterOrdinal = 0; /* always for now */
6326 pParameters->DeviceType = D3DDEVTYPE_HAL; /* always for now */
6327 pParameters->hFocusWindow = 0;
6328 pParameters->BehaviorFlags =0;
6332 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
6333 IWineD3DSwapChain *swapchain;
6334 HRESULT hrc = D3D_OK;
6336 TRACE("Relaying to swapchain\n");
6338 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
6339 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (D3DGAMMARAMP *)pRamp);
6340 IWineD3DSwapChain_Release(swapchain);
6345 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
6346 IWineD3DSwapChain *swapchain;
6347 HRESULT hrc = D3D_OK;
6349 TRACE("Relaying to swapchain\n");
6351 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
6352 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
6353 IWineD3DSwapChain_Release(swapchain);
6359 /** ********************************************************
6360 * Notification functions
6361 ** ********************************************************/
6362 /** This function must be called in the release of a resource when ref == 0,
6363 * the contents of resource must still be correct,
6364 * any handels to other resource held by the caller must be closed
6365 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
6366 *****************************************************/
6367 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6368 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6369 ResourceList* resourceList;
6371 TRACE("(%p) : resource %p\n", This, resource);
6373 EnterCriticalSection(&resourceStoreCriticalSection);
6375 /* add a new texture to the frot of the linked list */
6376 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
6377 resourceList->resource = resource;
6379 /* Get the old head */
6380 resourceList->next = This->resources;
6382 This->resources = resourceList;
6383 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
6386 LeaveCriticalSection(&resourceStoreCriticalSection);
6391 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6392 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6393 ResourceList* resourceList = NULL;
6394 ResourceList* previousResourceList = NULL;
6396 TRACE("(%p) : resource %p\n", This, resource);
6399 EnterCriticalSection(&resourceStoreCriticalSection);
6401 resourceList = This->resources;
6403 while (resourceList != NULL) {
6404 if(resourceList->resource == resource) break;
6405 previousResourceList = resourceList;
6406 resourceList = resourceList->next;
6409 if (resourceList == NULL) {
6410 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
6412 LeaveCriticalSection(&resourceStoreCriticalSection);
6416 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
6418 /* make sure we don't leave a hole in the list */
6419 if (previousResourceList != NULL) {
6420 previousResourceList->next = resourceList->next;
6422 This->resources = resourceList->next;
6426 LeaveCriticalSection(&resourceStoreCriticalSection);
6432 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
6433 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6436 TRACE("(%p) : resource %p\n", This, resource);
6437 switch(IWineD3DResource_GetType(resource)){
6438 case D3DRTYPE_SURFACE:
6439 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
6441 case D3DRTYPE_TEXTURE:
6442 case D3DRTYPE_CUBETEXTURE:
6443 case D3DRTYPE_VOLUMETEXTURE:
6444 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
6445 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6446 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6447 This->stateBlock->textures[counter] = NULL;
6449 if (This->updateStateBlock != This->stateBlock ){
6450 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6451 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6452 This->updateStateBlock->textures[counter] = NULL;
6457 case D3DRTYPE_VOLUME:
6458 /* TODO: nothing really? */
6460 case D3DRTYPE_VERTEXBUFFER:
6461 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
6464 TRACE("Cleaning up stream pointers\n");
6466 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
6467 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
6468 FINDOUT: should changes.streamSource[StreamNumber] be set ?
6470 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6471 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
6472 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
6473 This->updateStateBlock->streamSource[streamNumber] = 0;
6474 /* Set changed flag? */
6477 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) */
6478 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
6479 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
6480 This->stateBlock->streamSource[streamNumber] = 0;
6483 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
6484 else { /* This shouldn't happen */
6485 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
6492 case D3DRTYPE_INDEXBUFFER:
6493 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
6494 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6495 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6496 This->updateStateBlock->pIndexData = NULL;
6499 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
6500 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6501 This->stateBlock->pIndexData = NULL;
6507 FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
6512 /* Remove the resoruce from the resourceStore */
6513 IWineD3DDeviceImpl_RemoveResource(iface, resource);
6515 TRACE("Resource released\n");
6520 /** This function is to be called by the swapchain when it is released and it's ref = 0
6521 *****************************************************/
6522 void WINAPI IWineD3DDeviceImpl_SwapChainReleased(IWineD3DDevice *iface, IWineD3DSwapChain *swapChain){
6523 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6524 SwapChainList **nextSwapchain;
6525 nextSwapchain = &This->swapchains;
6527 /* Check to see if the swapchian is being used as the render target */
6528 if (This->renderTarget != NULL) {
6529 IWineD3DSurface *swapchainBackBuffer;
6531 IWineD3DSwapChain_GetBackBuffer(swapChain, 0 ,( D3DBACKBUFFER_TYPE) 0, &swapchainBackBuffer);
6532 if (This->renderTarget == swapchainBackBuffer) {
6533 /* Don't know what to do, so warn and carry on as usual (which in this case leaves the renderterget in limbo) */
6534 FIXME("Atempting to release a swapchain that is currently beuing used as a render target, behaviour is undefined\n");
6538 /* Go through the swapchain list and try to find the swapchain being released */
6539 while(*nextSwapchain != NULL && (*nextSwapchain)->swapchain != swapChain) {
6540 nextSwapchain = &(*nextSwapchain)->next;
6543 /* Check to see if we found the swapchain */
6544 if (NULL != *nextSwapchain) {
6545 /* We found the swapchain so remove it from the list */
6546 TRACE("(%p) releasing swapchain(%p)\n", iface, swapChain);
6547 HeapFree(GetProcessHeap(), 0 , *nextSwapchain);
6548 *nextSwapchain = (*nextSwapchain)->next;
6550 /* We didn't find the swapchain on the list, this can only heppen because of a programming error in wined3d */
6551 FIXME("(%p) Attempting to release a swapchain (%p) that hasn't been stored\n", iface, swapChain);
6554 TRACE("swapchain (%p) released\n", swapChain);
6558 /**********************************************************
6559 * IWineD3DDevice VTbl follows
6560 **********************************************************/
6562 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
6564 /*** IUnknown methods ***/
6565 IWineD3DDeviceImpl_QueryInterface,
6566 IWineD3DDeviceImpl_AddRef,
6567 IWineD3DDeviceImpl_Release,
6568 /*** IWineD3DDevice methods ***/
6569 IWineD3DDeviceImpl_GetParent,
6570 /*** Creation methods**/
6571 IWineD3DDeviceImpl_CreateVertexBuffer,
6572 IWineD3DDeviceImpl_CreateIndexBuffer,
6573 IWineD3DDeviceImpl_CreateStateBlock,
6574 IWineD3DDeviceImpl_CreateSurface,
6575 IWineD3DDeviceImpl_CreateTexture,
6576 IWineD3DDeviceImpl_CreateVolumeTexture,
6577 IWineD3DDeviceImpl_CreateVolume,
6578 IWineD3DDeviceImpl_CreateCubeTexture,
6579 IWineD3DDeviceImpl_CreateQuery,
6580 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
6581 IWineD3DDeviceImpl_CreateVertexDeclaration,
6582 IWineD3DDeviceImpl_CreateVertexShader,
6583 IWineD3DDeviceImpl_CreatePixelShader,
6584 /*** Odd functions **/
6585 IWineD3DDeviceImpl_EvictManagedResources,
6586 IWineD3DDeviceImpl_GetAvailableTextureMem,
6587 IWineD3DDeviceImpl_GetBackBuffer,
6588 IWineD3DDeviceImpl_GetCreationParameters,
6589 IWineD3DDeviceImpl_GetDeviceCaps,
6590 IWineD3DDeviceImpl_GetDirect3D,
6591 IWineD3DDeviceImpl_GetDisplayMode,
6592 IWineD3DDeviceImpl_GetNumberOfSwapChains,
6593 IWineD3DDeviceImpl_GetRasterStatus,
6594 IWineD3DDeviceImpl_GetSwapChain,
6595 IWineD3DDeviceImpl_Reset,
6596 IWineD3DDeviceImpl_SetDialogBoxMode,
6597 IWineD3DDeviceImpl_SetCursorProperties,
6598 IWineD3DDeviceImpl_SetCursorPosition,
6599 IWineD3DDeviceImpl_ShowCursor,
6600 IWineD3DDeviceImpl_TestCooperativeLevel,
6601 /*** Getters and setters **/
6602 IWineD3DDeviceImpl_SetClipPlane,
6603 IWineD3DDeviceImpl_GetClipPlane,
6604 IWineD3DDeviceImpl_SetClipStatus,
6605 IWineD3DDeviceImpl_GetClipStatus,
6606 IWineD3DDeviceImpl_SetCurrentTexturePalette,
6607 IWineD3DDeviceImpl_GetCurrentTexturePalette,
6608 IWineD3DDeviceImpl_SetDepthStencilSurface,
6609 IWineD3DDeviceImpl_GetDepthStencilSurface,
6610 IWineD3DDeviceImpl_SetFVF,
6611 IWineD3DDeviceImpl_GetFVF,
6612 IWineD3DDeviceImpl_SetGammaRamp,
6613 IWineD3DDeviceImpl_GetGammaRamp,
6614 IWineD3DDeviceImpl_SetIndices,
6615 IWineD3DDeviceImpl_GetIndices,
6616 IWineD3DDeviceImpl_SetLight,
6617 IWineD3DDeviceImpl_GetLight,
6618 IWineD3DDeviceImpl_SetLightEnable,
6619 IWineD3DDeviceImpl_GetLightEnable,
6620 IWineD3DDeviceImpl_SetMaterial,
6621 IWineD3DDeviceImpl_GetMaterial,
6622 IWineD3DDeviceImpl_SetNPatchMode,
6623 IWineD3DDeviceImpl_GetNPatchMode,
6624 IWineD3DDeviceImpl_SetPaletteEntries,
6625 IWineD3DDeviceImpl_GetPaletteEntries,
6626 IWineD3DDeviceImpl_SetPixelShader,
6627 IWineD3DDeviceImpl_GetPixelShader,
6628 IWineD3DDeviceImpl_SetPixelShaderConstant,
6629 IWineD3DDeviceImpl_GetPixelShaderConstant,
6630 IWineD3DDeviceImpl_SetPixelShaderConstantB,
6631 IWineD3DDeviceImpl_GetPixelShaderConstantB,
6632 IWineD3DDeviceImpl_SetPixelShaderConstantI,
6633 IWineD3DDeviceImpl_GetPixelShaderConstantI,
6634 IWineD3DDeviceImpl_SetPixelShaderConstantF,
6635 IWineD3DDeviceImpl_GetPixelShaderConstantF,
6636 IWineD3DDeviceImpl_SetPixelShaderConstantN,
6637 IWineD3DDeviceImpl_SetRenderState,
6638 IWineD3DDeviceImpl_GetRenderState,
6639 IWineD3DDeviceImpl_SetRenderTarget,
6640 IWineD3DDeviceImpl_GetRenderTarget,
6641 IWineD3DDeviceImpl_SetSamplerState,
6642 IWineD3DDeviceImpl_GetSamplerState,
6643 IWineD3DDeviceImpl_SetScissorRect,
6644 IWineD3DDeviceImpl_GetScissorRect,
6645 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
6646 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
6647 IWineD3DDeviceImpl_SetStreamSource,
6648 IWineD3DDeviceImpl_GetStreamSource,
6649 IWineD3DDeviceImpl_SetStreamSourceFreq,
6650 IWineD3DDeviceImpl_GetStreamSourceFreq,
6651 IWineD3DDeviceImpl_SetTexture,
6652 IWineD3DDeviceImpl_GetTexture,
6653 IWineD3DDeviceImpl_SetTextureStageState,
6654 IWineD3DDeviceImpl_GetTextureStageState,
6655 IWineD3DDeviceImpl_SetTransform,
6656 IWineD3DDeviceImpl_GetTransform,
6657 IWineD3DDeviceImpl_SetVertexDeclaration,
6658 IWineD3DDeviceImpl_GetVertexDeclaration,
6659 IWineD3DDeviceImpl_SetVertexShader,
6660 IWineD3DDeviceImpl_GetVertexShader,
6661 IWineD3DDeviceImpl_SetVertexShaderConstant,
6662 IWineD3DDeviceImpl_GetVertexShaderConstant,
6663 IWineD3DDeviceImpl_SetVertexShaderConstantB,
6664 IWineD3DDeviceImpl_GetVertexShaderConstantB,
6665 IWineD3DDeviceImpl_SetVertexShaderConstantI,
6666 IWineD3DDeviceImpl_GetVertexShaderConstantI,
6667 IWineD3DDeviceImpl_SetVertexShaderConstantF,
6668 IWineD3DDeviceImpl_GetVertexShaderConstantF,
6669 IWineD3DDeviceImpl_SetVertexShaderConstantN,
6670 IWineD3DDeviceImpl_SetViewport,
6671 IWineD3DDeviceImpl_GetViewport,
6672 IWineD3DDeviceImpl_MultiplyTransform,
6673 IWineD3DDeviceImpl_ValidateDevice,
6674 IWineD3DDeviceImpl_ProcessVertices,
6675 /*** State block ***/
6676 IWineD3DDeviceImpl_BeginStateBlock,
6677 IWineD3DDeviceImpl_EndStateBlock,
6678 /*** Scene management ***/
6679 IWineD3DDeviceImpl_BeginScene,
6680 IWineD3DDeviceImpl_EndScene,
6681 IWineD3DDeviceImpl_Present,
6682 IWineD3DDeviceImpl_Clear,
6684 IWineD3DDeviceImpl_DrawPrimitive,
6685 IWineD3DDeviceImpl_DrawIndexedPrimitive,
6686 IWineD3DDeviceImpl_DrawPrimitiveUP,
6687 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
6688 IWineD3DDeviceImpl_DrawRectPatch,
6689 IWineD3DDeviceImpl_DrawTriPatch,
6690 IWineD3DDeviceImpl_DeletePatch,
6691 IWineD3DDeviceImpl_ColorFill,
6692 IWineD3DDeviceImpl_UpdateTexture,
6693 IWineD3DDeviceImpl_UpdateSurface,
6694 IWineD3DDeviceImpl_CopyRects,
6695 IWineD3DDeviceImpl_StretchRect,
6696 IWineD3DDeviceImpl_GetRenderTargetData,
6697 IWineD3DDeviceImpl_GetFrontBufferData,
6698 /*** Internal use IWineD3DDevice methods ***/
6699 IWineD3DDeviceImpl_SetupTextureStates,
6700 /*** object tracking ***/
6701 IWineD3DDeviceImpl_SwapChainReleased,
6702 IWineD3DDeviceImpl_ResourceReleased
6706 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
6707 WINED3DRS_ALPHABLENDENABLE ,
6708 WINED3DRS_ALPHAFUNC ,
6709 WINED3DRS_ALPHAREF ,
6710 WINED3DRS_ALPHATESTENABLE ,
6712 WINED3DRS_COLORWRITEENABLE ,
6713 WINED3DRS_DESTBLEND ,
6714 WINED3DRS_DITHERENABLE ,
6715 WINED3DRS_FILLMODE ,
6716 WINED3DRS_FOGDENSITY ,
6718 WINED3DRS_FOGSTART ,
6719 WINED3DRS_LASTPIXEL ,
6720 WINED3DRS_SHADEMODE ,
6721 WINED3DRS_SRCBLEND ,
6722 WINED3DRS_STENCILENABLE ,
6723 WINED3DRS_STENCILFAIL ,
6724 WINED3DRS_STENCILFUNC ,
6725 WINED3DRS_STENCILMASK ,
6726 WINED3DRS_STENCILPASS ,
6727 WINED3DRS_STENCILREF ,
6728 WINED3DRS_STENCILWRITEMASK ,
6729 WINED3DRS_STENCILZFAIL ,
6730 WINED3DRS_TEXTUREFACTOR ,
6741 WINED3DRS_ZWRITEENABLE
6744 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
6745 WINED3DTSS_ADDRESSW ,
6746 WINED3DTSS_ALPHAARG0 ,
6747 WINED3DTSS_ALPHAARG1 ,
6748 WINED3DTSS_ALPHAARG2 ,
6749 WINED3DTSS_ALPHAOP ,
6750 WINED3DTSS_BUMPENVLOFFSET ,
6751 WINED3DTSS_BUMPENVLSCALE ,
6752 WINED3DTSS_BUMPENVMAT00 ,
6753 WINED3DTSS_BUMPENVMAT01 ,
6754 WINED3DTSS_BUMPENVMAT10 ,
6755 WINED3DTSS_BUMPENVMAT11 ,
6756 WINED3DTSS_COLORARG0 ,
6757 WINED3DTSS_COLORARG1 ,
6758 WINED3DTSS_COLORARG2 ,
6759 WINED3DTSS_COLOROP ,
6760 WINED3DTSS_RESULTARG ,
6761 WINED3DTSS_TEXCOORDINDEX ,
6762 WINED3DTSS_TEXTURETRANSFORMFLAGS
6765 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
6766 WINED3DSAMP_ADDRESSU ,
6767 WINED3DSAMP_ADDRESSV ,
6768 WINED3DSAMP_ADDRESSW ,
6769 WINED3DSAMP_BORDERCOLOR ,
6770 WINED3DSAMP_MAGFILTER ,
6771 WINED3DSAMP_MINFILTER ,
6772 WINED3DSAMP_MIPFILTER ,
6773 WINED3DSAMP_MIPMAPLODBIAS ,
6774 WINED3DSAMP_MAXMIPLEVEL ,
6775 WINED3DSAMP_MAXANISOTROPY ,
6776 WINED3DSAMP_SRGBTEXTURE ,
6777 WINED3DSAMP_ELEMENTINDEX
6780 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
6782 WINED3DRS_AMBIENTMATERIALSOURCE ,
6783 WINED3DRS_CLIPPING ,
6784 WINED3DRS_CLIPPLANEENABLE ,
6785 WINED3DRS_COLORVERTEX ,
6786 WINED3DRS_DIFFUSEMATERIALSOURCE ,
6787 WINED3DRS_EMISSIVEMATERIALSOURCE ,
6788 WINED3DRS_FOGDENSITY ,
6790 WINED3DRS_FOGSTART ,
6791 WINED3DRS_FOGTABLEMODE ,
6792 WINED3DRS_FOGVERTEXMODE ,
6793 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
6794 WINED3DRS_LIGHTING ,
6795 WINED3DRS_LOCALVIEWER ,
6796 WINED3DRS_MULTISAMPLEANTIALIAS ,
6797 WINED3DRS_MULTISAMPLEMASK ,
6798 WINED3DRS_NORMALIZENORMALS ,
6799 WINED3DRS_PATCHEDGESTYLE ,
6800 WINED3DRS_POINTSCALE_A ,
6801 WINED3DRS_POINTSCALE_B ,
6802 WINED3DRS_POINTSCALE_C ,
6803 WINED3DRS_POINTSCALEENABLE ,
6804 WINED3DRS_POINTSIZE ,
6805 WINED3DRS_POINTSIZE_MAX ,
6806 WINED3DRS_POINTSIZE_MIN ,
6807 WINED3DRS_POINTSPRITEENABLE ,
6808 WINED3DRS_RANGEFOGENABLE ,
6809 WINED3DRS_SPECULARMATERIALSOURCE ,
6810 WINED3DRS_TWEENFACTOR ,
6811 WINED3DRS_VERTEXBLEND
6814 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
6815 WINED3DTSS_TEXCOORDINDEX ,
6816 WINED3DTSS_TEXTURETRANSFORMFLAGS
6819 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
6820 WINED3DSAMP_DMAPOFFSET