2 * IWineD3DDevice implementation
4 * Copyright 2002 Lionel Ulmer
5 * Copyright 2002-2005 Jason Edmeades
6 * Copyright 2003-2004 Raphael Junqueira
7 * Copyright 2004 Christian Costa
8 * Copyright 2005 Oliver Stieber
9 * Copyright 2006 Stefan Dösinger for CodeWeavers
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #include "wined3d_private.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
33 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
35 /* x11drv GDI escapes */
36 #define X11DRV_ESCAPE 6789
37 enum x11drv_escape_codes
39 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
40 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
41 X11DRV_GET_FONT, /* get current X font for a DC */
44 /* retrieve the X display to use on a given DC */
45 inline static Display *get_display( HDC hdc )
48 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
50 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
51 sizeof(display), (LPSTR)&display )) display = NULL;
55 /* Memory tracking and object counting */
56 static unsigned int emulated_textureram = 64*1024*1024;
58 /* TODO: setup some flags in the regestry to enable, disable pbuffer support */
59 /* enable pbuffer support for offscreen textures */
60 BOOL pbuffer_support = FALSE;
61 /* allocate one pbuffer per surface */
62 BOOL pbuffer_per_surface = FALSE;
64 /* static function declarations */
65 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
67 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type);
70 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return WINED3DERR_OUTOFVIDEOMEMORY;}
72 #define D3DCREATEOBJECTINSTANCE(object, type) { \
73 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
74 D3DMEMCHECK(object, pp##type); \
75 object->lpVtbl = &IWineD3D##type##_Vtbl; \
76 object->wineD3DDevice = This; \
77 object->parent = parent; \
79 *pp##type = (IWineD3D##type *) object; \
82 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
83 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
84 D3DMEMCHECK(object, pp##type); \
85 object->lpVtbl = &IWineD3D##type##_Vtbl; \
86 object->resource.wineD3DDevice = This; \
87 object->resource.parent = parent; \
88 object->resource.resourceType = d3dtype; \
89 object->resource.ref = 1; \
90 object->resource.pool = Pool; \
91 object->resource.format = Format; \
92 object->resource.usage = Usage; \
93 object->resource.size = _size; \
94 /* Check that we have enough video ram left */ \
95 if (Pool == WINED3DPOOL_DEFAULT) { \
96 if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
97 WARN("Out of 'bogus' video memory\n"); \
98 HeapFree(GetProcessHeap(), 0, object); \
100 return WINED3DERR_OUTOFVIDEOMEMORY; \
102 globalChangeGlRam(_size); \
104 object->resource.allocatedMemory = (0 == _size ? NULL : Pool == WINED3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
105 if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != WINED3DPOOL_DEFAULT) { \
106 FIXME("Out of memory!\n"); \
107 HeapFree(GetProcessHeap(), 0, object); \
109 return WINED3DERR_OUTOFVIDEOMEMORY; \
111 *pp##type = (IWineD3D##type *) object; \
112 IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
113 TRACE("(%p) : Created resource %p\n", This, object); \
116 #define D3DINITIALIZEBASETEXTURE(_basetexture) { \
117 _basetexture.levels = Levels; \
118 _basetexture.filterType = (Usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE; \
119 _basetexture.LOD = 0; \
120 _basetexture.dirty = TRUE; \
123 /**********************************************************
124 * Global variable / Constants follow
125 **********************************************************/
126 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
128 /**********************************************************
129 * Utility functions follow
130 **********************************************************/
131 /* Convert the D3DLIGHT properties into equivalent gl lights */
132 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
135 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
136 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
138 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
139 glMatrixMode(GL_MODELVIEW);
141 glLoadMatrixf((float *)&This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
144 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
145 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
146 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
147 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
148 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
149 checkGLcall("glLightfv");
152 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
153 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
154 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
155 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
156 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
157 checkGLcall("glLightfv");
160 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
161 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
162 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
163 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
164 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
165 checkGLcall("glLightfv");
167 /* Attenuation - Are these right? guessing... */
168 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
169 checkGLcall("glLightf");
170 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
171 checkGLcall("glLightf");
173 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
174 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
176 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
179 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
180 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
181 checkGLcall("glLightf");
183 switch (lightInfo->OriginalParms.Type) {
186 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
187 checkGLcall("glLightfv");
188 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
189 checkGLcall("glLightf");
195 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
196 checkGLcall("glLightfv");
198 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
199 checkGLcall("glLightfv");
200 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
201 checkGLcall("glLightf");
202 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
203 checkGLcall("glLightf");
207 case D3DLIGHT_DIRECTIONAL:
209 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
210 checkGLcall("glLightfv");
211 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
212 checkGLcall("glLightf");
213 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
214 checkGLcall("glLightf");
218 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
221 /* Restore the modelview matrix */
225 /* Apply the current values to the specified texture stage */
226 void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Sampler, DWORD Flags) {
227 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
235 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
236 clamping, MIPLOD, etc. This will work for up to 16 samplers.
239 if (Sampler >= GL_LIMITS(samplers)) {
240 FIXME("Trying to set the state of more samplers %ld than are supported %d by this openGL implementation\n", Sampler, GL_LIMITS(samplers));
243 VTRACE(("Activating appropriate texture state %ld\n", Sampler));
244 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
246 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + Sampler));
247 checkGLcall("glActiveTextureARB");
249 /* Could we use bindTexture and then apply the states instead of GLACTIVETEXTURE */
250 } else if (Sampler > 0) {
251 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
255 /* TODO: change this to a lookup table
256 LOOKUP_TEXTURE_STATES lists all texture states that should be applied.
257 LOOKUP_CONTEXT_SATES list all context applicable states that can be applied
258 etc.... it's a lot cleaner, quicker and possibly easier to maintain than running a switch and setting a skip flag...
259 especially when there are a number of groups of states. */
261 TRACE("-----------------------> Updating the texture at Sampler %ld to have new texture state information\n", Sampler);
263 /* 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 */
264 #define APPLY_STATE(_state) IWineD3DDeviceImpl_ApplyTextureUnitState(iface, Sampler, _state)
265 /* these are the only two supported states that need to be applied */
266 APPLY_STATE(WINED3DTSS_TEXCOORDINDEX);
267 APPLY_STATE(WINED3DTSS_TEXTURETRANSFORMFLAGS);
268 #if 0 /* not supported at the moment */
269 APPLY_STATE(WINED3DTSS_BUMPENVMAT00);
270 APPLY_STATE(WINED3DTSS_BUMPENVMAT01);
271 APPLY_STATE(WINED3DTSS_BUMPENVMAT10);
272 APPLY_STATE(WINED3DTSS_BUMPENVMAT11);
273 APPLY_STATE(WINED3DTSS_BUMPENVLSCALE);
274 APPLY_STATE(WINED3DTSS_BUMPENVLOFFSET);
275 APPLY_STATE(WINED3DTSS_RESULTARG);
276 APPLY_STATE(WINED3DTSS_CONSTANT);
278 /* a quick sanity check in case someone forgot to update this function */
279 if (WINED3D_HIGHEST_TEXTURE_STATE > WINED3DTSS_CONSTANT) {
280 FIXME("(%p) : There are more texture states than expected, update device.c to match\n", This);
284 /* apply any sampler states that always need applying */
285 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
286 tmpvalue.d = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPMAPLODBIAS];
287 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
288 GL_TEXTURE_LOD_BIAS_EXT,
290 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
293 /* Note the D3DRS value applies to all textures, but GL has one
294 * per texture, so apply it now ready to be used!
296 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
297 /* Set the default alpha blend color */
298 if (GL_SUPPORT(ARB_IMAGING)) {
299 GL_EXTCALL(glBlendColor(col[0], col[1], col[2], col[3]));
300 checkGLcall("glBlendColor");
302 WARN("Unsupported in local OpenGL implementation: glBlendColor\n");
305 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
306 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
307 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
309 /* TODO: NV_POINT_SPRITE */
310 if (GL_SUPPORT(ARB_POINT_SPRITE)) {
311 if (This->stateBlock->renderState[WINED3DRS_POINTSPRITEENABLE] != FALSE) {
312 /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
313 glDisable(GL_POINT_SMOOTH);
315 /* Centre the texture on the vertex */
316 VTRACE(("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n"));
317 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
319 VTRACE(("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n"));
320 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
321 checkGLcall("glTexEnvf(...)");
322 VTRACE(("glEnable( GL_POINT_SPRITE_ARB )\n"));
323 glEnable( GL_POINT_SPRITE_ARB );
324 checkGLcall("glEnable(...)");
326 VTRACE(("glDisable( GL_POINT_SPRITE_ARB )\n"));
327 glDisable( GL_POINT_SPRITE_ARB );
328 checkGLcall("glEnable(...)");
332 TRACE("-----------------------> Updated the texture at Sampler %ld to have new texture state information\n", Sampler);
335 /**********************************************************
336 * IUnknown parts follows
337 **********************************************************/
339 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
341 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
343 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
344 if (IsEqualGUID(riid, &IID_IUnknown)
345 || IsEqualGUID(riid, &IID_IWineD3DBase)
346 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
347 IUnknown_AddRef(iface);
352 return E_NOINTERFACE;
355 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
356 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
357 ULONG refCount = InterlockedIncrement(&This->ref);
359 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
363 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
364 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
365 ULONG refCount = InterlockedDecrement(&This->ref);
367 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
370 /* TODO: Clean up all the surfaces and textures! */
371 /* NOTE: You must release the parent if the object was created via a callback
372 ** ***************************/
374 /* Release the update stateblock */
375 if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){
376 if(This->updateStateBlock != This->stateBlock)
377 FIXME("(%p) Something's still holding the Update stateblock\n",This);
379 This->updateStateBlock = NULL;
380 { /* because were not doing proper internal refcounts releasing the primary state block
381 causes recursion with the extra checks in ResourceReleased, to avoid this we have
382 to set this->stateBlock = NULL; first */
383 IWineD3DStateBlock *stateBlock = (IWineD3DStateBlock *)This->stateBlock;
384 This->stateBlock = NULL;
386 /* Release the stateblock */
387 if(IWineD3DStateBlock_Release(stateBlock) > 0){
388 FIXME("(%p) Something's still holding the Update stateblock\n",This);
392 if (This->resources != NULL ) {
393 FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This);
394 dumpResources(This->resources);
398 IWineD3D_Release(This->wineD3D);
399 This->wineD3D = NULL;
400 HeapFree(GetProcessHeap(), 0, This);
401 TRACE("Freed device %p\n", This);
407 /**********************************************************
408 * IWineD3DDevice implementation follows
409 **********************************************************/
410 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
411 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
412 *pParent = This->parent;
413 IUnknown_AddRef(This->parent);
417 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
418 DWORD FVF, WINED3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
420 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
421 IWineD3DVertexBufferImpl *object;
422 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
423 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, WINED3DRTYPE_VERTEXBUFFER, Size)
426 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
427 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
431 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
432 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
437 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
438 WINED3DFORMAT Format, WINED3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
439 HANDLE *sharedHandle, IUnknown *parent) {
440 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
441 IWineD3DIndexBufferImpl *object;
442 TRACE("(%p) Creating index buffer\n", This);
444 /* Allocate the storage for the device */
445 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,WINED3DRTYPE_INDEXBUFFER, Length)
448 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
449 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
452 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
453 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
454 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
459 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
461 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
462 IWineD3DStateBlockImpl *object;
465 D3DCREATEOBJECTINSTANCE(object, StateBlock)
466 object->blockType = Type;
468 /* Special case - Used during initialization to produce a placeholder stateblock
469 so other functions called can update a state block */
470 if (Type == WINED3DSBT_INIT) {
471 /* Don't bother increasing the reference count otherwise a device will never
472 be freed due to circular dependencies */
476 /* Otherwise, might as well set the whole state block to the appropriate values */
477 if ( This->stateBlock != NULL) {
478 memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
480 memset(object->streamFreq, 1, sizeof(object->streamFreq));
483 /* Reset the ref and type after kludging it */
484 object->wineD3DDevice = This;
486 object->blockType = Type;
488 TRACE("Updating changed flags appropriate for type %d\n", Type);
490 if (Type == WINED3DSBT_ALL) {
492 TRACE("ALL => Pretend everything has changed\n");
493 memset(&object->changed, TRUE, sizeof(This->stateBlock->changed));
494 } else if (Type == WINED3DSBT_PIXELSTATE) {
496 TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
497 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
499 object->changed.pixelShader = TRUE;
501 /* Pixel Shader Constants */
502 for (i = 0; i < MAX_PSHADER_CONSTANTS; ++i) {
503 object->changed.pixelShaderConstants[i] = TRUE;
505 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
506 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
508 for (j = 0; j < GL_LIMITS(textures); j++) {
509 for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
510 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
513 for (j = 0 ; j < 16; j++) {
514 for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
516 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
520 } else if (Type == WINED3DSBT_VERTEXSTATE) {
522 TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
523 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
525 object->changed.vertexShader = TRUE;
527 /* Vertex Shader Constants */
528 for (i = 0; i < MAX_VSHADER_CONSTANTS; ++i) {
529 object->changed.vertexShaderConstants[i] = TRUE;
531 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
532 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
534 for (j = 0; j < GL_LIMITS(textures); j++) {
535 for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
536 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
539 for (j = 0 ; j < 16; j++){
540 for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
541 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
545 /* Duplicate light chain */
547 PLIGHTINFOEL *src = NULL;
548 PLIGHTINFOEL *dst = NULL;
549 PLIGHTINFOEL *newEl = NULL;
550 src = This->stateBlock->lights;
551 object->lights = NULL;
555 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
556 if (newEl == NULL) return WINED3DERR_OUTOFVIDEOMEMORY;
557 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
559 newEl->changed = TRUE;
560 newEl->enabledChanged = TRUE;
562 object->lights = newEl;
573 FIXME("Unrecognized state block type %d\n", Type);
576 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
581 /* ************************************
583 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
586 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
588 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.
590 ******************************** */
592 HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height, WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **ppSurface,WINED3DRESOURCETYPE Type, DWORD Usage, WINED3DPOOL Pool, WINED3DMULTISAMPLE_TYPE MultiSample ,DWORD MultisampleQuality, HANDLE* pSharedHandle, WINED3DSURFTYPE Impl, IUnknown *parent) {
593 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
594 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
595 unsigned int pow2Width, pow2Height;
596 unsigned int Size = 1;
597 TRACE("(%p) Create surface\n",This);
599 /** FIXME: Check ranges on the inputs are valid
602 * [in] Quality level. The valid range is between zero and one less than the level
603 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
604 * Passing a larger value returns the error WINED3DERR_INVALIDCALL. The MultisampleQuality
605 * values of paired render targets, depth stencil surfaces, and the MultiSample type
607 *******************************/
612 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
614 * If this flag is set, the contents of the depth stencil buffer will be
615 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
616 * with a different depth surface.
618 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
619 ***************************/
621 if(MultisampleQuality < 0) {
622 FIXME("Invalid multisample level %ld\n", MultisampleQuality);
623 return WINED3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
626 if(MultisampleQuality > 0) {
627 FIXME("MultisampleQuality set to %ld, substituting 0\n", MultisampleQuality);
628 MultisampleQuality=0;
631 /** FIXME: Check that the format is supported
633 *******************************/
635 /* Non-power2 support */
637 /* Find the nearest pow2 match */
638 pow2Width = pow2Height = 1;
639 while (pow2Width < Width) pow2Width <<= 1;
640 while (pow2Height < Height) pow2Height <<= 1;
642 if (pow2Width > Width || pow2Height > Height) {
643 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
644 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
645 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
646 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
647 This, Width, Height);
648 return WINED3DERR_NOTAVAILABLE;
652 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
653 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
655 *********************************/
656 if (WINED3DFMT_UNKNOWN == Format) {
658 } else if (Format == WINED3DFMT_DXT1) {
659 /* DXT1 is half byte per pixel */
660 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4)) >> 1;
662 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
663 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
664 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4));
666 Size = (pow2Width * D3DFmtGetBpp(This, Format)) * pow2Height;
669 /** Create and initialise the surface resource **/
670 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,WINED3DRTYPE_SURFACE, Size)
671 /* "Standalone" surface */
672 IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL);
674 object->currentDesc.Width = Width;
675 object->currentDesc.Height = Height;
676 object->currentDesc.MultiSampleType = MultiSample;
677 object->currentDesc.MultiSampleQuality = MultisampleQuality;
679 /* Setup some glformat defaults */
680 if (WINED3DFMT_UNKNOWN != Format) {
681 object->glDescription.glFormat = D3DFmt2GLFmt(This, object->resource.format);
682 object->glDescription.glFormatInternal = D3DFmt2GLIntFmt(This, object->resource.format);
683 object->glDescription.glType = D3DFmt2GLType(This, object->resource.format);
685 object->glDescription.glFormat = 0;
686 object->glDescription.glFormatInternal = 0;
687 object->glDescription.glType = 0;
690 object->glDescription.textureName = 0;
691 object->glDescription.level = Level;
692 object->glDescription.target = GL_TEXTURE_2D;
695 object->pow2Width = pow2Width;
696 object->pow2Height = pow2Height;
699 object->Flags = 0; /* We start without flags set */
700 object->Flags |= (pow2Width != Width || pow2Height != Height) ? SFLAG_NONPOW2 : 0;
701 object->Flags |= Discard ? SFLAG_DISCARD : 0;
702 object->Flags |= (WINED3DFMT_D16_LOCKABLE == Format) ? SFLAG_LOCKABLE : 0;
703 object->Flags |= Lockable ? SFLAG_LOCKABLE : 0;
706 if (WINED3DFMT_UNKNOWN != Format) {
707 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
708 object->pow2Size = (pow2Width * object->bytesPerPixel) * pow2Height;
710 object->bytesPerPixel = 0;
711 object->pow2Size = 0;
714 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
716 TRACE("Pool %d %d %d %d",Pool, WINED3DPOOL_DEFAULT, WINED3DPOOL_MANAGED, WINED3DPOOL_SYSTEMMEM);
718 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
719 * this function is too deap to need to care about things like this.
720 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
721 * ****************************************/
723 case WINED3DPOOL_SCRATCH:
724 if(Lockable == FALSE)
725 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
726 which are mutually exclusive, setting lockable to true\n");
729 case WINED3DPOOL_SYSTEMMEM:
730 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
731 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
732 case WINED3DPOOL_MANAGED:
733 if(Usage == WINED3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
734 Usage of DYNAMIC which are mutually exclusive, not doing \
735 anything just telling you.\n");
737 case WINED3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
738 if(!(Usage & WINED3DUSAGE_DYNAMIC) && !(Usage & WINED3DUSAGE_RENDERTARGET)
739 && !(Usage && WINED3DUSAGE_DEPTHSTENCIL ) && Lockable)
740 WARN("Creating a surface with a POOL of DEFAULT with Lockable true, that doesn't specify DYNAMIC usage.\n");
743 FIXME("(%p) Unknown pool %d\n", This, Pool);
747 if (Usage & WINED3DUSAGE_RENDERTARGET && Pool != WINED3DPOOL_DEFAULT) {
748 FIXME("Trying to create a render target that isn't in the default pool\n");
751 /* mark the texture as dirty so that it get's loaded first time around*/
752 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
753 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
754 This, Width, Height, Format, debug_d3dformat(Format),
755 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
757 /* Store the DirectDraw primary surface. This is the first rendertarget surface created */
758 if( (Usage & WINED3DUSAGE_RENDERTARGET) && (!This->ddraw_primary) )
759 This->ddraw_primary = (IWineD3DSurface *) object;
761 /* Look at the implementation and set the correct Vtable */
764 /* Nothing to do, it's set already */
768 object->lpVtbl = &IWineGDISurface_Vtbl;
772 /* To be sure to catch this */
773 ERR("Unknown requested surface implementation %d!\n", Impl);
774 IWineD3DSurface_Release((IWineD3DSurface *) object);
775 return WINED3DERR_INVALIDCALL;
778 /* Call the private setup routine */
779 return IWineD3DSurface_PrivateSetup( (IWineD3DSurface *) object );
783 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
784 DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
785 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
786 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
788 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
789 IWineD3DTextureImpl *object;
794 unsigned int pow2Width = Width;
795 unsigned int pow2Height = Height;
798 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) ....\n", This, Width, Height, Levels, Usage);
800 /* TODO: It should only be possible to create textures for formats
801 that are reported as supported */
802 if (WINED3DFMT_UNKNOWN >= Format) {
803 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
804 return WINED3DERR_INVALIDCALL;
807 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, WINED3DRTYPE_TEXTURE, 0);
808 D3DINITIALIZEBASETEXTURE(object->baseTexture);
809 object->width = Width;
810 object->height = Height;
812 /** Non-power2 support **/
813 /* Find the nearest pow2 match */
814 pow2Width = pow2Height = 1;
815 while (pow2Width < Width) pow2Width <<= 1;
816 while (pow2Height < Height) pow2Height <<= 1;
818 /** FIXME: add support for real non-power-two if it's provided by the video card **/
819 /* Precalculated scaling for 'faked' non power of two texture coords */
820 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
821 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
822 TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
824 /* Calculate levels for mip mapping */
826 TRACE("calculating levels %d\n", object->baseTexture.levels);
827 object->baseTexture.levels++;
830 while (tmpW > 1 || tmpH > 1) {
831 tmpW = max(1, tmpW >> 1);
832 tmpH = max(1, tmpH >> 1);
833 object->baseTexture.levels++;
835 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
838 /* Generate all the surfaces */
841 for (i = 0; i < object->baseTexture.levels; i++)
843 /* use the callback to create the texture surface */
844 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
845 if (hr!= WINED3D_OK || ( (IWineD3DSurfaceImpl *) object->surfaces[i])->Flags & SFLAG_OVERSIZE) {
846 FIXME("Failed to create surface %p\n", object);
848 object->surfaces[i] = NULL;
849 IWineD3DTexture_Release((IWineD3DTexture *)object);
855 IWineD3DSurface_SetContainer(object->surfaces[i], (IWineD3DBase *)object);
856 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
857 /* calculate the next mipmap level */
858 tmpW = max(1, tmpW >> 1);
859 tmpH = max(1, tmpH >> 1);
862 TRACE("(%p) : Created texture %p\n", This, object);
866 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
867 UINT Width, UINT Height, UINT Depth,
868 UINT Levels, DWORD Usage,
869 WINED3DFORMAT Format, WINED3DPOOL Pool,
870 IWineD3DVolumeTexture **ppVolumeTexture,
871 HANDLE *pSharedHandle, IUnknown *parent,
872 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
874 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
875 IWineD3DVolumeTextureImpl *object;
881 /* TODO: It should only be possible to create textures for formats
882 that are reported as supported */
883 if (WINED3DFMT_UNKNOWN >= Format) {
884 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
885 return WINED3DERR_INVALIDCALL;
888 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, WINED3DRTYPE_VOLUMETEXTURE, 0);
889 D3DINITIALIZEBASETEXTURE(object->baseTexture);
891 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
892 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
894 object->width = Width;
895 object->height = Height;
896 object->depth = Depth;
898 /* Calculate levels for mip mapping */
900 object->baseTexture.levels++;
904 while (tmpW > 1 || tmpH > 1 || tmpD > 1) {
905 tmpW = max(1, tmpW >> 1);
906 tmpH = max(1, tmpH >> 1);
907 tmpD = max(1, tmpD >> 1);
908 object->baseTexture.levels++;
910 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
913 /* Generate all the surfaces */
918 for (i = 0; i < object->baseTexture.levels; i++)
920 /* Create the volume */
921 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
922 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
924 /* Set it's container to this object */
925 IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)object);
927 /* calcualte the next mipmap level */
928 tmpW = max(1, tmpW >> 1);
929 tmpH = max(1, tmpH >> 1);
930 tmpD = max(1, tmpD >> 1);
933 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
934 TRACE("(%p) : Created volume texture %p\n", This, object);
938 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
939 UINT Width, UINT Height, UINT Depth,
941 WINED3DFORMAT Format, WINED3DPOOL Pool,
942 IWineD3DVolume** ppVolume,
943 HANDLE* pSharedHandle, IUnknown *parent) {
945 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
946 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
948 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, WINED3DRTYPE_VOLUME, ((Width * D3DFmtGetBpp(This, Format)) * Height * Depth))
950 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
951 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
953 object->currentDesc.Width = Width;
954 object->currentDesc.Height = Height;
955 object->currentDesc.Depth = Depth;
956 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
958 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
959 object->lockable = TRUE;
960 object->locked = FALSE;
961 memset(&object->lockedBox, 0, sizeof(WINED3DBOX));
962 object->dirty = TRUE;
964 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
967 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
968 UINT Levels, DWORD Usage,
969 WINED3DFORMAT Format, WINED3DPOOL Pool,
970 IWineD3DCubeTexture **ppCubeTexture,
971 HANDLE *pSharedHandle, IUnknown *parent,
972 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
974 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
975 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
979 unsigned int pow2EdgeLength = EdgeLength;
981 /* TODO: It should only be possible to create textures for formats
982 that are reported as supported */
983 if (WINED3DFMT_UNKNOWN >= Format) {
984 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
985 return WINED3DERR_INVALIDCALL;
988 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, WINED3DRTYPE_CUBETEXTURE, 0);
989 D3DINITIALIZEBASETEXTURE(object->baseTexture);
991 TRACE("(%p) Create Cube Texture\n", This);
993 /** Non-power2 support **/
995 /* Find the nearest pow2 match */
997 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
999 object->edgeLength = EdgeLength;
1000 /* TODO: support for native non-power 2 */
1001 /* Precalculated scaling for 'faked' non power of two texture coords */
1002 object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
1004 /* Calculate levels for mip mapping */
1006 object->baseTexture.levels++;
1009 tmpW = max(1, tmpW >> 1);
1010 object->baseTexture.levels++;
1012 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1015 /* Generate all the surfaces */
1017 for (i = 0; i < object->baseTexture.levels; i++) {
1019 /* Create the 6 faces */
1020 for (j = 0; j < 6; j++) {
1022 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
1023 i /* Level */, &object->surfaces[j][i],pSharedHandle);
1025 if(hr!= WINED3D_OK) {
1029 for (l = 0; l < j; l++) {
1030 IWineD3DSurface_Release(object->surfaces[j][i]);
1032 for (k = 0; k < i; k++) {
1033 for (l = 0; l < 6; l++) {
1034 IWineD3DSurface_Release(object->surfaces[l][j]);
1038 FIXME("(%p) Failed to create surface\n",object);
1039 HeapFree(GetProcessHeap(),0,object);
1040 *ppCubeTexture = NULL;
1043 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IWineD3DBase *)object);
1044 TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1046 tmpW = max(1, tmpW >> 1);
1049 TRACE("(%p) : Created Cube Texture %p\n", This, object);
1050 *ppCubeTexture = (IWineD3DCubeTexture *) object;
1054 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1055 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1056 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1058 if (NULL == ppQuery) {
1059 /* Just a check to see if we support this type of query */
1060 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1062 case WINED3DQUERYTYPE_OCCLUSION:
1063 TRACE("(%p) occlusion query\n", This);
1064 if (GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY))
1067 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1069 case WINED3DQUERYTYPE_VCACHE:
1070 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1071 case WINED3DQUERYTYPE_VERTEXSTATS:
1072 case WINED3DQUERYTYPE_EVENT:
1073 case WINED3DQUERYTYPE_TIMESTAMP:
1074 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1075 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1076 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1077 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1078 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1079 case WINED3DQUERYTYPE_PIXELTIMINGS:
1080 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1081 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1083 FIXME("(%p) Unhandled query type %d\n", This, Type);
1088 D3DCREATEOBJECTINSTANCE(object, Query)
1089 object->type = Type;
1090 /* allocated the 'extended' data based on the type of query requested */
1092 case D3DQUERYTYPE_OCCLUSION:
1093 if(GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY)) {
1094 TRACE("(%p) Allocating data for an occlusion query\n", This);
1095 object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1098 case D3DQUERYTYPE_VCACHE:
1099 case D3DQUERYTYPE_RESOURCEMANAGER:
1100 case D3DQUERYTYPE_VERTEXSTATS:
1101 case D3DQUERYTYPE_EVENT:
1102 case D3DQUERYTYPE_TIMESTAMP:
1103 case D3DQUERYTYPE_TIMESTAMPDISJOINT:
1104 case D3DQUERYTYPE_TIMESTAMPFREQ:
1105 case D3DQUERYTYPE_PIPELINETIMINGS:
1106 case D3DQUERYTYPE_INTERFACETIMINGS:
1107 case D3DQUERYTYPE_VERTEXTIMINGS:
1108 case D3DQUERYTYPE_PIXELTIMINGS:
1109 case D3DQUERYTYPE_BANDWIDTHTIMINGS:
1110 case D3DQUERYTYPE_CACHEUTILIZATION:
1112 object->extendedData = 0;
1113 FIXME("(%p) Unhandled query type %d\n",This , Type);
1115 TRACE("(%p) : Created Query %p\n", This, object);
1119 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1120 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1122 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1123 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1124 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1127 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1129 XVisualInfo template;
1130 GLXContext oldContext;
1131 Drawable oldDrawable;
1132 HRESULT hr = WINED3D_OK;
1134 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1136 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1137 * does a device hold a reference to a swap chain giving them a lifetime of the device
1138 * or does the swap chain notify the device of its destruction.
1139 *******************************/
1141 /* Check the params */
1142 if(*pPresentationParameters->BackBufferCount > 1) {
1143 ERR("App requested %d back buffers, this is not supported for now\n", *pPresentationParameters->BackBufferCount);
1144 return WINED3DERR_INVALIDCALL;
1147 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1149 /*********************
1150 * Lookup the window Handle and the relating X window handle
1151 ********************/
1153 /* Setup hwnd we are using, plus which display this equates to */
1154 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1155 if (!object->win_handle) {
1156 object->win_handle = This->createParms.hFocusWindow;
1159 object->win_handle = GetAncestor(object->win_handle, GA_ROOT);
1160 if ( !( object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window") ) ) {
1161 ERR("Can't get drawable (window), HWND:%p doesn't have the property __wine_x11_whole_window\n", object->win_handle);
1162 return WINED3DERR_NOTAVAILABLE;
1164 hDc = GetDC(object->win_handle);
1165 object->display = get_display(hDc);
1166 ReleaseDC(object->win_handle, hDc);
1167 TRACE("Using a display of %p %p\n", object->display, hDc);
1169 if (NULL == object->display || NULL == hDc) {
1170 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1171 return WINED3DERR_NOTAVAILABLE;
1174 if (object->win == 0) {
1175 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1176 return WINED3DERR_NOTAVAILABLE;
1179 * Create an opengl context for the display visual
1180 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1181 * use different properties after that point in time. FIXME: How to handle when requested format
1182 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1183 * it chooses is identical to the one already being used!
1184 **********************************/
1186 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1189 /* Create a new context for this swapchain */
1190 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1191 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1192 (or the best possible if none is requested) */
1193 TRACE("Found x visual ID : %ld\n", template.visualid);
1195 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1196 if (NULL == object->visInfo) {
1197 ERR("cannot really get XVisual\n");
1199 return WINED3DERR_NOTAVAILABLE;
1202 /* Write out some debug info about the visual/s */
1203 TRACE("Using x visual ID : %ld\n", template.visualid);
1204 TRACE(" visual info: %p\n", object->visInfo);
1205 TRACE(" num items : %d\n", num);
1206 for (n = 0;n < num; n++) {
1207 TRACE("=====item=====: %d\n", n + 1);
1208 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1209 TRACE(" screen : %d\n", object->visInfo[n].screen);
1210 TRACE(" depth : %u\n", object->visInfo[n].depth);
1211 TRACE(" class : %d\n", object->visInfo[n].class);
1212 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1213 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1214 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1215 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1216 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1217 /* log some extra glx info */
1218 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1219 TRACE(" gl_aux_buffers : %d\n", value);
1220 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1221 TRACE(" gl_buffer_size : %d\n", value);
1222 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1223 TRACE(" gl_red_size : %d\n", value);
1224 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1225 TRACE(" gl_green_size : %d\n", value);
1226 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1227 TRACE(" gl_blue_size : %d\n", value);
1228 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1229 TRACE(" gl_alpha_size : %d\n", value);
1230 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1231 TRACE(" gl_depth_size : %d\n", value);
1232 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1233 TRACE(" gl_stencil_size : %d\n", value);
1235 /* Now choose a simila visual ID*/
1237 #ifdef USE_CONTEXT_MANAGER
1239 /** TODO: use a context mamager **/
1243 IWineD3DSwapChain *implSwapChain;
1244 if (WINED3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1245 /* The first time around we create the context that is shared with all other swapchains and render targets */
1246 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1247 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1250 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1251 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1252 /* and create a new context with the implicit swapchains context as the shared context */
1253 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1254 IWineD3DSwapChain_Release(implSwapChain);
1259 XFree(object->visInfo);
1260 object->visInfo = NULL;
1262 if (NULL == object->glCtx) {
1263 ERR("cannot create glxContext\n");
1265 return WINED3DERR_NOTAVAILABLE;
1269 if (object->glCtx == NULL) {
1270 ERR("Error in context creation !\n");
1271 return WINED3DERR_INVALIDCALL;
1273 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1274 object->win_handle, object->glCtx, object->win, object->visInfo);
1277 /*********************
1278 * Windowed / Fullscreen
1279 *******************/
1282 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1283 * so we should really check to see if there is a fullscreen swapchain already
1284 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1285 **************************************/
1287 if (!*(pPresentationParameters->Windowed)) {
1293 /* Get info on the current display setup */
1294 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1295 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1298 /* Change the display settings */
1299 memset(&devmode, 0, sizeof(DEVMODEW));
1300 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1301 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1302 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1303 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1304 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1305 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1307 /* Make popup window */
1308 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1309 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1310 *(pPresentationParameters->BackBufferWidth),
1311 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1313 /* For GetDisplayMode */
1314 This->ddraw_width = devmode.dmPelsWidth;
1315 This->ddraw_height = devmode.dmPelsHeight;
1316 This->ddraw_format = *(pPresentationParameters->BackBufferFormat);
1320 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1321 * then the corresponding dimension of the client area of the hDeviceWindow
1322 * (or the focus window, if hDeviceWindow is NULL) is taken.
1323 **********************/
1325 if (*(pPresentationParameters->Windowed) &&
1326 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1327 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1330 GetClientRect(object->win_handle, &Rect);
1332 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1333 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1334 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1336 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1337 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1338 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1342 /*********************
1343 * finish off parameter initialization
1344 *******************/
1346 /* Put the correct figures in the presentation parameters */
1347 TRACE("Coppying accross presentaion paraneters\n");
1348 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1349 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1350 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1351 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1352 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1353 object->presentParms.MultiSampleQuality = NULL == pPresentationParameters->MultiSampleQuality ? 0 : *(pPresentationParameters->MultiSampleQuality);
1354 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1355 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1356 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1357 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1358 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1359 object->presentParms.Flags = *(pPresentationParameters->Flags);
1360 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1361 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1364 /*********************
1365 * Create the back, front and stencil buffers
1366 *******************/
1368 TRACE("calling rendertarget CB\n");
1369 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1370 object->presentParms.BackBufferWidth,
1371 object->presentParms.BackBufferHeight,
1372 object->presentParms.BackBufferFormat,
1373 object->presentParms.MultiSampleType,
1374 object->presentParms.MultiSampleQuality,
1375 TRUE /* Lockable */,
1376 &object->frontBuffer,
1377 NULL /* pShared (always null)*/);
1378 if (object->frontBuffer != NULL)
1379 IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
1380 if(object->presentParms.BackBufferCount > 0) {
1381 TRACE("calling rendertarget CB\n");
1382 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1383 object->presentParms.BackBufferWidth,
1384 object->presentParms.BackBufferHeight,
1385 object->presentParms.BackBufferFormat,
1386 object->presentParms.MultiSampleType,
1387 object->presentParms.MultiSampleQuality,
1388 TRUE /* Lockable */,
1389 &object->backBuffer,
1390 NULL /* pShared (always null)*/);
1392 object->backBuffer = NULL;
1395 if (object->backBuffer != NULL) {
1396 IWineD3DSurface_SetContainer(object->backBuffer, (IWineD3DBase *)object);
1398 glDrawBuffer(GL_BACK);
1399 checkGLcall("glDrawBuffer(GL_BACK)");
1402 /* Single buffering - draw to front buffer */
1404 glDrawBuffer(GL_FRONT);
1405 checkGLcall("glDrawBuffer(GL_FRONT)");
1409 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1410 if (pPresentationParameters->EnableAutoDepthStencil) {
1411 TRACE("Creating depth stencil buffer\n");
1412 if (This->depthStencilBuffer == NULL ) {
1413 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1414 object->presentParms.BackBufferWidth,
1415 object->presentParms.BackBufferHeight,
1416 object->presentParms.AutoDepthStencilFormat,
1417 object->presentParms.MultiSampleType,
1418 object->presentParms.MultiSampleQuality,
1419 FALSE /* FIXME: Discard */,
1420 &This->depthStencilBuffer,
1421 NULL /* pShared (always null)*/ );
1422 if (This->depthStencilBuffer != NULL)
1423 IWineD3DSurface_SetContainer(This->depthStencilBuffer, 0);
1426 /** TODO: A check on width, height and multisample types
1427 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1428 ****************************/
1429 object->wantsDepthStencilBuffer = TRUE;
1431 object->wantsDepthStencilBuffer = FALSE;
1434 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1437 /*********************
1438 * init the default renderTarget management
1439 *******************/
1440 object->drawable = object->win;
1441 object->render_ctx = object->glCtx;
1443 if (hr == WINED3D_OK) {
1444 /*********************
1445 * Setup some defaults and clear down the buffers
1446 *******************/
1448 /** save current context and drawable **/
1449 oldContext = glXGetCurrentContext();
1450 oldDrawable = glXGetCurrentDrawable();
1452 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1453 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1454 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1456 checkGLcall("glXMakeCurrent");
1458 TRACE("Setting up the screen\n");
1459 /* Clear the screen */
1460 glClearColor(1.0, 0.0, 0.0, 0.0);
1461 checkGLcall("glClearColor");
1464 glClearStencil(0xffff);
1466 checkGLcall("glClear");
1468 glColor3f(1.0, 1.0, 1.0);
1469 checkGLcall("glColor3f");
1471 glEnable(GL_LIGHTING);
1472 checkGLcall("glEnable");
1474 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1475 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1477 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1478 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1480 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1481 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1483 /* switch back to the original context (if there was one)*/
1484 if (This->swapchains) {
1485 /** TODO: restore the context and drawable **/
1486 glXMakeCurrent(object->display, oldDrawable, oldContext);
1491 TRACE("Set swapchain to %p\n", object);
1492 } else { /* something went wrong so clean up */
1493 IUnknown* bufferParent;
1494 if (object->frontBuffer) {
1496 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1497 IUnknown_Release(bufferParent); /* once for the get parent */
1498 if (IUnknown_Release(bufferParent) > 0) {
1499 FIXME("(%p) Something's still holding the front buffer\n",This);
1502 if (object->backBuffer) {
1503 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1504 IUnknown_Release(bufferParent); /* once for the get parent */
1505 if (IUnknown_Release(bufferParent) > 0) {
1506 FIXME("(%p) Something's still holding the back buffer\n",This);
1509 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1510 /* Clean up the context */
1511 /* check that we are the current context first (we shouldn't be though!) */
1512 if (object->glCtx != 0) {
1513 if(glXGetCurrentContext() == object->glCtx) {
1514 glXMakeCurrent(object->display, None, NULL);
1516 glXDestroyContext(object->display, object->glCtx);
1518 HeapFree(GetProcessHeap(), 0, object);
1525 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1526 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1527 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1528 TRACE("(%p)\n", This);
1530 return This->NumberOfSwapChains;
1533 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1534 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1535 TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1537 if(iSwapChain < This->NumberOfSwapChains) {
1538 *pSwapChain = This->swapchains[iSwapChain];
1539 IWineD3DSwapChain_AddRef(*pSwapChain);
1540 TRACE("(%p) returning %p\n", This, *pSwapChain);
1543 TRACE("Swapchain out of range\n");
1545 return WINED3DERR_INVALIDCALL;
1550 * Vertex Declaration
1552 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1553 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1554 IWineD3DVertexDeclarationImpl *object = NULL;
1555 HRESULT hr = WINED3D_OK;
1556 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1557 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1560 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1565 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1566 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pDeclaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1567 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1568 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1569 HRESULT hr = WINED3D_OK;
1570 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1571 object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins;
1573 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1575 /* If a vertex declaration has been passed, save it to the vertex shader, this affects d3d8 only. */
1576 /* Further it needs to be set before calling SetFunction as SetFunction needs the declaration. */
1577 if (pDeclaration != NULL) {
1578 IWineD3DVertexDeclaration *vertexDeclaration;
1579 hr = IWineD3DDevice_CreateVertexDeclaration(iface, pDeclaration, &vertexDeclaration ,NULL);
1580 if (WINED3D_OK == hr) {
1581 TRACE("(%p) : Setting vertex declaration to %p\n", This, vertexDeclaration);
1582 object->vertexDeclaration = vertexDeclaration;
1584 FIXME("(%p) : Failed to set the declaration, returning WINED3DERR_INVALIDCALL\n", iface);
1585 IWineD3DVertexShader_Release(*ppVertexShader);
1586 return WINED3DERR_INVALIDCALL;
1590 hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1592 if (WINED3D_OK != hr) {
1593 FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface);
1594 IWineD3DVertexShader_Release(*ppVertexShader);
1595 return WINED3DERR_INVALIDCALL;
1598 #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. */
1599 if(Usage == WINED3DUSAGE_SOFTWAREVERTEXPROCESSING) {
1610 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
1611 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1612 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1613 HRESULT hr = WINED3D_OK;
1615 D3DCREATEOBJECTINSTANCE(object, PixelShader)
1616 object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins;
1617 hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
1618 if (WINED3D_OK == hr) {
1619 TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
1621 WARN("(%p) : Failed to create pixel shader\n", This);
1627 HRESULT WINAPI IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice *iface, DWORD Flags, PALETTEENTRY *PalEnt, IWineD3DPalette **Palette, IUnknown *Parent) {
1628 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1629 IWineD3DPaletteImpl *object;
1631 TRACE("(%p)->(%lx, %p, %p, %p)\n", This, Flags, PalEnt, Palette, Parent);
1633 /* Create the new object */
1634 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DPaletteImpl));
1636 ERR("Out of memory when allocating memory for a IWineD3DPalette implementation\n");
1637 return E_OUTOFMEMORY;
1640 object->lpVtbl = &IWineD3DPalette_Vtbl;
1642 object->Flags = Flags;
1643 object->parent = Parent;
1644 object->wineD3DDevice = This;
1645 object->palNumEntries = IWineD3DPaletteImpl_Size(Flags);
1647 object->hpal = CreatePalette((const LOGPALETTE*)&(object->palVersion));
1650 HeapFree( GetProcessHeap(), 0, object);
1651 return E_OUTOFMEMORY;
1654 hr = IWineD3DPalette_SetEntries((IWineD3DPalette *) object, 0, 0, IWineD3DPaletteImpl_Size(Flags), PalEnt);
1656 IWineD3DPalette_Release((IWineD3DPalette *) object);
1660 *Palette = (IWineD3DPalette *) object;
1665 HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) {
1666 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1667 IWineD3DSwapChainImpl *swapchain;
1669 TRACE("(%p)->(%p,%p)\n", This, pPresentationParameters, D3DCB_CreateAdditionalSwapChain);
1670 if(This->d3d_initialized) return WINED3DERR_INVALIDCALL;
1672 /* TODO: Test if OpenGL is compiled in and loaded */
1674 /* Setup the implicit swapchain */
1675 TRACE("Creating implicit swapchain\n");
1676 if (D3D_OK != D3DCB_CreateAdditionalSwapChain((IUnknown *) This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain) || swapchain == NULL) {
1677 WARN("Failed to create implicit swapchain\n");
1678 return WINED3DERR_INVALIDCALL;
1681 This->NumberOfSwapChains = 1;
1682 This->swapchains = HeapAlloc(GetProcessHeap(), 0, This->NumberOfSwapChains * sizeof(IWineD3DSwapChain *));
1683 if(!This->swapchains) {
1684 ERR("Out of memory!\n");
1685 IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
1686 return E_OUTOFMEMORY;
1688 This->swapchains[0] = (IWineD3DSwapChain *) swapchain;
1690 if(swapchain->backBuffer) {
1691 TRACE("Setting rendertarget to %p\n", swapchain->backBuffer);
1692 This->renderTarget = swapchain->backBuffer;
1695 TRACE("Setting rendertarget to %p\n", swapchain->frontBuffer);
1696 This->renderTarget = swapchain->frontBuffer;
1698 IWineD3DSurface_AddRef(This->renderTarget);
1699 /* Depth Stencil support */
1700 This->stencilBufferTarget = This->depthStencilBuffer;
1701 if (NULL != This->stencilBufferTarget) {
1702 IWineD3DSurface_AddRef(This->stencilBufferTarget);
1705 /* Set up some starting GL setup */
1708 * Initialize openGL extension related variables
1709 * with Default values
1712 ((IWineD3DImpl *) This->wineD3D)->isGLInfoValid = IWineD3DImpl_FillGLCaps( &((IWineD3DImpl *) This->wineD3D)->gl_info, swapchain->display);
1713 /* Setup all the devices defaults */
1714 IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)This->stateBlock);
1716 IWineD3DImpl_CheckGraphicsMemory();
1720 { /* Set a default viewport */
1724 vp.Width = *(pPresentationParameters->BackBufferWidth);
1725 vp.Height = *(pPresentationParameters->BackBufferHeight);
1728 IWineD3DDevice_SetViewport((IWineD3DDevice *)This, &vp);
1731 /* Initialize the current view state */
1732 This->modelview_valid = 1;
1733 This->proj_valid = 0;
1734 This->view_ident = 1;
1735 This->last_was_rhw = 0;
1736 glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights);
1737 TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This, This);
1739 /* Clear the screen */
1740 IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
1742 This->d3d_initialized = TRUE;
1746 HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface) {
1747 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1749 IUnknown* stencilBufferParent;
1750 IUnknown* swapChainParent;
1752 TRACE("(%p)\n", This);
1754 if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL;
1756 for(texstage = 0; texstage < GL_LIMITS(textures); texstage++) {
1757 IWineD3DDevice_SetTexture(iface, texstage, NULL);
1760 /* Release the buffers (with sanity checks)*/
1761 TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget);
1762 if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
1763 if(This->depthStencilBuffer != This->stencilBufferTarget)
1764 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
1766 This->stencilBufferTarget = NULL;
1768 TRACE("Releasing the render target at %p\n", This->renderTarget);
1769 if(IWineD3DSurface_Release(This->renderTarget) >0){
1770 /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
1772 TRACE("Setting rendertarget to NULL\n");
1773 This->renderTarget = NULL;
1775 IWineD3DSurface_GetParent(This->depthStencilBuffer, &stencilBufferParent);
1776 IUnknown_Release(stencilBufferParent); /* once for the get parent */
1777 if(IUnknown_Release(stencilBufferParent) >0){ /* the second time for when it was created */
1778 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
1780 This->depthStencilBuffer = NULL;
1782 for(i=0; i < This->NumberOfSwapChains; i++) {
1783 TRACE("Releasing the implicit swapchain %d\n", i);
1784 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
1785 IWineD3DSwapChain_GetParent(This->swapchains[i], &swapChainParent);
1786 IUnknown_Release(swapChainParent); /* once for the get parent */
1787 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
1788 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
1792 HeapFree(GetProcessHeap(), 0, This->swapchains);
1793 This->swapchains = NULL;
1794 This->NumberOfSwapChains = 0;
1796 This->d3d_initialized = FALSE;
1800 HRESULT WINAPI IWineD3DDeviceImpl_EnumDisplayModes(IWineD3DDevice *iface, DWORD Flags, UINT Width, UINT Height, WINED3DFORMAT pixelformat, LPVOID context, D3DCB_ENUMDISPLAYMODESCALLBACK callback) {
1801 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1806 TRACE("(%p)->(%lx,%d,%d,%d,%p,%p)\n", This, Flags, Width, Height, pixelformat, context, callback);
1808 for (i = 0; EnumDisplaySettingsExW(NULL, i, &DevModeW, 0); i++) {
1809 /* Ignore some modes if a description was passed */
1810 if ( (Width > 0) && (Width != DevModeW.dmPelsWidth)) continue;
1811 if ( (Height > 0) && (Height != DevModeW.dmPelsHeight)) continue;
1812 if ( (pixelformat != WINED3DFMT_UNKNOWN) && ( D3DFmtGetBpp(NULL, pixelformat) != DevModeW.dmBitsPerPel) ) continue;
1814 TRACE("Enumerating %ldx%ld@%s\n", DevModeW.dmPelsWidth, DevModeW.dmPelsHeight, debug_d3dformat(pixelformat_for_depth(DevModeW.dmBitsPerPel)));
1816 if (callback((IUnknown *) This, (UINT) DevModeW.dmPelsWidth, (UINT) DevModeW.dmPelsHeight, pixelformat_for_depth(DevModeW.dmBitsPerPel), 60.0, context) == DDENUMRET_CANCEL)
1823 HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
1825 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1828 TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This, iSwapChain, pMode, pMode->Width, pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1830 /* Resize the screen even without a window:
1831 * The app could have unset it with SetCooperativeLevel, but not called
1832 * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
1833 * but we don't have any hwnd
1836 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1837 devmode.dmBitsPerPel = D3DFmtGetBpp(This, pMode->Format) * 8;
1838 if(devmode.dmBitsPerPel == 24) devmode.dmBitsPerPel = 32;
1839 devmode.dmPelsWidth = pMode->Width;
1840 devmode.dmPelsHeight = pMode->Height;
1842 devmode.dmDisplayFrequency = pMode->RefreshRate;
1843 if (pMode->RefreshRate != 0) {
1844 devmode.dmFields |= DM_DISPLAYFREQUENCY;
1847 /* Only change the mode if necessary */
1848 if( (This->ddraw_width == pMode->Width) &&
1849 (This->ddraw_height == pMode->Height) &&
1850 (This->ddraw_format == pMode->Format) &&
1851 (pMode->RefreshRate == 0) ) {
1855 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL);
1856 if (ret != DISP_CHANGE_SUCCESSFUL) {
1857 if(devmode.dmDisplayFrequency != 0) {
1858 WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
1859 devmode.dmFields &= ~DM_DISPLAYFREQUENCY;
1860 devmode.dmDisplayFrequency = 0;
1861 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL;
1863 if(ret != DISP_CHANGE_SUCCESSFUL) {
1864 return DDERR_INVALIDMODE;
1868 /* Store the new values */
1869 This->ddraw_width = pMode->Width;
1870 This->ddraw_height = pMode->Height;
1871 This->ddraw_format = pMode->Format;
1873 /* Only do this with a window of course */
1874 if(This->ddraw_window)
1875 MoveWindow(This->ddraw_window, 0, 0, pMode->Width, pMode->Height, TRUE);
1880 HRESULT WINAPI IWineD3DDeviceImpl_EnumZBufferFormats(IWineD3DDevice *iface, D3DCB_ENUMPIXELFORMATS Callback, void *Context) {
1881 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1884 WINED3DFORMAT FormatList[] = {
1891 WINED3DFMT_UNKNOWN /* Terminate the list */
1894 TRACE("(%p)->(%p,%p)\n", This, Callback, Context);
1896 while(FormatList[i] != WINED3DFMT_UNKNOWN) {
1897 TRACE("Enumerating %s\n", debug_d3dformat(FormatList[i]));
1898 ret = Callback((IUnknown *) This, FormatList[i], Context);
1899 if(ret != DDENUMRET_OK) {
1900 TRACE("Enumeration cancelled by Application\n");
1906 TRACE("End of Enumeration\n");
1911 HRESULT WINAPI IWineD3DDeviceImpl_EnumTextureFormats(IWineD3DDevice *iface, D3DCB_ENUMPIXELFORMATS Callback, void *Context) {
1912 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1917 * WINED3DFMT_A1R5G5B5 needs to be the first 16 bit format, as some dumb apps depend on this
1919 * Do not enumerate RGBA pixel formats: "some games choose the first 16 bit texture format
1920 * with alpha they find enumerated, others the last one. And both want to have the ARGB one."
1921 * But WineD3D doesn't support RGBA formats anyway...
1924 WINED3DFORMAT FormatList[] = {
1926 WINED3DFMT_A8R8G8B8,
1927 WINED3DFMT_X8R8G8B8,
1931 WINED3DFMT_A1R5G5B5,
1932 WINED3DFMT_A4R4G4B4,
1934 WINED3DFMT_X1R5G5B5,
1942 /* Terminate the list */
1946 TRACE("(%p)->(%p,%p)\n", This, Callback, Context);
1948 while(FormatList[i] != WINED3DFMT_UNKNOWN) {
1949 TRACE("Enumerating %s\n", debug_d3dformat(FormatList[i]));
1950 ret = Callback((IUnknown *) This, FormatList[i], Context);
1951 if(ret != DDENUMRET_OK) {
1952 TRACE("Enumeration cancelled by Application\n");
1958 TRACE("End of Enumeration\n");
1963 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
1964 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1965 *ppD3D= This->wineD3D;
1966 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1967 IWineD3D_AddRef(*ppD3D);
1971 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1972 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1973 * Into the video ram as possible and seeing how many fit
1974 * you can also get the correct initial value from via X and ATI's driver
1975 *******************/
1976 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1977 static BOOL showfixmes = TRUE;
1979 FIXME("(%p) : stub, emulating %dMB for now, returning %dMB\n", This, (emulated_textureram/(1024*1024)),
1980 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1983 TRACE("(%p) : emulating %dMB for now, returning %dMB\n", This, (emulated_textureram/(1024*1024)),
1984 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1985 /* videomemory is simulated videomemory + AGP memory left */
1986 return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1994 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1995 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1996 HRESULT hr = WINED3D_OK;
1998 /* Update the current state block */
1999 This->updateStateBlock->fvf = fvf;
2000 This->updateStateBlock->changed.fvf = TRUE;
2001 This->updateStateBlock->set.fvf = TRUE;
2003 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
2006 /* clear down the vertex declaration
2007 NOTE: Axis and Allies doesn't work properly otherwise
2008 (may be a stateblock problem though!)
2010 hr = IWineD3DDevice_SetVertexDeclaration(iface, NULL);
2017 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
2018 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2019 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
2020 *pfvf = This->stateBlock->fvf;
2025 * Get / Set Stream Source
2027 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
2028 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2029 IWineD3DVertexBuffer *oldSrc;
2031 /**TODO: instance and index data, see
2032 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2034 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
2037 /* D3d9 only, but shouldn't hurt d3d8 */
2040 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2042 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2043 FIXME("stream index data not supported\n");
2045 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2046 FIXME("stream instance data not supported\n");
2050 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2052 if (StreamNumber >= MAX_STREAMS) {
2053 WARN("Stream out of range %d\n", StreamNumber);
2054 return WINED3DERR_INVALIDCALL;
2057 oldSrc = This->stateBlock->streamSource[StreamNumber];
2058 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
2060 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
2061 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
2062 This->updateStateBlock->streamStride[StreamNumber] = Stride;
2063 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
2064 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
2065 This->updateStateBlock->streamFlags[StreamNumber] = streamFlags;
2067 /* Handle recording of state blocks */
2068 if (This->isRecordingState) {
2069 TRACE("Recording... not performing anything\n");
2073 /* Not recording... */
2074 /* Need to do a getParent and pass the reffs up */
2075 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
2076 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
2077 so for now, just count internally */
2078 if (pStreamData != NULL) {
2079 IWineD3DVertexBuffer_AddRef(pStreamData);
2081 if (oldSrc != NULL) {
2082 IWineD3DVertexBuffer_Release(oldSrc);
2088 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
2089 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2092 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
2093 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
2096 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2098 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2099 FIXME("stream index data not supported\n");
2101 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2102 FIXME("stream instance data not supported\n");
2106 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2108 if (StreamNumber >= MAX_STREAMS) {
2109 WARN("Stream out of range %d\n", StreamNumber);
2110 return WINED3DERR_INVALIDCALL;
2112 *pStream = This->stateBlock->streamSource[StreamNumber];
2113 *pStride = This->stateBlock->streamStride[StreamNumber];
2114 *pOffset = This->stateBlock->streamOffset[StreamNumber];
2116 if (*pStream == NULL) {
2117 FIXME("Attempting to get an empty stream %d, returning WINED3DERR_INVALIDCALL\n", StreamNumber);
2118 return WINED3DERR_INVALIDCALL;
2121 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
2125 /*Should be quite easy, just an extension of vertexdata
2127 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2129 The divider is a bit odd though
2131 VertexOffset = StartVertex / Divider * StreamStride +
2132 VertexIndex / Divider * StreamStride + StreamOffset
2135 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
2136 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2138 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
2139 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (D3DSTREAMSOURCE_INSTANCEDATA | D3DSTREAMSOURCE_INDEXEDDATA );
2141 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
2142 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
2143 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
2145 if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
2146 FIXME("Stream indexing not fully supported\n");
2152 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
2153 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2155 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
2156 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
2158 TRACE("(%p) : returning %d\n", This, *Divider);
2164 * Get / Set & Multiply Transform
2166 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
2167 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2169 /* Most of this routine, comments included copied from ddraw tree initially: */
2170 TRACE("(%p) : Transform State=%d\n", This, d3dts);
2172 /* Handle recording of state blocks */
2173 if (This->isRecordingState) {
2174 TRACE("Recording... not performing anything\n");
2175 This->updateStateBlock->changed.transform[d3dts] = TRUE;
2176 This->updateStateBlock->set.transform[d3dts] = TRUE;
2177 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
2182 * If the new matrix is the same as the current one,
2183 * we cut off any further processing. this seems to be a reasonable
2184 * optimization because as was noticed, some apps (warcraft3 for example)
2185 * tend towards setting the same matrix repeatedly for some reason.
2187 * From here on we assume that the new matrix is different, wherever it matters.
2189 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
2190 TRACE("The app is setting the same matrix over again\n");
2193 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
2197 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2198 where ViewMat = Camera space, WorldMat = world space.
2200 In OpenGL, camera and world space is combined into GL_MODELVIEW
2201 matrix. The Projection matrix stay projection matrix.
2204 /* Capture the times we can just ignore the change for now */
2205 if (d3dts == D3DTS_WORLDMATRIX(0)) {
2206 This->modelview_valid = FALSE;
2209 } else if (d3dts == D3DTS_PROJECTION) {
2210 This->proj_valid = FALSE;
2213 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
2214 /* Indexed Vertex Blending Matrices 256 -> 511 */
2215 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
2216 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
2220 /* Now we really are going to have to change a matrix */
2223 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
2224 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
2225 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
2228 /* If we are changing the View matrix, reset the light and clipping planes to the new view
2229 * NOTE: We have to reset the positions even if the light/plane is not currently
2230 * enabled, since the call to enable it will not reset the position.
2231 * NOTE2: Apparently texture transforms do NOT need reapplying
2234 PLIGHTINFOEL *lightChain = NULL;
2235 This->modelview_valid = FALSE;
2236 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
2238 glMatrixMode(GL_MODELVIEW);
2239 checkGLcall("glMatrixMode(GL_MODELVIEW)");
2241 glLoadMatrixf((float *)lpmatrix);
2242 checkGLcall("glLoadMatrixf(...)");
2245 lightChain = This->stateBlock->lights;
2246 while (lightChain && lightChain->glIndex != -1) {
2247 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
2248 checkGLcall("glLightfv posn");
2249 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
2250 checkGLcall("glLightfv dirn");
2251 lightChain = lightChain->next;
2254 /* Reset Clipping Planes if clipping is enabled */
2255 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2256 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
2257 checkGLcall("glClipPlane");
2261 } else { /* What was requested!?? */
2262 WARN("invalid matrix specified: %i\n", d3dts);
2265 /* Release lock, all done */
2270 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
2271 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2272 TRACE("(%p) : for Transform State %d\n", This, State);
2273 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
2277 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
2278 D3DMATRIX *mat = NULL;
2281 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2282 * below means it will be recorded in a state block change, but it
2283 * works regardless where it is recorded.
2284 * If this is found to be wrong, change to StateBlock.
2286 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2287 TRACE("(%p) : For state %u\n", This, State);
2289 if (State < HIGHEST_TRANSFORMSTATE)
2291 mat = &This->updateStateBlock->transforms[State];
2293 FIXME("Unhandled transform state!!\n");
2296 multiply_matrix(&temp, mat, (D3DMATRIX *) pMatrix);
2298 /* Apply change via set transform - will reapply to eg. lights this way */
2299 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2304 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
2306 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2307 you can reference any indexes you want as long as that number max are enabled at any
2308 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2309 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2310 but when recording, just build a chain pretty much of commands to be replayed. */
2312 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2314 PLIGHTINFOEL *object, *temp;
2316 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2317 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2319 /* If recording state block, just add to end of lights chain */
2320 if (This->isRecordingState) {
2321 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2322 if (NULL == object) {
2323 return WINED3DERR_OUTOFVIDEOMEMORY;
2325 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2326 object->OriginalIndex = Index;
2327 object->glIndex = -1;
2328 object->changed = TRUE;
2330 /* Add to the END of the chain of lights changes to be replayed */
2331 if (This->updateStateBlock->lights == NULL) {
2332 This->updateStateBlock->lights = object;
2334 temp = This->updateStateBlock->lights;
2335 while (temp->next != NULL) temp=temp->next;
2336 temp->next = object;
2338 TRACE("Recording... not performing anything more\n");
2342 /* Ok, not recording any longer so do real work */
2343 object = This->stateBlock->lights;
2344 while (object != NULL && object->OriginalIndex != Index) object = object->next;
2346 /* If we didn't find it in the list of lights, time to add it */
2347 if (object == NULL) {
2348 PLIGHTINFOEL *insertAt,*prevPos;
2350 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2351 if (NULL == object) {
2352 return WINED3DERR_OUTOFVIDEOMEMORY;
2354 object->OriginalIndex = Index;
2355 object->glIndex = -1;
2357 /* Add it to the front of list with the idea that lights will be changed as needed
2358 BUT after any lights currently assigned GL indexes */
2359 insertAt = This->stateBlock->lights;
2361 while (insertAt != NULL && insertAt->glIndex != -1) {
2363 insertAt = insertAt->next;
2366 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2367 This->stateBlock->lights = object;
2368 } else if (insertAt == NULL) { /* End of list */
2369 prevPos->next = object;
2370 object->prev = prevPos;
2371 } else { /* Middle of chain */
2372 if (prevPos == NULL) {
2373 This->stateBlock->lights = object;
2375 prevPos->next = object;
2377 object->prev = prevPos;
2378 object->next = insertAt;
2379 insertAt->prev = object;
2383 /* Initialize the object */
2384 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,
2385 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2386 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2387 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2388 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2389 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2390 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2392 /* Save away the information */
2393 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2395 switch (pLight->Type) {
2396 case D3DLIGHT_POINT:
2398 object->lightPosn[0] = pLight->Position.x;
2399 object->lightPosn[1] = pLight->Position.y;
2400 object->lightPosn[2] = pLight->Position.z;
2401 object->lightPosn[3] = 1.0f;
2402 object->cutoff = 180.0f;
2406 case D3DLIGHT_DIRECTIONAL:
2408 object->lightPosn[0] = -pLight->Direction.x;
2409 object->lightPosn[1] = -pLight->Direction.y;
2410 object->lightPosn[2] = -pLight->Direction.z;
2411 object->lightPosn[3] = 0.0;
2412 object->exponent = 0.0f;
2413 object->cutoff = 180.0f;
2418 object->lightPosn[0] = pLight->Position.x;
2419 object->lightPosn[1] = pLight->Position.y;
2420 object->lightPosn[2] = pLight->Position.z;
2421 object->lightPosn[3] = 1.0;
2424 object->lightDirn[0] = pLight->Direction.x;
2425 object->lightDirn[1] = pLight->Direction.y;
2426 object->lightDirn[2] = pLight->Direction.z;
2427 object->lightDirn[3] = 1.0;
2430 * opengl-ish and d3d-ish spot lights use too different models for the
2431 * light "intensity" as a function of the angle towards the main light direction,
2432 * so we only can approximate very roughly.
2433 * however spot lights are rather rarely used in games (if ever used at all).
2434 * furthermore if still used, probably nobody pays attention to such details.
2436 if (pLight->Falloff == 0) {
2439 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2441 if (rho < 0.0001) rho = 0.0001f;
2442 object->exponent = -0.3/log(cos(rho/2));
2443 object->cutoff = pLight->Phi*90/M_PI;
2449 FIXME("Unrecognized light type %d\n", pLight->Type);
2452 /* Update the live definitions if the light is currently assigned a glIndex */
2453 if (object->glIndex != -1) {
2454 setup_light(iface, object->glIndex, object);
2459 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2460 PLIGHTINFOEL *lightInfo = NULL;
2461 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2462 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2464 /* Locate the light in the live lights */
2465 lightInfo = This->stateBlock->lights;
2466 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2468 if (lightInfo == NULL) {
2469 TRACE("Light information requested but light not defined\n");
2470 return WINED3DERR_INVALIDCALL;
2473 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
2478 * Get / Set Light Enable
2479 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2481 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2482 PLIGHTINFOEL *lightInfo = NULL;
2483 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2484 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2486 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2487 if (This->isRecordingState) {
2488 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2489 if (NULL == lightInfo) {
2490 return WINED3DERR_OUTOFVIDEOMEMORY;
2492 lightInfo->OriginalIndex = Index;
2493 lightInfo->glIndex = -1;
2494 lightInfo->enabledChanged = TRUE;
2496 /* Add to the END of the chain of lights changes to be replayed */
2497 if (This->updateStateBlock->lights == NULL) {
2498 This->updateStateBlock->lights = lightInfo;
2500 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2501 while (temp->next != NULL) temp=temp->next;
2502 temp->next = lightInfo;
2504 TRACE("Recording... not performing anything more\n");
2508 /* Not recording... So, locate the light in the live lights */
2509 lightInfo = This->stateBlock->lights;
2510 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2512 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2513 if (lightInfo == NULL) {
2514 D3DLIGHT9 lightParms;
2515 /* Warning - untested code :-) Prob safe to change fixme to a trace but
2516 wait until someone confirms it seems to work! */
2517 TRACE("Light enabled requested but light not defined, so defining one!\n");
2518 lightParms.Type = D3DLIGHT_DIRECTIONAL;
2519 lightParms.Diffuse.r = 1.0;
2520 lightParms.Diffuse.g = 1.0;
2521 lightParms.Diffuse.b = 1.0;
2522 lightParms.Diffuse.a = 0.0;
2523 lightParms.Specular.r = 0.0;
2524 lightParms.Specular.g = 0.0;
2525 lightParms.Specular.b = 0.0;
2526 lightParms.Specular.a = 0.0;
2527 lightParms.Ambient.r = 0.0;
2528 lightParms.Ambient.g = 0.0;
2529 lightParms.Ambient.b = 0.0;
2530 lightParms.Ambient.a = 0.0;
2531 lightParms.Position.x = 0.0;
2532 lightParms.Position.y = 0.0;
2533 lightParms.Position.z = 0.0;
2534 lightParms.Direction.x = 0.0;
2535 lightParms.Direction.y = 0.0;
2536 lightParms.Direction.z = 1.0;
2537 lightParms.Range = 0.0;
2538 lightParms.Falloff = 0.0;
2539 lightParms.Attenuation0 = 0.0;
2540 lightParms.Attenuation1 = 0.0;
2541 lightParms.Attenuation2 = 0.0;
2542 lightParms.Theta = 0.0;
2543 lightParms.Phi = 0.0;
2544 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
2546 /* Search for it again! Should be fairly quick as near head of list */
2547 lightInfo = This->stateBlock->lights;
2548 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2549 if (lightInfo == NULL) {
2550 FIXME("Adding default lights has failed dismally\n");
2551 return WINED3DERR_INVALIDCALL;
2555 /* OK, we now have a light... */
2556 if (Enable == FALSE) {
2558 /* If we are disabling it, check it was enabled, and
2559 still only do something if it has assigned a glIndex (which it should have!) */
2560 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2561 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2563 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2564 checkGLcall("glDisable GL_LIGHT0+Index");
2567 TRACE("Nothing to do as light was not enabled\n");
2569 lightInfo->lightEnabled = FALSE;
2572 /* We are enabling it. If it is enabled, it's really simple */
2573 if (lightInfo->lightEnabled) {
2575 TRACE("Nothing to do as light was enabled\n");
2577 /* If it already has a glIndex, it's still simple */
2578 } else if (lightInfo->glIndex != -1) {
2579 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2580 lightInfo->lightEnabled = TRUE;
2582 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2583 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2586 /* Otherwise got to find space - lights are ordered gl indexes first */
2588 PLIGHTINFOEL *bsf = NULL;
2589 PLIGHTINFOEL *pos = This->stateBlock->lights;
2590 PLIGHTINFOEL *prev = NULL;
2594 /* Try to minimize changes as much as possible */
2595 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2597 /* Try to remember which index can be replaced if necessary */
2598 if (bsf==NULL && pos->lightEnabled == FALSE) {
2599 /* Found a light we can replace, save as best replacement */
2603 /* Step to next space */
2609 /* If we have too many active lights, fail the call */
2610 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2611 FIXME("Program requests too many concurrent lights\n");
2612 return WINED3DERR_INVALIDCALL;
2614 /* If we have allocated all lights, but not all are enabled,
2615 reuse one which is not enabled */
2616 } else if (Index == This->maxConcurrentLights) {
2617 /* use bsf - Simply swap the new light and the BSF one */
2618 PLIGHTINFOEL *bsfNext = bsf->next;
2619 PLIGHTINFOEL *bsfPrev = bsf->prev;
2622 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2623 if (bsf->prev != NULL) {
2624 bsf->prev->next = lightInfo;
2626 This->stateBlock->lights = lightInfo;
2629 /* If not side by side, lots of chains to update */
2630 if (bsf->next != lightInfo) {
2631 lightInfo->prev->next = bsf;
2632 bsf->next->prev = lightInfo;
2633 bsf->next = lightInfo->next;
2634 bsf->prev = lightInfo->prev;
2635 lightInfo->next = bsfNext;
2636 lightInfo->prev = bsfPrev;
2640 bsf->prev = lightInfo;
2641 bsf->next = lightInfo->next;
2642 lightInfo->next = bsf;
2643 lightInfo->prev = bsfPrev;
2648 glIndex = bsf->glIndex;
2650 lightInfo->glIndex = glIndex;
2651 lightInfo->lightEnabled = TRUE;
2653 /* Finally set up the light in gl itself */
2654 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2656 setup_light(iface, glIndex, lightInfo);
2657 glEnable(GL_LIGHT0 + glIndex);
2658 checkGLcall("glEnable GL_LIGHT0 new setup");
2661 /* If we reached the end of the allocated lights, with space in the
2662 gl lights, setup a new light */
2663 } else if (pos->glIndex == -1) {
2665 /* We reached the end of the allocated gl lights, so already
2666 know the index of the next one! */
2668 lightInfo->glIndex = glIndex;
2669 lightInfo->lightEnabled = TRUE;
2671 /* In an ideal world, it's already in the right place */
2672 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2673 /* No need to move it */
2675 /* Remove this light from the list */
2676 lightInfo->prev->next = lightInfo->next;
2677 if (lightInfo->next != NULL) {
2678 lightInfo->next->prev = lightInfo->prev;
2681 /* Add in at appropriate place (inbetween prev and pos) */
2682 lightInfo->prev = prev;
2683 lightInfo->next = pos;
2685 This->stateBlock->lights = lightInfo;
2687 prev->next = lightInfo;
2690 pos->prev = lightInfo;
2694 /* Finally set up the light in gl itself */
2695 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2697 setup_light(iface, glIndex, lightInfo);
2698 glEnable(GL_LIGHT0 + glIndex);
2699 checkGLcall("glEnable GL_LIGHT0 new setup");
2708 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2710 PLIGHTINFOEL *lightInfo = NULL;
2711 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2712 TRACE("(%p) : for idx(%ld)\n", This, Index);
2714 /* Locate the light in the live lights */
2715 lightInfo = This->stateBlock->lights;
2716 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2718 if (lightInfo == NULL) {
2719 TRACE("Light enabled state requested but light not defined\n");
2720 return WINED3DERR_INVALIDCALL;
2722 *pEnable = lightInfo->lightEnabled;
2727 * Get / Set Clip Planes
2729 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2730 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2731 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2733 /* Validate Index */
2734 if (Index >= GL_LIMITS(clipplanes)) {
2735 TRACE("Application has requested clipplane this device doesn't support\n");
2736 return WINED3DERR_INVALIDCALL;
2739 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2740 This->updateStateBlock->set.clipplane[Index] = TRUE;
2741 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2742 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2743 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2744 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2746 /* Handle recording of state blocks */
2747 if (This->isRecordingState) {
2748 TRACE("Recording... not performing anything\n");
2756 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2757 glMatrixMode(GL_MODELVIEW);
2759 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2761 TRACE("Clipplane [%f,%f,%f,%f]\n",
2762 This->updateStateBlock->clipplane[Index][0],
2763 This->updateStateBlock->clipplane[Index][1],
2764 This->updateStateBlock->clipplane[Index][2],
2765 This->updateStateBlock->clipplane[Index][3]);
2766 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2767 checkGLcall("glClipPlane");
2775 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2776 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2777 TRACE("(%p) : for idx %ld\n", This, Index);
2779 /* Validate Index */
2780 if (Index >= GL_LIMITS(clipplanes)) {
2781 TRACE("Application has requested clipplane this device doesn't support\n");
2782 return WINED3DERR_INVALIDCALL;
2785 pPlane[0] = This->stateBlock->clipplane[Index][0];
2786 pPlane[1] = This->stateBlock->clipplane[Index][1];
2787 pPlane[2] = This->stateBlock->clipplane[Index][2];
2788 pPlane[3] = This->stateBlock->clipplane[Index][3];
2793 * Get / Set Clip Plane Status
2794 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2796 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2797 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2798 FIXME("(%p) : stub\n", This);
2799 if (NULL == pClipStatus) {
2800 return WINED3DERR_INVALIDCALL;
2802 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2803 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2807 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2808 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2809 FIXME("(%p) : stub\n", This);
2810 if (NULL == pClipStatus) {
2811 return WINED3DERR_INVALIDCALL;
2813 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2814 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2819 * Get / Set Material
2820 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2822 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2823 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2825 This->updateStateBlock->changed.material = TRUE;
2826 This->updateStateBlock->set.material = TRUE;
2827 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2829 /* Handle recording of state blocks */
2830 if (This->isRecordingState) {
2831 TRACE("Recording... not performing anything\n");
2836 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2837 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2838 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2839 pMaterial->Ambient.b, pMaterial->Ambient.a);
2840 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2841 pMaterial->Specular.b, pMaterial->Specular.a);
2842 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2843 pMaterial->Emissive.b, pMaterial->Emissive.a);
2844 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2846 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2847 checkGLcall("glMaterialfv(GL_AMBIENT)");
2848 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2849 checkGLcall("glMaterialfv(GL_DIFFUSE)");
2851 /* Only change material color if specular is enabled, otherwise it is set to black */
2852 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2853 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2854 checkGLcall("glMaterialfv(GL_SPECULAR");
2856 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2857 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2858 checkGLcall("glMaterialfv(GL_SPECULAR");
2860 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2861 checkGLcall("glMaterialfv(GL_EMISSION)");
2862 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2863 checkGLcall("glMaterialf(GL_SHININESS");
2869 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2870 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2871 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2872 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2873 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2874 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2875 pMaterial->Ambient.b, pMaterial->Ambient.a);
2876 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2877 pMaterial->Specular.b, pMaterial->Specular.a);
2878 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2879 pMaterial->Emissive.b, pMaterial->Emissive.a);
2880 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2888 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2889 UINT BaseVertexIndex) {
2890 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2891 IWineD3DIndexBuffer *oldIdxs;
2893 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2894 oldIdxs = This->updateStateBlock->pIndexData;
2896 This->updateStateBlock->changed.indices = TRUE;
2897 This->updateStateBlock->set.indices = TRUE;
2898 This->updateStateBlock->pIndexData = pIndexData;
2899 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2901 /* Handle recording of state blocks */
2902 if (This->isRecordingState) {
2903 TRACE("Recording... not performing anything\n");
2907 if (NULL != pIndexData) {
2908 IWineD3DIndexBuffer_AddRef(pIndexData);
2910 if (NULL != oldIdxs) {
2911 IWineD3DIndexBuffer_Release(oldIdxs);
2916 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2917 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2919 *ppIndexData = This->stateBlock->pIndexData;
2921 /* up ref count on ppindexdata */
2923 IWineD3DIndexBuffer_AddRef(*ppIndexData);
2924 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2925 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
2927 TRACE("(%p) No index data set\n", This);
2929 TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
2935 * Get / Set Viewports
2937 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2938 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2940 TRACE("(%p)\n", This);
2941 This->updateStateBlock->changed.viewport = TRUE;
2942 This->updateStateBlock->set.viewport = TRUE;
2943 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2945 /* Handle recording of state blocks */
2946 if (This->isRecordingState) {
2947 TRACE("Recording... not performing anything\n");
2950 This->viewport_changed = TRUE;
2954 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2955 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2957 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2958 checkGLcall("glDepthRange");
2959 /* Note: GL requires lower left, DirectX supplies upper left */
2960 /* TODO: replace usage of renderTarget with context management */
2961 glViewport(pViewport->X,
2962 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2963 pViewport->Width, pViewport->Height);
2965 checkGLcall("glViewport");
2973 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2974 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2975 TRACE("(%p)\n", This);
2976 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2981 * Get / Set Render States
2982 * TODO: Verify against dx9 definitions
2984 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2986 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2987 DWORD OldValue = This->stateBlock->renderState[State];
2989 /* Simple way of referring to either a DWORD or a 4 byte float */
2995 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2996 This->updateStateBlock->changed.renderState[State] = TRUE;
2997 This->updateStateBlock->set.renderState[State] = TRUE;
2998 This->updateStateBlock->renderState[State] = Value;
3000 /* Handle recording of state blocks */
3001 if (This->isRecordingState) {
3002 TRACE("Recording... not performing anything\n");
3009 case WINED3DRS_FILLMODE :
3010 switch ((D3DFILLMODE) Value) {
3011 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
3012 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
3013 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
3015 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
3017 checkGLcall("glPolygonMode (fillmode)");
3020 case WINED3DRS_LIGHTING :
3022 glEnable(GL_LIGHTING);
3023 checkGLcall("glEnable GL_LIGHTING");
3025 glDisable(GL_LIGHTING);
3026 checkGLcall("glDisable GL_LIGHTING");
3030 case WINED3DRS_ZENABLE :
3031 switch ((D3DZBUFFERTYPE) Value) {
3033 glDisable(GL_DEPTH_TEST);
3034 checkGLcall("glDisable GL_DEPTH_TEST");
3037 glEnable(GL_DEPTH_TEST);
3038 checkGLcall("glEnable GL_DEPTH_TEST");
3041 glEnable(GL_DEPTH_TEST);
3042 checkGLcall("glEnable GL_DEPTH_TEST");
3043 FIXME("W buffer is not well handled\n");
3046 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
3050 case WINED3DRS_CULLMODE :
3052 /* If we are culling "back faces with clockwise vertices" then
3053 set front faces to be counter clockwise and enable culling
3055 switch ((D3DCULL) Value) {
3057 glDisable(GL_CULL_FACE);
3058 checkGLcall("glDisable GL_CULL_FACE");
3061 glEnable(GL_CULL_FACE);
3062 checkGLcall("glEnable GL_CULL_FACE");
3063 if (This->renderUpsideDown) {
3065 checkGLcall("glFrontFace GL_CW");
3067 glFrontFace(GL_CCW);
3068 checkGLcall("glFrontFace GL_CCW");
3070 glCullFace(GL_BACK);
3073 glEnable(GL_CULL_FACE);
3074 checkGLcall("glEnable GL_CULL_FACE");
3075 if (This->renderUpsideDown) {
3076 glFrontFace(GL_CCW);
3077 checkGLcall("glFrontFace GL_CCW");
3080 checkGLcall("glFrontFace GL_CW");
3082 glCullFace(GL_BACK);
3085 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
3089 case WINED3DRS_SHADEMODE :
3090 switch ((D3DSHADEMODE) Value) {
3092 glShadeModel(GL_FLAT);
3093 checkGLcall("glShadeModel");
3095 case D3DSHADE_GOURAUD:
3096 glShadeModel(GL_SMOOTH);
3097 checkGLcall("glShadeModel");
3099 case D3DSHADE_PHONG:
3100 FIXME("D3DSHADE_PHONG isn't supported?\n");
3103 return WINED3DERR_INVALIDCALL;
3105 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
3109 case WINED3DRS_DITHERENABLE :
3111 glEnable(GL_DITHER);
3112 checkGLcall("glEnable GL_DITHER");
3114 glDisable(GL_DITHER);
3115 checkGLcall("glDisable GL_DITHER");
3119 case WINED3DRS_ZWRITEENABLE :
3122 checkGLcall("glDepthMask");
3125 checkGLcall("glDepthMask");
3129 case WINED3DRS_ZFUNC :
3131 int glParm = GL_LESS;
3133 switch ((D3DCMPFUNC) Value) {
3134 case D3DCMP_NEVER: glParm=GL_NEVER; break;
3135 case D3DCMP_LESS: glParm=GL_LESS; break;
3136 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
3137 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
3138 case D3DCMP_GREATER: glParm=GL_GREATER; break;
3139 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
3140 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
3141 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
3143 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3145 glDepthFunc(glParm);
3146 checkGLcall("glDepthFunc");
3150 case WINED3DRS_AMBIENT :
3153 D3DCOLORTOGLFLOAT4(Value, col);
3154 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
3155 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
3156 checkGLcall("glLightModel for MODEL_AMBIENT");
3161 case WINED3DRS_ALPHABLENDENABLE :
3164 checkGLcall("glEnable GL_BLEND");
3166 glDisable(GL_BLEND);
3167 checkGLcall("glDisable GL_BLEND");
3171 case WINED3DRS_SRCBLEND :
3172 case WINED3DRS_DESTBLEND :
3174 int newVal = GL_ZERO;
3176 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
3177 case D3DBLEND_ONE : newVal = GL_ONE; break;
3178 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
3179 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
3180 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
3181 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
3182 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
3183 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
3184 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
3185 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
3186 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
3188 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
3189 This->srcBlend = newVal;
3190 This->dstBlend = newVal;
3193 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
3194 This->srcBlend = newVal;
3195 This->dstBlend = newVal;
3198 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
3201 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
3202 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
3203 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
3204 glBlendFunc(This->srcBlend, This->dstBlend);
3206 checkGLcall("glBlendFunc");
3210 case WINED3DRS_ALPHATESTENABLE :
3211 case WINED3DRS_ALPHAFUNC :
3212 case WINED3DRS_ALPHAREF :
3213 case WINED3DRS_COLORKEYENABLE :
3216 float ref = GL_LESS;
3217 BOOL enable_ckey = FALSE;
3219 IWineD3DSurfaceImpl *surf;
3221 /* Find out if the texture on the first stage has a ckey set */
3222 if(This->stateBlock->textures[0]) {
3223 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)This->stateBlock->textures[0])->surfaces[0];
3224 if(surf->CKeyFlags & DDSD_CKSRCBLT) enable_ckey = TRUE;
3227 if (This->stateBlock->renderState[WINED3DRS_ALPHATESTENABLE] ||
3228 (This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey)) {
3229 glEnable(GL_ALPHA_TEST);
3230 checkGLcall("glEnable GL_ALPHA_TEST");
3232 glDisable(GL_ALPHA_TEST);
3233 checkGLcall("glDisable GL_ALPHA_TEST");
3234 /* Alpha test is disabled, don't bother setting the params - it will happen on the next
3240 if(This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) {
3241 glParm = GL_NOTEQUAL;
3244 ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
3246 switch ((D3DCMPFUNC) This->stateBlock->renderState[WINED3DRS_ALPHAFUNC]) {
3247 case D3DCMP_NEVER: glParm = GL_NEVER; break;
3248 case D3DCMP_LESS: glParm = GL_LESS; break;
3249 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
3250 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
3251 case D3DCMP_GREATER: glParm = GL_GREATER; break;
3252 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
3253 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
3254 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
3256 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3259 This->alphafunc = glParm;
3260 glAlphaFunc(glParm, ref);
3261 checkGLcall("glAlphaFunc");
3265 case WINED3DRS_CLIPPLANEENABLE :
3266 case WINED3DRS_CLIPPING :
3268 /* Ensure we only do the changed clip planes */
3269 DWORD enable = 0xFFFFFFFF;
3270 DWORD disable = 0x00000000;
3272 /* If enabling / disabling all */
3273 if (State == WINED3DRS_CLIPPING) {
3275 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3278 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3282 enable = Value & ~OldValue;
3283 disable = ~Value & OldValue;
3286 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
3287 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
3288 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
3289 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
3290 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
3291 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
3293 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
3294 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
3295 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
3296 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
3297 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
3298 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
3300 /** update clipping status */
3302 This->stateBlock->clip_status.ClipUnion = 0;
3303 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
3305 This->stateBlock->clip_status.ClipUnion = 0;
3306 This->stateBlock->clip_status.ClipIntersection = 0;
3311 case WINED3DRS_BLENDOP :
3313 int glParm = GL_FUNC_ADD;
3315 switch ((D3DBLENDOP) Value) {
3316 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
3317 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
3318 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3319 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
3320 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
3322 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
3325 if(GL_SUPPORT(ARB_IMAGING)) {
3326 TRACE("glBlendEquation(%x)\n", glParm);
3327 GL_EXTCALL(glBlendEquation(glParm));
3328 checkGLcall("glBlendEquation");
3330 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
3335 case WINED3DRS_TEXTUREFACTOR :
3339 /* Note the texture color applies to all textures whereas
3340 GL_TEXTURE_ENV_COLOR applies to active only */
3342 D3DCOLORTOGLFLOAT4(Value, col);
3343 /* Set the default alpha blend color */
3344 if (GL_SUPPORT(ARB_IMAGING)) {
3345 GL_EXTCALL(glBlendColor(col[0], col[1], col[2], col[3]));
3346 checkGLcall("glBlendColor");
3348 WARN("Unsupported in local OpenGL implementation: glBlendColor\n");
3351 /* And now the default texture color as well */
3352 for (i = 0; i < GL_LIMITS(textures); i++) {
3354 /* Note the D3DRS value applies to all textures, but GL has one
3355 per texture, so apply it now ready to be used! */
3356 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3357 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
3358 checkGLcall("glActiveTextureARB");
3360 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3363 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3364 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3369 case WINED3DRS_SPECULARENABLE :
3371 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3372 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3373 specular color. This is wrong:
3374 Separate specular color means the specular colour is maintained separately, whereas
3375 single color means it is merged in. However in both cases they are being used to
3377 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3378 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3382 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3383 checkGLcall("glMaterialfv");
3384 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3385 glEnable(GL_COLOR_SUM_EXT);
3387 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3389 checkGLcall("glEnable(GL_COLOR_SUM)");
3391 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3393 /* for the case of enabled lighting: */
3394 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3395 checkGLcall("glMaterialfv");
3397 /* for the case of disabled lighting: */
3398 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3399 glDisable(GL_COLOR_SUM_EXT);
3401 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3403 checkGLcall("glDisable(GL_COLOR_SUM)");
3408 case WINED3DRS_STENCILENABLE :
3410 glEnable(GL_STENCIL_TEST);
3411 checkGLcall("glEnable GL_STENCIL_TEST");
3413 glDisable(GL_STENCIL_TEST);
3414 checkGLcall("glDisable GL_STENCIL_TEST");
3418 case WINED3DRS_STENCILFUNC :
3421 GLint ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3422 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3425 switch ((D3DCMPFUNC)Value) {
3426 case D3DCMP_NEVER: func = GL_NEVER; break;
3427 case D3DCMP_LESS: func = GL_LESS; break;
3428 case D3DCMP_EQUAL: func = GL_EQUAL; break;
3429 case D3DCMP_LESSEQUAL: func = GL_LEQUAL; break;
3430 case D3DCMP_GREATER: func = GL_GREATER; break;
3431 case D3DCMP_NOTEQUAL: func = GL_NOTEQUAL; break;
3432 case D3DCMP_GREATEREQUAL: func = GL_GEQUAL; break;
3433 case D3DCMP_ALWAYS: func = GL_ALWAYS; break;
3435 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3437 This->stencilfunc = func;
3438 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3439 #if 0 /* Don't use OpenGL 2.0 calls for now */
3440 if(GL_EXTCALL(glStencilFuncSeparate)) {
3441 GL_EXTCALL(glStencilFuncSeparate(GL_FRONT, func, ref, mask));
3442 checkGLcall("glStencilFuncSeparate(GL_FRONT,...)");
3446 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3447 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3448 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3449 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
3450 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
3451 glStencilFunc(func, ref, mask);
3452 checkGLcall("glStencilFunc(...)");
3454 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3455 GL_EXTCALL(glStencilFuncSeparateATI(GL_FRONT, func, ref, mask));
3456 checkGLcall("glStencilFuncSeparateATI(GL_FRONT,...)");
3458 TRACE("Separate stencil function not supported on this version of opengl");
3459 glStencilFunc(func, ref, mask);
3460 checkGLcall("glStencilFunc(...)");
3463 glStencilFunc(func, ref, mask);
3464 checkGLcall("glStencilFunc(...)");
3468 case WINED3DRS_STENCILREF :
3470 int glParm = This->stencilfunc;
3472 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3475 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3476 glStencilFunc(glParm, ref, mask);
3477 checkGLcall("glStencilFunc");
3481 case WINED3DRS_STENCILMASK :
3483 int glParm = This->stencilfunc;
3484 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3485 GLuint mask = Value;
3487 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3488 glStencilFunc(glParm, ref, mask);
3489 checkGLcall("glStencilFunc");
3493 case WINED3DRS_STENCILFAIL :
3494 case WINED3DRS_STENCILZFAIL :
3495 case WINED3DRS_STENCILPASS :
3501 GLint action = StencilOp(Value);
3503 glGetIntegerv(GL_STENCIL_FAIL, &stencilFail);
3504 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &depthFail);
3505 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &stencilPass);
3507 if(WINED3DRS_STENCILFAIL == State) {
3508 stencilFail = action;
3510 else if(WINED3DRS_STENCILZFAIL == State) {
3513 else if(WINED3DRS_STENCILPASS == State) {
3514 stencilPass = action;
3517 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3518 #if 0 /* Don't use OpenGL 2.0 calls for now */
3519 if(GL_EXTCALL(glStencilOpSeparate)) {
3520 GL_EXTCALL(glStencilOpSeparate(GL_FRONT, stencilFail, depthFail, stencilPass));
3521 checkGLcall("glStencilOpSeparate(GL_FRONT,...)");
3525 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3526 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3527 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3528 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
3529 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
3530 glStencilOp(stencilFail, depthFail, stencilPass);
3531 checkGLcall("glStencilOp(...)");
3533 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3534 GL_EXTCALL(glStencilOpSeparateATI(GL_FRONT, stencilFail, depthFail, stencilPass));
3535 checkGLcall("glStencilOpSeparateATI(GL_FRONT,...)");
3537 TRACE("Separate stencil operation not supported on this version of opengl");
3538 glStencilOp(stencilFail, depthFail, stencilPass);
3539 checkGLcall("glStencilOp(...)");
3542 glStencilOp(stencilFail, depthFail, stencilPass);
3543 checkGLcall("glStencilOp(...)");
3547 case WINED3DRS_STENCILWRITEMASK :
3549 glStencilMask(Value);
3550 TRACE("glStencilMask(%lu)\n", Value);
3551 checkGLcall("glStencilMask");
3555 case WINED3DRS_FOGENABLE :
3557 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
3559 checkGLcall("glEnable GL_FOG");
3562 checkGLcall("glDisable GL_FOG");
3567 case WINED3DRS_RANGEFOGENABLE :
3570 TRACE("Enabled RANGEFOG");
3572 TRACE("Disabled RANGEFOG");
3577 case WINED3DRS_FOGCOLOR :
3580 D3DCOLORTOGLFLOAT4(Value, col);
3581 /* Set the default alpha blend color */
3582 glFogfv(GL_FOG_COLOR, &col[0]);
3583 checkGLcall("glFog GL_FOG_COLOR");
3587 case WINED3DRS_FOGTABLEMODE :
3589 glHint(GL_FOG_HINT, GL_NICEST);
3592 if(This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] == D3DFOG_NONE) {
3593 glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
3595 /* Otherwise leave the vertex fog value */
3598 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3599 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3600 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3602 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3604 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3605 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3610 case WINED3DRS_FOGVERTEXMODE :
3612 glHint(GL_FOG_HINT, GL_FASTEST);
3613 /* DX 7 sdk: "If both render states(vertex and table fog) are set to valid modes, the system will apply only pixel(=table) fog effects." */
3614 if(This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == D3DFOG_NONE) {
3616 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3617 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3619 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3621 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3623 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3624 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
3630 case WINED3DRS_FOGSTART :
3633 glFogfv(GL_FOG_START, &tmpvalue.f);
3634 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3635 TRACE("Fog Start == %f\n", tmpvalue.f);
3639 case WINED3DRS_FOGEND :
3642 glFogfv(GL_FOG_END, &tmpvalue.f);
3643 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3644 TRACE("Fog End == %f\n", tmpvalue.f);
3648 case WINED3DRS_FOGDENSITY :
3651 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3652 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3656 case WINED3DRS_VERTEXBLEND :
3658 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3659 TRACE("Vertex Blending state to %ld\n", Value);
3663 case WINED3DRS_TWEENFACTOR :
3666 This->updateStateBlock->tween_factor = tmpvalue.f;
3667 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3671 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
3673 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3677 case WINED3DRS_COLORVERTEX :
3678 case WINED3DRS_DIFFUSEMATERIALSOURCE :
3679 case WINED3DRS_SPECULARMATERIALSOURCE :
3680 case WINED3DRS_AMBIENTMATERIALSOURCE :
3681 case WINED3DRS_EMISSIVEMATERIALSOURCE :
3683 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3685 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3686 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3687 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3688 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3689 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3690 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3692 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3693 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3694 Parm = GL_AMBIENT_AND_DIFFUSE;
3698 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3700 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3702 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3709 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3711 This->tracking_color = NEEDS_TRACKING;
3712 This->tracking_parm = Parm;
3716 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3721 case WINED3DRS_LINEPATTERN :
3727 tmppattern.d = Value;
3729 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3731 if (tmppattern.lp.wRepeatFactor) {
3732 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3733 checkGLcall("glLineStipple(repeat, linepattern)");
3734 glEnable(GL_LINE_STIPPLE);
3735 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3737 glDisable(GL_LINE_STIPPLE);
3738 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3743 case WINED3DRS_ZBIAS : /* D3D8 only */
3747 TRACE("ZBias value %f\n", tmpvalue.f);
3748 glPolygonOffset(0, -tmpvalue.f);
3749 checkGLcall("glPolygonOffset(0, -Value)");
3750 glEnable(GL_POLYGON_OFFSET_FILL);
3751 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3752 glEnable(GL_POLYGON_OFFSET_LINE);
3753 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3754 glEnable(GL_POLYGON_OFFSET_POINT);
3755 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3757 glDisable(GL_POLYGON_OFFSET_FILL);
3758 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3759 glDisable(GL_POLYGON_OFFSET_LINE);
3760 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3761 glDisable(GL_POLYGON_OFFSET_POINT);
3762 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3767 case WINED3DRS_NORMALIZENORMALS :
3769 glEnable(GL_NORMALIZE);
3770 checkGLcall("glEnable(GL_NORMALIZE);");
3772 glDisable(GL_NORMALIZE);
3773 checkGLcall("glDisable(GL_NORMALIZE);");
3777 case WINED3DRS_POINTSIZE :
3778 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
3780 TRACE("Set point size to %f\n", tmpvalue.f);
3781 glPointSize(tmpvalue.f);
3782 checkGLcall("glPointSize(...);");
3785 case WINED3DRS_POINTSIZE_MIN :
3786 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3788 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3789 checkGLcall("glPointParameterfEXT(...);");
3791 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3795 case WINED3DRS_POINTSIZE_MAX :
3796 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3798 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3799 checkGLcall("glPointParameterfEXT(...);");
3801 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3805 case WINED3DRS_POINTSCALE_A :
3806 case WINED3DRS_POINTSCALE_B :
3807 case WINED3DRS_POINTSCALE_C :
3808 case WINED3DRS_POINTSCALEENABLE :
3811 * POINTSCALEENABLE controls how point size value is treated. If set to
3812 * true, the point size is scaled with respect to height of viewport.
3813 * When set to false point size is in pixels.
3815 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
3818 /* Default values */
3819 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3822 * Minimum valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
3823 * This means that OpenGL will clamp really small point sizes to 1.0f.
3824 * To correct for this we need to multiply by the scale factor when sizes
3825 * are less than 1.0f. scale_factor = 1.0f / point_size.
3827 GLfloat pointSize = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSIZE]);
3828 if(pointSize > 0.0f) {
3829 GLfloat scaleFactor;
3831 if(pointSize < 1.0f) {
3832 scaleFactor = pointSize * pointSize;
3837 if(This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3838 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]) /
3839 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3840 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]) /
3841 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3842 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) /
3843 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3847 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
3848 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
3849 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
3851 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3852 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3853 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
3855 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
3859 case WINED3DRS_COLORWRITEENABLE :
3861 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3862 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3863 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3864 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3865 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3866 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3867 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3868 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3869 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3870 checkGLcall("glColorMask(...)");
3874 case WINED3DRS_LOCALVIEWER :
3876 GLint state = (Value) ? 1 : 0;
3877 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3878 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3882 case WINED3DRS_LASTPIXEL :
3885 TRACE("Last Pixel Drawing Enabled\n");
3887 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3892 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3895 TRACE("Software Processing Enabled\n");
3897 TRACE("Software Processing Disabled\n");
3902 /** not supported */
3903 case WINED3DRS_ZVISIBLE :
3906 return WINED3DERR_INVALIDCALL;
3908 case WINED3DRS_POINTSPRITEENABLE :
3910 /* TODO: NV_POINT_SPRITE */
3911 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
3912 TRACE("Point sprites not supported\n");
3917 * Point sprites are always enabled. Value controls texture coordinate
3918 * replacement mode. Must be set true for point sprites to use
3921 glEnable(GL_POINT_SPRITE_ARB);
3922 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
3925 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
3926 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, TRUE)");
3928 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, FALSE);
3929 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, FALSE)");
3933 case WINED3DRS_EDGEANTIALIAS :
3936 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3938 checkGLcall("glEnable(GL_BLEND)");
3939 glEnable(GL_LINE_SMOOTH);
3940 checkGLcall("glEnable(GL_LINE_SMOOTH)");
3942 if(!This->stateBlock->renderState[WINED3DRS_ALPHABLENDENABLE])
3943 glDisable(GL_BLEND);
3944 checkGLcall("glDisable(GL_BLEND)");
3945 glDisable(GL_LINE_SMOOTH);
3946 checkGLcall("glDisable(GL_LINE_SMOOTH)");
3950 case WINED3DRS_WRAP0 :
3951 case WINED3DRS_WRAP1 :
3952 case WINED3DRS_WRAP2 :
3953 case WINED3DRS_WRAP3 :
3954 case WINED3DRS_WRAP4 :
3955 case WINED3DRS_WRAP5 :
3956 case WINED3DRS_WRAP6 :
3957 case WINED3DRS_WRAP7 :
3958 case WINED3DRS_WRAP8 :
3959 case WINED3DRS_WRAP9 :
3960 case WINED3DRS_WRAP10 :
3961 case WINED3DRS_WRAP11 :
3962 case WINED3DRS_WRAP12 :
3963 case WINED3DRS_WRAP13 :
3964 case WINED3DRS_WRAP14 :
3965 case WINED3DRS_WRAP15 :
3967 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
3968 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
3969 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
3970 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
3971 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
3973 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
3975 TRACE("(%p)->(%s,%ld) Texture wraping not yet supported\n",This, debug_d3drenderstate(State), Value);
3977 case WINED3DRS_MULTISAMPLEANTIALIAS :
3979 if (!GL_SUPPORT(ARB_MULTISAMPLE)) {
3980 TRACE("Multisample antialiasing not supported\n");
3985 glEnable(GL_MULTISAMPLE_ARB);
3986 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
3988 glDisable(GL_MULTISAMPLE_ARB);
3989 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
3993 case WINED3DRS_SCISSORTESTENABLE :
3996 glEnable(GL_SCISSOR_TEST);
3997 checkGLcall("glEnable(GL_SCISSOR_TEST)");
3999 glDisable(GL_SCISSOR_TEST);
4000 checkGLcall("glDisable(GL_SCISSOR_TEST)");
4004 case WINED3DRS_SLOPESCALEDEPTHBIAS :
4008 glEnable(GL_POLYGON_OFFSET_FILL);
4009 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4010 glPolygonOffset(tmpvalue.f, *((float*)&This->stateBlock->renderState[WINED3DRS_DEPTHBIAS]));
4011 checkGLcall("glPolygonOffset(...)");
4013 glDisable(GL_POLYGON_OFFSET_FILL);
4014 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4018 case WINED3DRS_ANTIALIASEDLINEENABLE :
4021 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4023 checkGLcall("glEnable(GL_BLEND)");
4024 glEnable(GL_LINE_SMOOTH);
4025 checkGLcall("glEnable(GL_LINE_SMOOTH)");
4027 glDisable(GL_BLEND);
4028 checkGLcall("glDisable(GL_BLEND)");
4029 glDisable(GL_LINE_SMOOTH);
4030 checkGLcall("glDisable(GL_LINE_SMOOTH)");
4034 case WINED3DRS_TWOSIDEDSTENCILMODE :
4037 TRACE("Two-sided stencil mode enabled\n");
4039 TRACE("Two-sided stencil mode disabled\n");
4043 case WINED3DRS_CCW_STENCILFAIL :
4044 case WINED3DRS_CCW_STENCILZFAIL :
4045 case WINED3DRS_CCW_STENCILPASS :
4051 GLint action = StencilOp(Value);
4053 glGetIntegerv(GL_STENCIL_BACK_FAIL, &stencilFail);
4054 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &depthFail);
4055 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS, &stencilPass);
4057 if(WINED3DRS_CCW_STENCILFAIL == State) {
4058 stencilFail = action;
4060 else if(WINED3DRS_CCW_STENCILZFAIL == State) {
4063 else if(WINED3DRS_CCW_STENCILPASS == State) {
4064 stencilPass = action;
4067 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
4068 #if 0 /* Don't use OpenGL 2.0 calls for now */
4069 if(GL_EXTCALL(glStencilOpSeparate)) {
4070 GL_EXTCALL(glStencilOpSeparate(GL_BACK, stencilFail, depthFail, stencilPass));
4071 checkGLcall("glStencilOpSeparate(GL_BACK,...)");
4075 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
4076 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
4077 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
4078 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
4079 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
4080 glStencilOp(stencilFail, depthFail, stencilPass);
4081 checkGLcall("glStencilOp(...)");
4083 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
4084 GL_EXTCALL(glStencilOpSeparateATI(GL_BACK, stencilFail, depthFail, stencilPass));
4085 checkGLcall("glStencilOpSeparateATI(GL_BACK,...)");
4087 TRACE("Separate stencil operation not supported on this version of opengl");
4088 glStencilOp(stencilFail, depthFail, stencilPass);
4089 checkGLcall("glStencilOp(...)");
4092 glStencilOp(stencilFail, depthFail, stencilPass);
4093 checkGLcall("glStencilOp(...)");
4097 case WINED3DRS_CCW_STENCILFUNC :
4100 GLint ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
4101 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
4104 switch ((D3DCMPFUNC)Value) {
4105 case D3DCMP_NEVER: func = GL_NEVER; break;
4106 case D3DCMP_LESS: func = GL_LESS; break;
4107 case D3DCMP_EQUAL: func = GL_EQUAL; break;
4108 case D3DCMP_LESSEQUAL: func = GL_LEQUAL; break;
4109 case D3DCMP_GREATER: func = GL_GREATER; break;
4110 case D3DCMP_NOTEQUAL: func = GL_NOTEQUAL; break;
4111 case D3DCMP_GREATEREQUAL: func = GL_GEQUAL; break;
4112 case D3DCMP_ALWAYS: func = GL_ALWAYS; break;
4114 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
4116 This->stencilfunc = func;
4117 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
4118 #if 0 /* Don't use OpenGL 2.0 calls for now */
4119 if(GL_EXTCALL(glStencilFuncSeparate)) {
4120 GL_EXTCALL(glStencilFuncSeparate(GL_BACK, func, ref, mask));
4121 checkGLcall("glStencilFuncSeparate(GL_BACK,...)");
4125 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
4126 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
4127 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
4128 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
4129 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
4130 glStencilFunc(func, ref, mask);
4131 checkGLcall("glStencilFunc(...)");
4133 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
4134 GL_EXTCALL(glStencilFuncSeparateATI(GL_BACK, func, ref, mask));
4135 checkGLcall("glStencilFuncSeparateATI(GL_BACK,...)");
4137 TRACE("Separate stencil function not supported on this version of opengl");
4138 glStencilFunc(func, ref, mask);
4139 checkGLcall("glStencilFunc(...)");
4142 glStencilFunc(func, ref, mask);
4143 checkGLcall("glStencilFunc(...)");
4147 case WINED3DRS_DEPTHBIAS :
4151 glEnable(GL_POLYGON_OFFSET_FILL);
4152 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4153 glPolygonOffset(*((float*)&This->stateBlock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS]), tmpvalue.f);
4154 checkGLcall("glPolygonOffset(...)");
4156 glDisable(GL_POLYGON_OFFSET_FILL);
4157 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4162 case WINED3DRS_TEXTUREPERSPECTIVE :
4165 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
4167 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
4171 case WINED3DRS_STIPPLEDALPHA :
4174 ERR(" Stippled Alpha not supported yet.\n");
4177 case WINED3DRS_ANTIALIAS :
4180 ERR(" Antialias not supported yet.\n");
4184 FIXME("(%p)->(%s,%ld) not handled yet\n", This, debug_d3drenderstate(State), Value);
4192 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
4193 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4194 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
4195 *pValue = This->stateBlock->renderState[State];
4200 * Get / Set Sampler States
4201 * TODO: Verify against dx9 definitions
4204 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
4205 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4207 * SetSampler is designed to allow for more than the standard up to 8 textures
4208 * and Geforce has stopped supporting more than 6 standard textures in openGL.
4209 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
4211 * http://developer.nvidia.com/object/General_FAQ.html#t6
4213 * There are two new settings for GForce
4215 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
4216 * and the texture one:
4217 * GL_MAX_TEXTURE_COORDS_ARB.
4218 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
4220 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
4221 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
4223 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
4224 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE, Sampler, Type);
4225 return WINED3DERR_INVALIDCALL;
4227 TRACE("Setting sampler %ld %d to %ld\n", Sampler, Type, Value);
4228 This->updateStateBlock->samplerState[Sampler][Type] = Value;
4229 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
4230 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
4232 /* Handle recording of state blocks */
4233 if (This->isRecordingState) {
4234 TRACE("Recording... not performing anything\n");
4241 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
4242 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4243 /** TODO: check that sampler is in range **/
4244 *Value = This->updateStateBlock->samplerState[Sampler][Type];
4245 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
4250 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
4251 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4254 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4255 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4256 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
4262 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
4263 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4264 GLint scissorBox[4];
4267 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4268 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
4269 pRect->left = scissorBox[1];
4270 pRect->top = scissorBox[2];
4271 pRect->right = scissorBox[1] + scissorBox[3];
4272 pRect->bottom = scissorBox[2] + scissorBox[4];
4273 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4278 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
4279 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4280 IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
4282 TRACE("(%p) : pDecl=%p\n", This, pDecl);
4284 This->updateStateBlock->vertexDecl = pDecl;
4285 This->updateStateBlock->changed.vertexDecl = TRUE;
4286 This->updateStateBlock->set.vertexDecl = TRUE;
4288 if (This->isRecordingState) {
4289 TRACE("Recording... not performing anything\n");
4292 if (NULL != pDecl) {
4293 IWineD3DVertexDeclaration_AddRef(pDecl);
4295 if (NULL != oldDecl) {
4296 IWineD3DVertexDeclaration_Release(oldDecl);
4301 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
4302 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4304 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
4306 *ppDecl = This->stateBlock->vertexDecl;
4307 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
4311 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
4312 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4313 IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
4315 This->updateStateBlock->vertexShader = pShader;
4316 This->updateStateBlock->changed.vertexShader = TRUE;
4317 This->updateStateBlock->set.vertexShader = TRUE;
4319 if (This->isRecordingState) {
4320 TRACE("Recording... not performing anything\n");
4323 if (NULL != pShader) {
4324 IWineD3DVertexShader_AddRef(pShader);
4326 if (NULL != oldShader) {
4327 IWineD3DVertexShader_Release(oldShader);
4330 if (pShader != NULL && ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration != NULL) {
4331 TRACE("(%p) : setting vertexDeclaration(%p)\n", This, ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration);
4332 IWineD3DDevice_SetVertexDeclaration(iface, ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration);
4335 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4337 * TODO: merge HAL shaders context switching from prototype
4342 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
4343 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4345 if (NULL == ppShader) {
4346 return WINED3DERR_INVALIDCALL;
4348 *ppShader = This->stateBlock->vertexShader;
4349 if( NULL != *ppShader)
4350 IWineD3DVertexShader_AddRef(*ppShader);
4352 TRACE("(%p) : returning %p\n", This, *ppShader);
4356 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4357 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4360 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4362 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4363 iface, dstData, srcData, type, start, count, registersize);
4365 if (type != WINESHADERCNST_NONE) {
4366 if (srcData == NULL || cnt < 0) {
4367 return WINED3DERR_INVALIDCALL;
4370 CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
4373 for (i = start; i < cnt + start; ++i) {
4374 This->updateStateBlock->changed.vertexShaderConstants[i] = TRUE;
4375 This->updateStateBlock->set.vertexShaderConstants[i] = TRUE;
4376 This->updateStateBlock->vertexShaderConstantT[i] = type;
4382 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4383 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4386 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4388 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4389 iface, dstData, srcData, type, start, count, registersize);
4391 /* Verify that the requested shader constant was populated with the correct type */
4392 for (i = start; i < cnt + start; ++i) {
4393 if (This->updateStateBlock->vertexShaderConstantT[i] != type) {
4394 TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning WINED3DERR_INVALIDCALL\n",
4395 This, type, This->updateStateBlock->vertexShaderConstantT[i]);
4396 return WINED3DERR_INVALIDCALL;
4400 if (dstData == NULL || cnt < 0) {
4401 return WINED3DERR_INVALIDCALL;
4404 CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
4409 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
4410 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4412 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4413 This->updateStateBlock->vertexShaderConstantB,
4415 WINESHADERCNST_BOOL,
4418 sizeof(*pConstantData));
4421 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
4422 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4424 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4426 This->updateStateBlock->vertexShaderConstantB,
4427 WINESHADERCNST_BOOL,
4430 sizeof(*pConstantData));
4433 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
4434 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4436 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4437 This->updateStateBlock->vertexShaderConstantI,
4439 WINESHADERCNST_INTEGER,
4442 4 * sizeof(*pConstantData));
4445 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
4446 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4448 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4450 This->updateStateBlock->vertexShaderConstantI,
4451 WINESHADERCNST_INTEGER,
4454 4 * sizeof(*pConstantData));
4458 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
4459 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4461 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4462 This->updateStateBlock->vertexShaderConstantF,
4464 WINESHADERCNST_FLOAT,
4467 4 * sizeof(*pConstantData));
4470 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
4471 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4473 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4475 This->updateStateBlock->vertexShaderConstantF,
4476 WINESHADERCNST_FLOAT,
4479 4 * sizeof(*pConstantData));
4482 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
4483 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4486 WINESHADERCNST_NONE,
4492 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
4493 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4494 IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader;
4495 This->updateStateBlock->pixelShader = pShader;
4496 This->updateStateBlock->changed.pixelShader = TRUE;
4497 This->updateStateBlock->set.pixelShader = TRUE;
4499 /* Handle recording of state blocks */
4500 if (This->isRecordingState) {
4501 TRACE("Recording... not performing anything\n");
4504 if (NULL != pShader) {
4505 IWineD3DPixelShader_AddRef(pShader);
4507 if (NULL != oldShader) {
4508 IWineD3DPixelShader_Release(oldShader);
4511 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4513 * TODO: merge HAL shaders context switching from prototype
4518 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
4519 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4521 if (NULL == ppShader) {
4522 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
4523 return WINED3DERR_INVALIDCALL;
4526 *ppShader = This->stateBlock->pixelShader;
4527 if (NULL != *ppShader) {
4528 IWineD3DPixelShader_AddRef(*ppShader);
4530 TRACE("(%p) : returning %p\n", This, *ppShader);
4534 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4535 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4538 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4540 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4541 iface, dstData, srcData, type, start, count, registersize);
4543 if (type != WINESHADERCNST_NONE) {
4544 if (srcData == NULL || cnt < 0) {
4545 return WINED3DERR_INVALIDCALL;
4548 CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
4551 for (i = start; i < cnt + start; ++i) {
4552 This->updateStateBlock->changed.pixelShaderConstants[i] = TRUE;
4553 This->updateStateBlock->set.pixelShaderConstants[i] = TRUE;
4554 This->updateStateBlock->pixelShaderConstantT[i] = type;
4560 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4561 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4564 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4566 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4567 iface, dstData, srcData, type, start, count, registersize);
4569 /* Verify that the requested shader constant was populated with the correct type */
4570 for (i = start; i < cnt + start; ++i) {
4571 if (This->updateStateBlock->pixelShaderConstantT[i] != type) {
4572 TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning WINED3DERR_INVALIDCALL\n",
4573 This, type, This->updateStateBlock->pixelShaderConstantT[i]);
4574 return WINED3DERR_INVALIDCALL;
4578 if (dstData == NULL || cnt < 0) {
4579 return WINED3DERR_INVALIDCALL;
4582 CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
4587 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
4588 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4590 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4591 This->updateStateBlock->pixelShaderConstantB,
4593 WINESHADERCNST_BOOL,
4596 sizeof(*pConstantData));
4599 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
4600 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4602 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4604 This->updateStateBlock->pixelShaderConstantB,
4605 WINESHADERCNST_BOOL,
4608 sizeof(*pConstantData));
4611 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
4612 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4614 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4615 This->updateStateBlock->pixelShaderConstantI,
4617 WINESHADERCNST_INTEGER,
4620 4 * sizeof(*pConstantData));
4623 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
4624 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4626 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4628 This->updateStateBlock->pixelShaderConstantI,
4629 WINESHADERCNST_INTEGER,
4632 4 * sizeof(*pConstantData));
4635 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
4636 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4638 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4639 This->updateStateBlock->pixelShaderConstantF,
4641 WINESHADERCNST_FLOAT,
4644 4 * sizeof(*pConstantData));
4647 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
4648 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4650 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4652 This->updateStateBlock->pixelShaderConstantF,
4653 WINESHADERCNST_FLOAT,
4656 4 * sizeof(*pConstantData));
4659 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
4660 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4663 WINESHADERCNST_NONE,
4669 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
4671 process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, WineDirect3DVertexStridedData *lpStrideData, DWORD SrcFVF, IWineD3DVertexBufferImpl *dest, DWORD dwFlags) {
4674 DWORD DestFVF = dest->fvf;
4676 D3DMATRIX mat, proj_mat, view_mat, world_mat;
4680 if (SrcFVF & D3DFVF_NORMAL) {
4681 WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
4684 if ( (SrcFVF & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
4685 ERR("Source has no position mask\n");
4686 return WINED3DERR_INVALIDCALL;
4689 if (dest->resource.allocatedMemory == NULL) {
4690 ERR("Destination buffer has no memory allocated\n");
4691 return WINED3DERR_INVALIDCALL;
4695 * a) D3DRS_CLIPPING is enabled
4696 * b) WINED3DVOP_CLIP is passed
4698 if(This->stateBlock->renderState[WINED3DRS_CLIPPING]) {
4699 static BOOL warned = FALSE;
4701 * The clipping code is not quite correct. Some things need
4702 * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
4703 * so disable clipping for now.
4704 * (The graphics in Half-Life are broken, and my processvertices
4705 * test crashes with IDirect3DDevice3)
4711 FIXME("Clipping is broken and disabled for now\n");
4713 } else doClip = FALSE;
4714 dest_ptr = ((char *) dest->resource.allocatedMemory) + dwDestIndex * get_flexible_vertex_size(DestFVF);
4716 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
4719 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
4722 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
4723 D3DTS_WORLDMATRIX(0),
4726 TRACE("View mat: \n");
4727 TRACE("%f %f %f %f\n", view_mat.u.s._11, view_mat.u.s._12, view_mat.u.s._13, view_mat.u.s._14); \
4728 TRACE("%f %f %f %f\n", view_mat.u.s._21, view_mat.u.s._22, view_mat.u.s._23, view_mat.u.s._24); \
4729 TRACE("%f %f %f %f\n", view_mat.u.s._31, view_mat.u.s._32, view_mat.u.s._33, view_mat.u.s._34); \
4730 TRACE("%f %f %f %f\n", view_mat.u.s._41, view_mat.u.s._42, view_mat.u.s._43, view_mat.u.s._44); \
4732 TRACE("Proj mat: \n");
4733 TRACE("%f %f %f %f\n", proj_mat.u.s._11, proj_mat.u.s._12, proj_mat.u.s._13, proj_mat.u.s._14); \
4734 TRACE("%f %f %f %f\n", proj_mat.u.s._21, proj_mat.u.s._22, proj_mat.u.s._23, proj_mat.u.s._24); \
4735 TRACE("%f %f %f %f\n", proj_mat.u.s._31, proj_mat.u.s._32, proj_mat.u.s._33, proj_mat.u.s._34); \
4736 TRACE("%f %f %f %f\n", proj_mat.u.s._41, proj_mat.u.s._42, proj_mat.u.s._43, proj_mat.u.s._44); \
4738 TRACE("World mat: \n");
4739 TRACE("%f %f %f %f\n", world_mat.u.s._11, world_mat.u.s._12, world_mat.u.s._13, world_mat.u.s._14); \
4740 TRACE("%f %f %f %f\n", world_mat.u.s._21, world_mat.u.s._22, world_mat.u.s._23, world_mat.u.s._24); \
4741 TRACE("%f %f %f %f\n", world_mat.u.s._31, world_mat.u.s._32, world_mat.u.s._33, world_mat.u.s._34); \
4742 TRACE("%f %f %f %f\n", world_mat.u.s._41, world_mat.u.s._42, world_mat.u.s._43, world_mat.u.s._44); \
4744 /* Get the viewport */
4745 IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
4746 TRACE("Viewport: X=%ld, Y=%ld, Width=%ld, Height=%ld, MinZ=%f, MaxZ=%f\n",
4747 vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
4749 multiply_matrix(&mat,&view_mat,&world_mat);
4750 multiply_matrix(&mat,&proj_mat,&mat);
4752 numTextures = (DestFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
4754 for (i = 0; i < dwCount; i+= 1) {
4755 unsigned int tex_index;
4757 if ( ((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZ ) ||
4758 ((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW ) ) {
4759 /* The position first */
4761 (float *) (((char *) lpStrideData->u.s.position.lpData) + i * lpStrideData->u.s.position.dwStride);
4763 TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
4765 /* Multiplication with world, view and projection matrix */
4766 x = (p[0] * mat.u.s._11) + (p[1] * mat.u.s._21) + (p[2] * mat.u.s._31) + (1.0 * mat.u.s._41);
4767 y = (p[0] * mat.u.s._12) + (p[1] * mat.u.s._22) + (p[2] * mat.u.s._32) + (1.0 * mat.u.s._42);
4768 z = (p[0] * mat.u.s._13) + (p[1] * mat.u.s._23) + (p[2] * mat.u.s._33) + (1.0 * mat.u.s._43);
4769 rhw = (p[0] * mat.u.s._14) + (p[1] * mat.u.s._24) + (p[2] * mat.u.s._34) + (1.0 * mat.u.s._44);
4771 TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
4773 /* WARNING: The following things are taken from d3d7 and were not yet checked
4774 * against d3d8 or d3d9!
4777 /* Clipping conditions: From
4778 * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp
4780 * A vertex is clipped if it does not match the following requirements
4784 * 0 < rhw ( Not in d3d7, but tested in d3d7)
4786 * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
4787 * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
4791 if( doClip == FALSE ||
4792 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
4793 (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) &&
4796 /* "Normal" viewport transformation (not clipped)
4797 * 1) The values are divided trough rhw
4798 * 2) The y axis is negative, so multiply it with -1
4799 * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
4800 * -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
4801 * 4) Multiply x with Width/2 and add Width/2
4802 * 5) The same for the height
4803 * 6) Add the viewpoint X and Y to the 2D coordinates and
4804 * The minimum Z value to z
4805 * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
4807 * Well, basically it's simply a linear transformation into viewport
4819 z *= vp.MaxZ - vp.MinZ;
4821 x += vp.Width / 2 + vp.X;
4822 y += vp.Height / 2 + vp.Y;
4827 /* That vertex got clipped
4828 * Contrary to OpenGL it is not dropped completely, it just
4829 * undergoes a different calculation.
4831 TRACE("Vertex got clipped\n");
4838 /* Msdn mentiones that Direct3D9 keeps a list of clipped vertices
4839 * outside of the main vertex buffer memory. That needs some more
4844 TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
4847 ( (float *) dest_ptr)[0] = x;
4848 ( (float *) dest_ptr)[1] = y;
4849 ( (float *) dest_ptr)[2] = z;
4850 ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
4852 dest_ptr += 3 * sizeof(float);
4854 if((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
4855 dest_ptr += sizeof(float);
4858 if (DestFVF & D3DFVF_PSIZE) {
4859 dest_ptr += sizeof(DWORD);
4861 if (DestFVF & D3DFVF_NORMAL) {
4863 (float *) (((float *) lpStrideData->u.s.normal.lpData) + i * lpStrideData->u.s.normal.dwStride);
4864 /* AFAIK this should go into the lighting information */
4865 FIXME("Didn't expect the destination to have a normal\n");
4866 copy_and_next(dest_ptr, normal, 3 * sizeof(float));
4869 if (DestFVF & D3DFVF_DIFFUSE) {
4871 (DWORD *) (((char *) lpStrideData->u.s.diffuse.lpData) + i * lpStrideData->u.s.diffuse.dwStride);
4873 static BOOL warned = FALSE;
4875 if(warned == FALSE) {
4876 ERR("No diffuse color in source, but destination has one\n");
4880 *( (DWORD *) dest_ptr) = 0xffffffff;
4881 dest_ptr += sizeof(DWORD);
4884 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
4887 if (DestFVF & D3DFVF_SPECULAR) {
4888 /* What's the color value in the feedback buffer? */
4890 (DWORD *) (((char *) lpStrideData->u.s.specular.lpData) + i * lpStrideData->u.s.specular.dwStride);
4892 static BOOL warned = FALSE;
4894 if(warned == FALSE) {
4895 ERR("No specular color in source, but destination has one\n");
4899 *( (DWORD *) dest_ptr) = 0xFF000000;
4900 dest_ptr += sizeof(DWORD);
4903 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
4907 for (tex_index = 0; tex_index < numTextures; tex_index++) {
4909 (float *) (((char *) lpStrideData->u.s.texCoords[tex_index].lpData) +
4910 i * lpStrideData->u.s.texCoords[tex_index].dwStride);
4912 ERR("No source texture, but destination requests one\n");
4913 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
4916 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
4923 #undef copy_and_next
4925 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
4926 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4927 IWineD3DVertexBufferImpl *SrcImpl = (IWineD3DVertexBufferImpl *) pVertexDecl;
4928 WineDirect3DVertexStridedData strided;
4930 TRACE("(%p)->(%d,%d,%d,%p,%p,%ld\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
4932 hr = IWineD3DDevice_SetFVF(iface, SrcImpl->fvf);
4933 hr = IWineD3DDevice_SetStreamSource(iface, 0, pVertexDecl, get_flexible_vertex_size(SrcImpl->fvf) * SrcStartIndex, get_flexible_vertex_size(SrcImpl->fvf));
4935 memset(&strided, 0, sizeof(strided));
4936 primitiveConvertToStridedData(iface, &strided, 0);
4938 return process_vertices_strided(This, DestIndex, VertexCount, &strided, SrcImpl->fvf, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags);
4942 * Apply / Get / Set Texture Stage States
4943 * TODO: Verify against dx9 definitions
4946 /* 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 */
4947 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
4948 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4949 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
4950 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4952 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4954 /* Check that the stage is within limits */
4955 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4956 TRACE("Attempt to access invalid texture rejected\n");
4963 case WINED3DTSS_ALPHAOP :
4964 case WINED3DTSS_COLOROP :
4965 /* nothing to do as moved to drawprim for now */
4967 case WINED3DTSS_ADDRESSW :
4968 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
4969 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
4970 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
4973 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
4974 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
4975 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
4976 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
4979 case WINED3DTSS_TEXCOORDINDEX :
4981 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
4983 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
4984 one flag, you can still specify an index value, which the system uses to
4985 determine the texture wrapping mode.
4986 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
4987 means use the vertex position (camera-space) as the input texture coordinates
4988 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
4989 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
4990 to the TEXCOORDINDEX value */
4993 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
4995 switch (Value & 0xFFFF0000) {
4996 case D3DTSS_TCI_PASSTHRU:
4997 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
4998 glDisable(GL_TEXTURE_GEN_S);
4999 glDisable(GL_TEXTURE_GEN_T);
5000 glDisable(GL_TEXTURE_GEN_R);
5001 glDisable(GL_TEXTURE_GEN_Q);
5002 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
5005 case D3DTSS_TCI_CAMERASPACEPOSITION:
5006 /* CameraSpacePosition means use the vertex position, transformed to camera space,
5007 as the input texture coordinates for this stage's texture transformation. This
5008 equates roughly to EYE_LINEAR */
5010 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5011 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5012 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5013 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5014 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
5016 glMatrixMode(GL_MODELVIEW);
5019 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5020 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5021 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5022 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5025 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
5026 glEnable(GL_TEXTURE_GEN_S);
5027 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5028 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5029 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5030 glEnable(GL_TEXTURE_GEN_T);
5031 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5032 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5033 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5034 glEnable(GL_TEXTURE_GEN_R);
5035 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5036 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5037 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5041 case D3DTSS_TCI_CAMERASPACENORMAL:
5043 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5044 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5045 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5046 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5047 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5048 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
5050 glMatrixMode(GL_MODELVIEW);
5053 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5054 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5055 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5056 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5059 glEnable(GL_TEXTURE_GEN_S);
5060 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5061 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5062 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5063 glEnable(GL_TEXTURE_GEN_T);
5064 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5065 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5066 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5067 glEnable(GL_TEXTURE_GEN_R);
5068 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5069 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5070 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5075 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
5077 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5078 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5079 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5080 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5081 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5082 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
5084 glMatrixMode(GL_MODELVIEW);
5087 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5088 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5089 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5090 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5093 glEnable(GL_TEXTURE_GEN_S);
5094 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5095 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5096 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5097 glEnable(GL_TEXTURE_GEN_T);
5098 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5099 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5100 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5101 glEnable(GL_TEXTURE_GEN_R);
5102 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5103 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5104 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5109 /* Unhandled types: */
5112 /* ? disable GL_TEXTURE_GEN_n ? */
5113 glDisable(GL_TEXTURE_GEN_S);
5114 glDisable(GL_TEXTURE_GEN_T);
5115 glDisable(GL_TEXTURE_GEN_R);
5116 glDisable(GL_TEXTURE_GEN_Q);
5117 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
5124 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
5125 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);
5128 case WINED3DTSS_BUMPENVMAT00 :
5129 case WINED3DTSS_BUMPENVMAT01 :
5130 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
5132 case WINED3DTSS_BUMPENVMAT10 :
5133 case WINED3DTSS_BUMPENVMAT11 :
5134 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
5137 case WINED3DTSS_BUMPENVLSCALE :
5138 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5141 case WINED3DTSS_BUMPENVLOFFSET :
5142 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5145 case WINED3DTSS_RESULTARG :
5146 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5150 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
5151 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5160 * Get / Set Texture Stage States
5161 * TODO: Verify against dx9 definitions
5163 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
5164 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5166 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5168 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
5170 /* Reject invalid texture units */
5171 if (Stage >= GL_LIMITS(textures)) {
5172 TRACE("Attempt to access invalid texture rejected\n");
5173 return WINED3DERR_INVALIDCALL;
5176 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
5177 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
5178 This->updateStateBlock->textureState[Stage][Type] = Value;
5183 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
5184 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5185 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
5186 *pValue = This->updateStateBlock->textureState[Stage][Type];
5193 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
5195 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5196 IWineD3DBaseTexture *oldTexture;
5198 oldTexture = This->updateStateBlock->textures[Stage];
5199 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
5201 #if 0 /* TODO: check so vertex textures */
5202 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
5203 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
5208 /* Reject invalid texture units */
5209 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
5210 WARN("Attempt to access invalid texture rejected\n");
5211 return WINED3DERR_INVALIDCALL;
5214 if(pTexture != NULL) {
5215 /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH;
5217 if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH) {
5218 WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
5219 return WINED3DERR_INVALIDCALL;
5223 oldTexture = This->updateStateBlock->textures[Stage];
5224 TRACE("GL_LIMITS %d\n",GL_LIMITS(textures));
5225 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
5227 This->updateStateBlock->set.textures[Stage] = TRUE;
5228 This->updateStateBlock->changed.textures[Stage] = TRUE;
5229 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
5230 This->updateStateBlock->textures[Stage] = pTexture;
5232 /* Handle recording of state blocks */
5233 if (This->isRecordingState) {
5234 TRACE("Recording... not performing anything\n");
5238 /** NOTE: MSDN says that setTexture increases the reference count,
5239 * and the the application nust set the texture back to null (or have a leaky application),
5240 * This means we should pass the refcount up to the parent
5241 *******************************/
5242 if (NULL != This->updateStateBlock->textures[Stage]) {
5243 IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
5246 if (NULL != oldTexture) {
5247 IWineD3DBaseTexture_Release(oldTexture);
5250 /* Reset color keying */
5251 if(Stage == 0 && This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE]) {
5252 BOOL enable_ckey = FALSE;
5255 IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)pTexture)->surfaces[0];
5256 if(surf->CKeyFlags & DDSD_CKSRCBLT) enable_ckey = TRUE;
5260 glAlphaFunc(GL_NOTEQUAL, 0.0);
5261 checkGLcall("glAlphaFunc");
5268 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
5269 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5270 TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
5272 /* Reject invalid texture units */
5273 if (Stage >= GL_LIMITS(textures)) {
5274 TRACE("Attempt to access invalid texture rejected\n");
5275 return WINED3DERR_INVALIDCALL;
5277 *ppTexture=This->updateStateBlock->textures[Stage];
5279 IWineD3DBaseTexture_AddRef(*ppTexture);
5281 return WINED3DERR_INVALIDCALL;
5288 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
5289 IWineD3DSurface **ppBackBuffer) {
5290 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5291 IWineD3DSwapChain *swapChain;
5294 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
5296 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
5297 if (hr == WINED3D_OK) {
5298 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
5299 IWineD3DSwapChain_Release(swapChain);
5301 *ppBackBuffer = NULL;
5306 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
5307 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5308 WARN("(%p) : stub, calling idirect3d for now\n", This);
5309 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
5312 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
5313 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5314 IWineD3DSwapChain *swapChain;
5317 if(iSwapChain > 0) {
5318 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5319 if (hr == WINED3D_OK) {
5320 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
5321 IWineD3DSwapChain_Release(swapChain);
5323 FIXME("(%p) Error getting display mode\n", This);
5326 /* Don't read the real display mode,
5327 but return the stored mode instead. X11 can't change the color
5328 depth, and some apps are pretty angry if they SetDisplayMode from
5329 24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
5331 Also don't relay to the swapchain because with ddraw it's possible
5332 that there isn't a swapchain at all */
5333 pMode->Width = This->ddraw_width;
5334 pMode->Height = This->ddraw_height;
5335 pMode->Format = This->ddraw_format;
5336 pMode->RefreshRate = 0;
5343 HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
5344 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5345 TRACE("(%p)->(%p)\n", This, hWnd);
5347 This->ddraw_window = hWnd;
5351 HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
5352 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5353 TRACE("(%p)->(%p)\n", This, hWnd);
5355 *hWnd = This->ddraw_window;
5360 * Stateblock related functions
5363 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
5364 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5365 IWineD3DStateBlockImpl *object;
5366 TRACE("(%p)", This);
5368 if (This->isRecordingState) {
5369 return WINED3DERR_INVALIDCALL;
5372 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
5373 if (NULL == object ) {
5374 FIXME("(%p)Error allocating memory for stateblock\n", This);
5375 return E_OUTOFMEMORY;
5377 TRACE("(%p) creted object %p\n", This, object);
5378 object->wineD3DDevice= This;
5379 /** FIXME: object->parent = parent; **/
5380 object->parent = NULL;
5381 object->blockType = WINED3DSBT_ALL;
5383 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
5385 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
5386 This->updateStateBlock = object;
5387 This->isRecordingState = TRUE;
5389 TRACE("(%p) recording stateblock %p\n",This , object);
5393 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
5394 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5396 if (!This->isRecordingState) {
5397 FIXME("(%p) not recording! returning error\n", This);
5398 *ppStateBlock = NULL;
5399 return WINED3DERR_INVALIDCALL;
5402 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
5403 This->isRecordingState = FALSE;
5404 This->updateStateBlock = This->stateBlock;
5405 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
5406 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
5407 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
5412 * Scene related functions
5414 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
5415 /* At the moment we have no need for any functionality at the beginning
5417 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5418 TRACE("(%p) : stub\n", This);
5422 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
5423 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5424 TRACE("(%p)\n", This);
5426 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
5428 checkGLcall("glFlush");
5430 TRACE("End Scene\n");
5431 if(This->renderTarget != NULL) {
5433 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
5434 IUnknown *targetContainer = NULL;
5435 if (WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
5436 || WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
5437 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
5438 /** always dirtify for now. we must find a better way to see that surface have been modified
5439 (Modifications should will only occur via draw-primitive, but we do need better locking
5440 switching to render-to-texture should remove the overhead though.
5442 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
5443 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
5444 IWineD3DSurface_PreLoad(This->renderTarget);
5445 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
5446 IUnknown_Release(targetContainer);
5449 This->sceneEnded = TRUE;
5454 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
5455 CONST RECT* pSourceRect, CONST RECT* pDestRect,
5456 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
5457 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5458 IWineD3DSwapChain *swapChain = NULL;
5460 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
5462 TRACE("(%p) Presenting the frame\n", This);
5464 for(i = 0 ; i < swapchains ; i ++) {
5466 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
5467 TRACE("presentinng chain %d, %p\n", i, swapChain);
5468 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
5469 IWineD3DSwapChain_Release(swapChain);
5475 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
5476 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
5477 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5479 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
5480 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
5481 when the depth-buffer format does not contain stencil buffer information, this method fails. */
5482 GLbitfield glMask = 0;
5483 GLboolean old_ztest;
5484 GLfloat old_z_clear_value;
5485 GLint old_stencil_clear_value;
5486 GLfloat old_color_clear_value[4];
5488 CONST D3DRECT* curRect;
5490 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
5491 Count, pRects, Flags, Z, Stencil);
5495 glEnable(GL_SCISSOR_TEST);
5496 checkGLcall("glEnable GL_SCISSOR_TEST");
5498 if (Count > 0 && pRects) {
5504 /* Only set the values up once, as they are not changing */
5505 if (Flags & D3DCLEAR_STENCIL) {
5506 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
5507 glClearStencil(Stencil);
5508 checkGLcall("glClearStencil");
5509 glMask = glMask | GL_STENCIL_BUFFER_BIT;
5510 glStencilMask(0xFFFFFFFF);
5513 if (Flags & D3DCLEAR_ZBUFFER) {
5514 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
5515 glDepthMask(GL_TRUE);
5516 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
5518 checkGLcall("glClearDepth");
5519 glMask = glMask | GL_DEPTH_BUFFER_BIT;
5522 if (Flags & D3DCLEAR_TARGET) {
5523 TRACE("Clearing screen with glClear to color %lx\n", Color);
5524 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
5525 glClearColor(D3DCOLOR_R(Color),
5529 checkGLcall("glClearColor");
5531 /* Clear ALL colors! */
5532 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5533 glMask = glMask | GL_COLOR_BUFFER_BIT;
5536 /* Now process each rect in turn */
5537 for (i = 0; i < Count || i == 0; i++) {
5540 /* Note gl uses lower left, width/height */
5541 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
5542 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
5543 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
5544 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
5545 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
5546 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
5547 checkGLcall("glScissor");
5549 glScissor(This->stateBlock->viewport.X,
5550 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
5551 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
5552 This->stateBlock->viewport.Width,
5553 This->stateBlock->viewport.Height);
5554 checkGLcall("glScissor");
5557 /* Clear the selected rectangle (or full screen) */
5559 checkGLcall("glClear");
5561 /* Step to the next rectangle */
5562 if (curRect) curRect = curRect + sizeof(D3DRECT);
5565 /* Restore the old values (why..?) */
5566 if (Flags & D3DCLEAR_STENCIL) {
5567 glClearStencil(old_stencil_clear_value);
5568 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
5570 if (Flags & D3DCLEAR_ZBUFFER) {
5571 glDepthMask(old_ztest);
5572 glClearDepth(old_z_clear_value);
5574 if (Flags & D3DCLEAR_TARGET) {
5575 glClearColor(old_color_clear_value[0],
5576 old_color_clear_value[1],
5577 old_color_clear_value[2],
5578 old_color_clear_value[3]);
5579 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
5580 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
5581 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
5582 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
5585 glDisable(GL_SCISSOR_TEST);
5586 checkGLcall("glDisable");
5595 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
5596 UINT PrimitiveCount) {
5598 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5599 This->stateBlock->streamIsUP = FALSE;
5601 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
5602 debug_d3dprimitivetype(PrimitiveType),
5603 StartVertex, PrimitiveCount);
5604 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
5605 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */, NULL);
5611 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
5612 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
5613 D3DPRIMITIVETYPE PrimitiveType,
5614 INT baseVIndex, UINT minIndex,
5615 UINT NumVertices, UINT startIndex, UINT primCount) {
5617 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5619 IWineD3DIndexBuffer *pIB;
5620 WINED3DINDEXBUFFER_DESC IdxBufDsc;
5622 pIB = This->stateBlock->pIndexData;
5623 This->stateBlock->streamIsUP = FALSE;
5625 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
5626 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5627 minIndex, NumVertices, startIndex, baseVIndex, primCount);
5629 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
5630 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
5636 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
5637 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex, NULL);
5642 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
5643 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
5644 UINT VertexStreamZeroStride) {
5645 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5647 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
5648 debug_d3dprimitivetype(PrimitiveType),
5649 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
5651 /* release the stream source */
5652 if (This->stateBlock->streamSource[0] != NULL) {
5653 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5656 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5657 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5658 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5659 This->stateBlock->streamIsUP = TRUE;
5661 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
5662 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */, NULL);
5664 /* MSDN specifies stream zero settings must be set to NULL */
5665 This->stateBlock->streamStride[0] = 0;
5666 This->stateBlock->streamSource[0] = NULL;
5668 /*stream zero settings set to null at end, as per the msdn */
5672 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
5673 UINT MinVertexIndex, UINT NumVertices,
5674 UINT PrimitiveCount, CONST void* pIndexData,
5675 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
5676 UINT VertexStreamZeroStride) {
5678 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5680 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
5681 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5682 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
5683 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
5685 if (IndexDataFormat == WINED3DFMT_INDEX16) {
5691 /* release the stream and index data */
5692 if (This->stateBlock->streamSource[0] != NULL) {
5693 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5695 if (This->stateBlock->pIndexData) {
5696 IWineD3DIndexBuffer_Release(This->stateBlock->pIndexData);
5699 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5700 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5701 This->stateBlock->streamIsUP = TRUE;
5702 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5704 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex, NULL);
5706 /* MSDN specifies stream zero settings and index buffer must be set to NULL */
5707 This->stateBlock->streamSource[0] = NULL;
5708 This->stateBlock->streamStride[0] = 0;
5709 This->stateBlock->pIndexData = NULL;
5714 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
5716 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0, DrawPrimStrideData);
5719 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
5720 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
5721 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5722 HRESULT hr = WINED3D_OK;
5723 WINED3DRESOURCETYPE sourceType;
5724 WINED3DRESOURCETYPE destinationType;
5727 /* TODO: think about moving the code into IWineD3DBaseTexture */
5729 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
5731 /* verify that the source and destination textures aren't NULL */
5732 if (NULL == pSourceTexture || NULL == pDestinationTexture) {
5733 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
5734 This, pSourceTexture, pDestinationTexture);
5735 hr = WINED3DERR_INVALIDCALL;
5738 if (pSourceTexture == pDestinationTexture) {
5739 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
5740 This, pSourceTexture, pDestinationTexture);
5741 hr = WINED3DERR_INVALIDCALL;
5743 /* Verify that the source and destination textures are the same type */
5744 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
5745 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
5747 if (sourceType != destinationType) {
5748 WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
5750 hr = WINED3DERR_INVALIDCALL;
5753 /* check that both textures have the identical numbers of levels */
5754 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
5755 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
5756 hr = WINED3DERR_INVALIDCALL;
5759 if (WINED3D_OK == hr) {
5761 /* Make sure that the destination texture is loaded */
5762 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
5764 /* Update every surface level of the texture */
5765 levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
5767 switch (sourceType) {
5768 case WINED3DRTYPE_TEXTURE:
5770 IWineD3DSurface *srcSurface;
5771 IWineD3DSurface *destSurface;
5773 for (i = 0 ; i < levels ; ++i) {
5774 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture, i, &srcSurface);
5775 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
5776 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5777 IWineD3DSurface_Release(srcSurface);
5778 IWineD3DSurface_Release(destSurface);
5779 if (WINED3D_OK != hr) {
5780 WARN("(%p) : Call to update surface failed\n", This);
5786 case WINED3DRTYPE_CUBETEXTURE:
5788 IWineD3DSurface *srcSurface;
5789 IWineD3DSurface *destSurface;
5790 WINED3DCUBEMAP_FACES faceType;
5792 for (i = 0 ; i < levels ; ++i) {
5793 /* Update each cube face */
5794 for (faceType = D3DCUBEMAP_FACE_POSITIVE_X; faceType <= D3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
5795 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture, faceType, i, &srcSurface);
5796 if (WINED3D_OK != hr) {
5797 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5799 TRACE("Got srcSurface %p\n", srcSurface);
5801 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
5802 if (WINED3D_OK != hr) {
5803 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5805 TRACE("Got desrSurface %p\n", destSurface);
5807 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5808 IWineD3DSurface_Release(srcSurface);
5809 IWineD3DSurface_Release(destSurface);
5810 if (WINED3D_OK != hr) {
5811 WARN("(%p) : Call to update surface failed\n", This);
5818 #if 0 /* TODO: Add support for volume textures */
5819 case WINED3DRTYPE_VOLUMETEXTURE:
5821 IWineD3DVolume srcVolume = NULL;
5822 IWineD3DSurface destVolume = NULL;
5824 for (i = 0 ; i < levels ; ++i) {
5825 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture, i, &srcVolume);
5826 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
5827 hr = IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
5828 IWineD3DVolume_Release(srcSurface);
5829 IWineD3DVolume_Release(destSurface);
5830 if (WINED3D_OK != hr) {
5831 WARN("(%p) : Call to update volume failed\n", This);
5839 FIXME("(%p) : Unsupported source and destination type\n", This);
5840 hr = WINED3DERR_INVALIDCALL;
5847 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
5848 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
5849 CONST RECT* pDestRect, WINED3DTEXTUREFILTERTYPE Filter) {
5850 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5852 TRACE("(%p) : stub\n", This);
5855 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
5856 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5857 /** TODO: remove remove casts to IWineD3DSurfaceImpl *
5858 * NOTE It may be best to move the code into surface to occomplish this
5859 ****************************************/
5861 WINED3DSURFACE_DESC surfaceDesc;
5862 unsigned int surfaceWidth, surfaceHeight;
5863 glDescriptor *targetGlDescription = NULL;
5864 glDescriptor *surfaceGlDescription = NULL;
5865 IWineD3DSwapChainImpl *container = NULL;
5867 IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
5868 IWineD3DSurface_GetGlDesc(pSurface, &surfaceGlDescription);
5869 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5871 surfaceDesc.Width = &surfaceWidth;
5872 surfaceDesc.Height = &surfaceHeight;
5873 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5874 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
5876 /* Ok, I may need to setup some kind of active swapchain reference on the device */
5877 IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
5879 /* TODO: opengl Context switching for swapchains etc... */
5880 if (NULL != container || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
5881 if (NULL != container && (pRenderTarget == container->backBuffer)) {
5882 glReadBuffer(GL_BACK);
5883 vcheckGLcall("glReadBuffer(GL_BACK)");
5884 } else if ((NULL != container && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
5885 glReadBuffer(GL_FRONT);
5886 vcheckGLcall("glReadBuffer(GL_FRONT)");
5887 } else if (pRenderTarget == This->depthStencilBuffer) {
5888 FIXME("Reading of depthstencil not yet supported\n");
5891 glReadPixels(surfaceGlDescription->target,
5892 surfaceGlDescription->level,
5895 surfaceGlDescription->glFormat,
5896 surfaceGlDescription->glType,
5897 (void *)IWineD3DSurface_GetData(pSurface));
5898 vcheckGLcall("glReadPixels(...)");
5899 if(NULL != container ){
5900 IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
5903 IWineD3DBaseTexture *container;
5904 GLenum textureDimensions = GL_TEXTURE_2D;
5906 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
5907 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
5908 IWineD3DBaseTexture_Release(container);
5910 /* TODO: 2D -> Cube surface coppies etc.. */
5911 if (surfaceGlDescription->target != textureDimensions) {
5912 FIXME("(%p) : Texture dimension mismatch\n", This);
5914 glEnable(textureDimensions);
5915 vcheckGLcall("glEnable(GL_TEXTURE_...)");
5916 /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
5917 glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
5918 vcheckGLcall("glBindTexture");
5919 glGetTexImage(surfaceGlDescription->target,
5920 surfaceGlDescription->level,
5921 surfaceGlDescription->glFormat,
5922 surfaceGlDescription->glType,
5923 (void *)IWineD3DSurface_GetData(pSurface));
5924 glDisable(textureDimensions);
5925 vcheckGLcall("glDisable(GL_TEXTURE_...)");
5932 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
5933 IWineD3DSwapChain *swapChain;
5935 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5936 if(hr == WINED3D_OK) {
5937 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
5938 IWineD3DSwapChain_Release(swapChain);
5943 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5944 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5945 /* return a sensible default */
5947 /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
5948 FIXME("(%p) : stub\n", This);
5952 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5953 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5955 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5956 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5957 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5958 return WINED3DERR_INVALIDCALL;
5960 for (j = 0; j < 256; ++j) {
5961 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
5962 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5963 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
5964 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5966 TRACE("(%p) : returning\n", This);
5970 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5971 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5973 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5974 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5975 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5976 return WINED3DERR_INVALIDCALL;
5978 for (j = 0; j < 256; ++j) {
5979 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
5980 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5981 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
5982 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5984 TRACE("(%p) : returning\n", This);
5988 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5989 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5990 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5991 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5992 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5993 return WINED3DERR_INVALIDCALL;
5995 /*TODO: stateblocks */
5996 This->currentPalette = PaletteNumber;
5997 TRACE("(%p) : returning\n", This);
6001 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
6002 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6003 if (PaletteNumber == NULL) {
6004 WARN("(%p) : returning Invalid Call\n", This);
6005 return WINED3DERR_INVALIDCALL;
6007 /*TODO: stateblocks */
6008 *PaletteNumber = This->currentPalette;
6009 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
6013 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
6014 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6015 static BOOL showFixmes = TRUE;
6017 FIXME("(%p) : stub\n", This);
6021 This->softwareVertexProcessing = bSoftware;
6026 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
6027 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6028 static BOOL showFixmes = TRUE;
6030 FIXME("(%p) : stub\n", This);
6033 return This->softwareVertexProcessing;
6037 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
6038 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6039 IWineD3DSwapChain *swapChain;
6042 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
6044 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
6045 if(hr == WINED3D_OK){
6046 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
6047 IWineD3DSwapChain_Release(swapChain);
6049 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
6055 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
6056 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6057 static BOOL showfixmes = TRUE;
6058 if(nSegments != 0.0f) {
6060 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
6067 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
6068 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6069 static BOOL showfixmes = TRUE;
6071 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
6077 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
6078 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6079 /** TODO: remove casts to IWineD3DSurfaceImpl
6080 * NOTE: move code to surface to accomplish this
6081 ****************************************/
6082 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
6083 int srcWidth, srcHeight;
6084 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
6085 WINED3DFORMAT destFormat, srcFormat;
6087 int destLeft, destTop;
6088 WINED3DPOOL srcPool, destPool;
6090 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
6091 glDescriptor *glDescription = NULL;
6092 GLenum textureDimensions = GL_TEXTURE_2D;
6093 IWineD3DBaseTexture *baseTexture;
6095 WINED3DSURFACE_DESC winedesc;
6097 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
6098 memset(&winedesc, 0, sizeof(winedesc));
6099 winedesc.Width = &srcSurfaceWidth;
6100 winedesc.Height = &srcSurfaceHeight;
6101 winedesc.Pool = &srcPool;
6102 winedesc.Format = &srcFormat;
6104 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
6106 winedesc.Width = &destSurfaceWidth;
6107 winedesc.Height = &destSurfaceHeight;
6108 winedesc.Pool = &destPool;
6109 winedesc.Format = &destFormat;
6110 winedesc.Size = &destSize;
6112 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6114 if(srcPool != WINED3DPOOL_SYSTEMMEM || destPool != WINED3DPOOL_DEFAULT){
6115 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
6116 return WINED3DERR_INVALIDCALL;
6119 if (destFormat == WINED3DFMT_UNKNOWN) {
6120 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
6121 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
6123 /* Get the update surface description */
6124 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6127 /* Make sure the surface is loaded and up to date */
6128 IWineD3DSurface_PreLoad(pDestinationSurface);
6130 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
6134 /* this needs to be done in lines if the sourceRect != the sourceWidth */
6135 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
6136 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
6137 destLeft = pDestPoint ? pDestPoint->x : 0;
6138 destTop = pDestPoint ? pDestPoint->y : 0;
6141 /* This function doesn't support compressed textures
6142 the pitch is just bytesPerPixel * width */
6143 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
6144 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
6145 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
6146 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
6148 /* TODO DXT formats */
6150 if(pSourceRect != NULL && pSourceRect->top != 0){
6151 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
6153 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
6155 ,glDescription->level
6160 ,glDescription->glFormat
6161 ,glDescription->glType
6162 ,IWineD3DSurface_GetData(pSourceSurface)
6166 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
6168 /* need to lock the surface to get the data */
6169 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
6172 /* TODO: Cube and volume support */
6174 /* not a whole row so we have to do it a line at a time */
6177 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
6178 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
6180 for(j = destTop ; j < (srcHeight + destTop) ; j++){
6182 glTexSubImage2D(glDescription->target
6183 ,glDescription->level
6188 ,glDescription->glFormat
6189 ,glDescription->glType
6190 ,data /* could be quicker using */
6195 } else { /* Full width, so just write out the whole texture */
6197 if (WINED3DFMT_DXT1 == destFormat ||
6198 WINED3DFMT_DXT2 == destFormat ||
6199 WINED3DFMT_DXT3 == destFormat ||
6200 WINED3DFMT_DXT4 == destFormat ||
6201 WINED3DFMT_DXT5 == destFormat) {
6202 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
6203 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
6204 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
6205 FIXME("Updating part of a compressed texture is not supported at the moment\n");
6206 } if (destFormat != srcFormat) {
6207 FIXME("Updating mixed format compressed texture is not curretly support\n");
6209 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
6210 glDescription->level,
6211 glDescription->glFormatInternal,
6216 IWineD3DSurface_GetData(pSourceSurface));
6219 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
6224 if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
6226 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
6227 to repack the data from pow2Width/Height to expected Width,Height, this makes the
6228 data returned by GetData non-power2 width/height with hardware non-power2
6229 pow2Width/height are set to surface width height, repacking isn't needed so it
6230 doesn't matter which function gets called. */
6231 glTexSubImage2D(glDescription->target
6232 ,glDescription->level
6237 ,glDescription->glFormat
6238 ,glDescription->glType
6239 ,IWineD3DSurface_GetData(pSourceSurface)
6243 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
6244 glTexSubImage2D(glDescription->target
6245 ,glDescription->level
6248 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
6249 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
6250 ,glDescription->glFormat
6251 ,glDescription->glType
6252 ,IWineD3DSurface_GetData(pSourceSurface)
6258 checkGLcall("glTexSubImage2D");
6260 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
6261 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
6262 * surface bigger than it needs to be hmm.. */
6263 if (WINED3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
6264 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
6265 IWineD3DBaseTexture_Release(baseTexture);
6268 glDisable(textureDimensions); /* This needs to be managed better.... */
6274 /* Used by DirectX 8 */
6275 HRESULT WINAPI IWineD3DDeviceImpl_CopyRects(IWineD3DDevice *iface,
6276 IWineD3DSurface* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
6277 IWineD3DSurface* pDestinationSurface, CONST POINT* pDestPointsArray) {
6279 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6280 HRESULT hr = WINED3D_OK;
6281 WINED3DFORMAT srcFormat, destFormat;
6282 UINT srcWidth, destWidth;
6283 UINT srcHeight, destHeight;
6285 WINED3DSURFACE_DESC winedesc;
6287 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
6288 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
6291 /* Check that the source texture is in WINED3DPOOL_SYSTEMMEM and the destination texture is in WINED3DPOOL_DEFAULT */
6292 memset(&winedesc, 0, sizeof(winedesc));
6294 winedesc.Format = &srcFormat;
6295 winedesc.Width = &srcWidth;
6296 winedesc.Height = &srcHeight;
6297 winedesc.Size = &srcSize;
6298 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
6300 winedesc.Format = &destFormat;
6301 winedesc.Width = &destWidth;
6302 winedesc.Height = &destHeight;
6303 winedesc.Size = NULL;
6304 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6306 /* Check that the source and destination formats match */
6307 if (srcFormat != destFormat && WINED3DFMT_UNKNOWN != destFormat) {
6308 WARN("(%p) source %p format must match the dest %p format, returning WINED3DERR_INVALIDCALL\n", This, pSourceSurface, pDestinationSurface);
6309 return WINED3DERR_INVALIDCALL;
6310 } else if (WINED3DFMT_UNKNOWN == destFormat) {
6311 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
6312 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
6313 destFormat = srcFormat;
6316 /* Quick if complete copy ... */
6317 if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
6319 if (srcWidth == destWidth && srcHeight == destHeight) {
6320 WINED3DLOCKED_RECT lrSrc;
6321 WINED3DLOCKED_RECT lrDst;
6322 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, NULL, WINED3DLOCK_READONLY);
6323 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, NULL, 0L);
6324 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", srcWidth, srcHeight);
6326 memcpy(lrDst.pBits, lrSrc.pBits, srcSize);
6328 IWineD3DSurface_UnlockRect(pSourceSurface);
6329 IWineD3DSurface_UnlockRect(pDestinationSurface);
6330 TRACE("Unlocked src and dst\n");
6334 FIXME("Wanted to copy all surfaces but size not compatible, returning WINED3DERR_INVALIDCALL\n");
6335 hr = WINED3DERR_INVALIDCALL;
6340 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
6342 int bytesPerPixel = ((IWineD3DSurfaceImpl *) pSourceSurface)->bytesPerPixel;
6345 /* Copy rect by rect */
6346 for (i = 0; i < cRects; ++i) {
6347 CONST RECT* r = &pSourceRectsArray[i];
6348 CONST POINT* p = &pDestPointsArray[i];
6351 WINED3DLOCKED_RECT lrSrc;
6352 WINED3DLOCKED_RECT lrDst;
6355 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
6356 if (srcFormat == WINED3DFMT_DXT1) {
6357 copyperline = ((r->right - r->left) * bytesPerPixel) / 2; /* DXT1 is half byte per pixel */
6359 copyperline = ((r->right - r->left) * bytesPerPixel);
6362 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, r, WINED3DLOCK_READONLY);
6363 dest_rect.left = p->x;
6364 dest_rect.top = p->y;
6365 dest_rect.right = p->x + (r->right - r->left);
6366 dest_rect.bottom= p->y + (r->bottom - r->top);
6367 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, &dest_rect, 0L);
6368 TRACE("Locked src and dst\n");
6370 /* Find where to start */
6371 for (j = 0; j < (r->bottom - r->top - 1); ++j) {
6372 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
6374 IWineD3DSurface_UnlockRect(pSourceSurface);
6375 IWineD3DSurface_UnlockRect(pDestinationSurface);
6376 TRACE("Unlocked src and dst\n");
6379 FIXME("Wanted to copy partial surfaces not implemented, returning WINED3DERR_INVALIDCALL\n");
6380 hr = WINED3DERR_INVALIDCALL;
6387 /* Implementation details at http://developer.nvidia.com/attach/6494
6389 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
6390 hmm.. no longer supported use
6391 OpenGL evaluators or tessellate surfaces within your application.
6394 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
6395 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
6396 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6397 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
6398 FIXME("(%p) : Stub\n", This);
6403 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
6404 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
6405 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6406 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
6407 FIXME("(%p) : Stub\n", This);
6411 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
6412 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6413 TRACE("(%p) Handle(%d)\n", This, Handle);
6414 FIXME("(%p) : Stub\n", This);
6418 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
6419 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
6420 fill a surface with a block of color! */
6421 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6422 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
6423 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
6424 IWineD3DSwapChainImpl *container = NULL;
6425 BOOL isRenderTarget = FALSE;
6426 unsigned int width, height;
6427 unsigned int top, left;
6430 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
6432 if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
6433 FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
6434 return WINED3DERR_INVALIDCALL;
6437 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
6438 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
6439 if (WINED3DUSAGE_RENDERTARGET & surface->resource.usage) {
6440 /* TODO: make sure we set everything back to the way it was, and context management!
6441 glGetIntegerv(GL_READ_BUFFER, &prev_read);
6442 vcheckGLcall("glIntegerv");
6443 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
6444 vcheckGLcall("glIntegerv");
6446 TRACE("Color fill to render targets may cause some graphics issues\n");
6447 if (pSurface == container->frontBuffer) {
6448 glDrawBuffer(GL_FRONT);
6450 glDrawBuffer(GL_BACK);
6453 if (WINED3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
6454 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld\n", surface, surface->resource.usage);
6456 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
6458 if (container != NULL) {
6459 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
6461 /* we can use GL_STENCIL_INDEX etc...*/
6464 if (container != NULL) {
6465 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
6467 isRenderTarget = TRUE;
6469 /* TODO: drawing to GL_FRONT and GL_BACK */
6470 /* TODO: see if things can be speeded up by using the correct
6471 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
6472 if (pRect == NULL) {
6475 width = surface->currentDesc.Width;
6476 height = surface->currentDesc.Height;
6480 width = pRect->x2 - left;
6481 height = pRect->y2 - top;
6484 data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
6485 /* Create a 'line' of color color, in the correct format for the surface */
6486 for (u = 0 ; u < width ; u ++) {
6491 if (isRenderTarget == FALSE) {
6492 glDescriptor *glDesc;
6493 IWineD3DSurface_PreLoad(pSurface);
6495 /* draw a block of the coloured line on the sufrace */
6496 IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
6497 for (v = 0 ; v< height;v++) {
6498 glTexSubImage2D(glDesc->target
6499 ,glDesc->level /* level */
6509 checkGLcall("glTexSubImage2D");
6511 glDisable(glDesc->target);
6513 /** FIXME: Using GLClear may be faster **/
6514 glRasterPos2i(left, top);
6515 glPixelZoom((float)width ,(float)height);
6516 glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
6517 checkGLcall("glDrawPixels");
6519 HeapFree(GetProcessHeap(), 0, data);
6525 /* rendertarget and deptth stencil functions */
6526 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
6527 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6529 /* FIXME: Implelent RenderTargetIndex >0 */
6530 if(RenderTargetIndex > 0)
6531 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
6533 *ppRenderTarget = This->renderTarget;
6534 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
6535 /* Note inc ref on returned surface */
6536 if(*ppRenderTarget != NULL)
6537 IWineD3DSurface_AddRef(*ppRenderTarget);
6541 HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
6542 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6543 IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
6544 IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
6545 IWineD3DSwapChainImpl *Swapchain;
6548 TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
6550 hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
6551 if(hr != WINED3D_OK) {
6552 ERR("Can't get the swapchain\n");
6556 /* Make sure to release the swapchain */
6557 IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
6559 if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
6560 ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6561 return WINED3DERR_INVALIDCALL;
6563 else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
6564 ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6565 return WINED3DERR_INVALIDCALL;
6568 if(Swapchain->frontBuffer != Front) {
6569 TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
6571 if(Swapchain->frontBuffer)
6572 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
6573 Swapchain->frontBuffer = Front;
6575 if(Swapchain->frontBuffer) {
6576 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
6579 if(Swapchain->backBuffer != Back) {
6580 TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
6582 if(!Swapchain->backBuffer) {
6583 /* GL was told to draw to the front buffer at creation,
6586 glDrawBuffer(GL_BACK);
6587 checkGLcall("glDrawBuffer(GL_BACK)");
6589 /* That makes problems - disable for now */
6590 /* glDrawBuffer(GL_FRONT); */
6591 checkGLcall("glDrawBuffer(GL_FRONT)");
6595 if(Swapchain->backBuffer)
6596 IWineD3DSurface_SetContainer(Swapchain->backBuffer, NULL);
6597 Swapchain->backBuffer = Back;
6599 if(Swapchain->backBuffer) {
6600 IWineD3DSurface_SetContainer(Swapchain->backBuffer, (IWineD3DBase *) Swapchain);
6608 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
6609 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6610 *ppZStencilSurface = This->depthStencilBuffer;
6611 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
6613 if(*ppZStencilSurface != NULL) {
6614 /* Note inc ref on returned surface */
6615 IWineD3DSurface_AddRef(*ppZStencilSurface);
6620 /* internal static helper functions */
6621 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
6622 IWineD3DSurface *RenderSurface);
6624 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
6625 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6626 HRESULT hr = WINED3D_OK;
6627 WINED3DVIEWPORT viewport;
6629 TRACE("(%p) Swapping rendertarget\n",This);
6630 if (RenderTargetIndex > 0) {
6631 FIXME("(%p) Render targets other than the first are not supported\n",This);
6632 RenderTargetIndex = 0;
6635 /* MSDN says that null disables the render target
6636 but a device must always be associated with a render target
6637 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
6639 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
6642 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
6643 FIXME("Trying to set render target 0 to NULL\n");
6644 return WINED3DERR_INVALIDCALL;
6646 /* TODO: replace Impl* usage with interface usage */
6647 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
6648 FIXME("(%p)Trying to set the render target to a surface(%p) that wasn't created with a usage of WINED3DUSAGE_RENDERTARGET\n",This ,pRenderTarget);
6649 return WINED3DERR_INVALIDCALL;
6651 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
6652 * builds, but I think wine counts as a 'debug' build for now.
6653 ******************************/
6654 /* If we are trying to set what we already have, don't bother */
6655 if (pRenderTarget == This->renderTarget) {
6656 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6658 /* Otherwise, set the render target up */
6660 if (FALSE == This->sceneEnded) {
6661 IWineD3DDevice_EndScene(iface);
6663 TRACE("clearing renderer\n");
6664 /* IWineD3DDeviceImpl_CleanRender(iface); */
6665 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6666 depending on the renter target implementation being used.
6667 A shared context implementation will share all buffers between all rendertargets (including swapchains),
6668 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6669 stencil buffer and incure an extra memory overhead */
6670 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
6673 if (SUCCEEDED(hr)) {
6674 /* Finally, reset the viewport as the MSDN states. */
6675 /* TODO: Replace impl usage */
6676 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
6677 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
6680 viewport.MaxZ = 1.0f;
6681 viewport.MinZ = 0.0f;
6682 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
6684 FIXME("Unknown error setting the render target\n");
6686 This->sceneEnded = FALSE;
6690 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
6691 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6692 HRESULT hr = WINED3D_OK;
6693 IWineD3DSurface *tmp;
6695 TRACE("(%p) Swapping z-buffer\n",This);
6697 if (pNewZStencil == This->stencilBufferTarget) {
6698 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6700 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6701 * depending on the renter target implementation being used.
6702 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
6703 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6704 * stencil buffer and incure an extra memory overhead
6705 ******************************************************/
6708 tmp = This->stencilBufferTarget;
6709 This->stencilBufferTarget = pNewZStencil;
6710 /* should we be calling the parent or the wined3d surface? */
6711 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
6712 if (NULL != tmp) IWineD3DSurface_Release(tmp);
6714 /** TODO: glEnable/glDisable on depth/stencil depending on
6715 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
6716 **********************************************************/
6723 #ifdef GL_VERSION_1_3
6724 /* Internal functions not in DirectX */
6725 /** TODO: move this off to the opengl context manager
6726 *(the swapchain doesn't need to know anything about offscreen rendering!)
6727 ****************************************************/
6729 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
6731 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6733 TRACE("(%p), %p\n", This, swapchain);
6735 if (swapchain->win != swapchain->drawable) {
6736 /* Set everything back the way it ws */
6737 swapchain->render_ctx = swapchain->glCtx;
6738 swapchain->drawable = swapchain->win;
6743 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
6744 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
6745 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6748 unsigned int height;
6749 WINED3DFORMAT format;
6750 WINED3DSURFACE_DESC surfaceDesc;
6751 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
6752 surfaceDesc.Width = &width;
6753 surfaceDesc.Height = &height;
6754 surfaceDesc.Format = &format;
6755 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
6757 /* I need a get width/height function (and should do something with the format) */
6758 for (i = 0; i < CONTEXT_CACHE; ++i) {
6759 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
6760 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
6761 the pSurface can be set to 0 allowing it to be reused from cache **/
6762 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
6763 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
6764 *context = &This->contextCache[i];
6767 if (This->contextCache[i].Width == 0) {
6768 This->contextCache[i].pSurface = pSurface;
6769 This->contextCache[i].Width = width;
6770 This->contextCache[i].Height = height;
6771 *context = &This->contextCache[i];
6775 if (i == CONTEXT_CACHE) {
6776 int minUsage = 0x7FFFFFFF; /* MAX_INT */
6777 glContext *dropContext = 0;
6778 for (i = 0; i < CONTEXT_CACHE; i++) {
6779 if (This->contextCache[i].usedcount < minUsage) {
6780 dropContext = &This->contextCache[i];
6781 minUsage = This->contextCache[i].usedcount;
6784 /* clean up the context (this doesn't work for ATI at the moment */
6786 glXDestroyContext(swapchain->display, dropContext->context);
6787 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
6790 dropContext->Width = 0;
6791 dropContext->pSurface = pSurface;
6792 *context = dropContext;
6794 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
6795 for (i = 0; i < CONTEXT_CACHE; i++) {
6796 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
6800 if (*context != NULL)
6803 return E_OUTOFMEMORY;
6807 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
6808 * the functionality needs splitting up so that we don't do more than we should do.
6809 * this only seems to impact performance a little.
6810 ******************************/
6811 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
6812 IWineD3DSurface *RenderSurface) {
6813 HRESULT ret = WINED3DERR_INVALIDCALL;
6816 * Currently only active for GLX >= 1.3
6817 * for others versions we'll have to use GLXPixmaps
6819 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
6820 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
6821 * so only check OpenGL version
6822 * ..........................
6823 * I don't believe that it is a problem with NVidia headers,
6824 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
6825 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
6827 * Your application will report GLX version 1.2 on glXQueryVersion.
6828 * However, it is safe to call the GLX 1.3 functions as described below.
6830 #if defined(GL_VERSION_1_3)
6832 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6833 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
6834 IWineD3DSurface *tmp;
6835 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
6836 GLXFBConfig* cfgs = NULL;
6840 IWineD3DSwapChain *currentSwapchain;
6841 IWineD3DSwapChainImpl *swapchain;
6842 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
6843 * but switch them off if the StencilSurface is set to NULL
6844 ** *********************************************************/
6845 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
6846 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
6849 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
6850 it StencilSurface != NULL && zBufferTarget == NULL switch it on
6853 #define PUSH1(att) attribs[nAttribs++] = (att);
6854 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
6856 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
6858 /** TODO: remove the reff to Impl (context manager should fix this!) **/
6859 IWineD3DSwapChainImpl *impSwapChain;
6860 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
6861 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
6862 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
6867 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
6868 PUSH2(GLX_X_RENDERABLE, TRUE);
6869 PUSH2(GLX_DOUBLEBUFFER, TRUE);
6870 TRACE("calling makeglcfg\n");
6871 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
6874 TRACE("calling chooseFGConfig\n");
6875 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
6878 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
6879 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
6880 why we failed and only show this message once! */
6881 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"); /**/
6883 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
6884 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
6885 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
6886 PUSH2(GLX_DOUBLEBUFFER, FALSE);
6887 TRACE("calling makeglcfg\n");
6888 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
6890 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
6897 for (i = 0; i < nCfgs; ++i) {
6898 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
6899 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
6900 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
6903 if (NULL != This->renderTarget) {
6905 vcheckGLcall("glFlush");
6906 /** This is only useful if the old render target was a swapchain,
6907 * we need to supercede this with a function that displays
6908 * the current buffer on the screen. This is easy to do in glx1.3 but
6909 * we need to do copy-write pixels in glx 1.2.
6910 ************************************************/
6911 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
6913 printf("Hit Enter to get next frame ...\n");
6919 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain) != WINED3D_OK) {
6920 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
6921 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
6925 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
6926 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
6927 **********************************************************************/
6928 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == WINED3D_OK) {
6929 /* We also need to make sure that the lights &co are also in the context of the swapchains */
6930 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
6931 TRACE("making swapchain active\n");
6932 if (RenderSurface != This->renderTarget) {
6933 if (RenderSurface == swapchain->backBuffer) {
6935 /* This could be flagged so that some operations work directly with the front buffer */
6936 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
6938 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
6940 TRACE("Error in setting current context: context %p drawable %ld !\n",
6941 impSwapChain->glCtx, impSwapChain->win);
6944 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
6946 checkGLcall("glXMakeContextCurrent");
6948 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
6950 else if (pbuffer_support && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
6952 /** ********************************************************************
6953 * This is a quickly hacked out implementation of offscreen textures.
6954 * It will work in most cases but there may be problems if the client
6955 * modifies the texture directly, or expects the contents of the rendertarget
6958 * There are some real speed vs compatibility issues here:
6959 * we should really use a new context for every texture, but that eats ram.
6960 * we should also be restoring the texture to the pbuffer but that eats CPU
6961 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
6962 * but if this means reusing the display backbuffer then we need to make sure that
6963 * states are correctly preserved.
6964 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
6965 * and gain a good performance increase at the cost of compatibility.
6966 * I would suggest that, when this is the case, a user configurable flag be made
6967 * available, allowing the user to choose the best emulated experience for them.
6968 *********************************************************************/
6970 XVisualInfo *visinfo;
6971 glContext *newContext;
6973 /* Here were using a shared context model */
6974 if (WINED3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
6975 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6978 /* If the context doesn't exist then create a new one */
6979 /* TODO: This should really be part of findGlContext */
6980 if (NULL == newContext->context) {
6982 TRACE("making new buffer\n");
6984 PUSH2(GLX_PBUFFER_WIDTH, newContext->Width);
6985 PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
6988 newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
6990 /** ****************************************
6991 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
6993 * In future releases, we may provide the calls glXCreateNewContext,
6994 * glXQueryDrawable and glXMakeContextCurrent.
6995 * so until then we have to use glXGetVisualFromFBConfig &co..
6996 ********************************************/
6999 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
7001 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
7003 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
7007 if (NULL == newContext || NULL == newContext->context) {
7008 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
7010 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
7011 if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
7012 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
7015 /* Clean up the old context */
7016 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
7017 /* Set the current context of the swapchain to the new context */
7018 impSwapChain->drawable = newContext->drawable;
7019 impSwapChain->render_ctx = newContext->context;
7023 #if 1 /* Apply the stateblock to the new context
7024 FIXME: This is a bit of a hack, each context should know it's own state,
7025 the directX current directX state should then be applied to the context */
7028 IWineD3DStateBlockImpl *oldUpdateStateBlock;
7029 oldUpdateStateBlock = This->updateStateBlock;
7030 oldRecording= This->isRecordingState;
7031 This->isRecordingState = FALSE;
7032 This->updateStateBlock = This->stateBlock;
7033 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
7035 This->isRecordingState = oldRecording;
7036 This->updateStateBlock = oldUpdateStateBlock;
7041 /* clean up the current rendertargets swapchain (if it belonged to one) */
7042 if (currentSwapchain != NULL) {
7043 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
7046 /* Were done with the opengl context management, setup the rendertargets */
7048 tmp = This->renderTarget;
7049 This->renderTarget = RenderSurface;
7050 IWineD3DSurface_AddRef(This->renderTarget);
7051 IWineD3DSurface_Release(tmp);
7057 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
7058 /* Check that the container is not a swapchain member */
7060 IWineD3DSwapChain *tmpSwapChain;
7061 if (WINED3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
7062 This->renderUpsideDown = TRUE;
7064 This->renderUpsideDown = FALSE;
7065 IWineD3DSwapChain_Release(tmpSwapChain);
7067 /* Force updating the cull mode */
7068 TRACE("setting render state\n");
7069 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
7070 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
7072 /* Force updating projection matrix */
7073 This->last_was_rhw = FALSE;
7074 This->proj_valid = FALSE;
7082 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
7083 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
7088 if ( NULL != impSwapChain) {
7089 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
7097 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
7098 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
7099 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7100 /* TODO: the use of Impl is deprecated. */
7101 /* some basic validation checks */
7102 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
7104 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
7106 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
7107 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
7108 return WINED3DERR_INVALIDCALL;
7110 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
7111 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
7112 return WINED3DERR_INVALIDCALL;
7114 /* TODO: make the cursor 'real' */
7116 This->xHotSpot = XHotSpot;
7117 This->yHotSpot = YHotSpot;
7122 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
7123 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7124 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
7126 This->xScreenSpace = XScreenSpace;
7127 This->yScreenSpace = YScreenSpace;
7133 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
7134 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7135 TRACE("(%p) : visible(%d)\n", This, bShow);
7137 This->bCursorVisible = bShow;
7142 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
7143 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7144 TRACE("(%p) : state (%lu)\n", This, This->state);
7145 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
7146 switch (This->state) {
7149 case WINED3DERR_DEVICELOST:
7151 ResourceList *resourceList = This->resources;
7152 while (NULL != resourceList) {
7153 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
7154 return WINED3DERR_DEVICENOTRESET;
7155 resourceList = resourceList->next;
7157 return WINED3DERR_DEVICELOST;
7159 case WINED3DERR_DRIVERINTERNALERROR:
7160 return WINED3DERR_DRIVERINTERNALERROR;
7164 return WINED3DERR_DRIVERINTERNALERROR;
7168 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
7169 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7170 /** FIXME: Resource tracking needs to be done,
7171 * The closes we can do to this is set the priorities of all managed textures low
7172 * and then reset them.
7173 ***********************************************************/
7174 FIXME("(%p) : stub\n", This);
7178 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
7179 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7180 /** FIXME: Resource trascking needs to be done.
7181 * in effect this pulls all non only default
7182 * textures out of video memory and deletes all glTextures (glDeleteTextures)
7183 * and should clear down the context and set it up according to pPresentationParameters
7184 ***********************************************************/
7185 FIXME("(%p) : stub\n", This);
7189 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
7190 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7191 /** FIXME: always true at the moment **/
7192 if(bEnableDialogs == FALSE) {
7193 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
7199 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
7200 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7201 TRACE("(%p) : pParameters %p\n", This, pParameters);
7203 *pParameters = This->createParms;
7207 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
7208 IWineD3DSwapChain *swapchain;
7209 HRESULT hrc = WINED3D_OK;
7211 TRACE("Relaying to swapchain\n");
7213 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7214 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
7215 IWineD3DSwapChain_Release(swapchain);
7220 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
7221 IWineD3DSwapChain *swapchain;
7222 HRESULT hrc = WINED3D_OK;
7224 TRACE("Relaying to swapchain\n");
7226 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7227 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
7228 IWineD3DSwapChain_Release(swapchain);
7234 /** ********************************************************
7235 * Notification functions
7236 ** ********************************************************/
7237 /** This function must be called in the release of a resource when ref == 0,
7238 * the contents of resource must still be correct,
7239 * any handels to other resource held by the caller must be closed
7240 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
7241 *****************************************************/
7242 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7243 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7244 ResourceList* resourceList;
7246 TRACE("(%p) : resource %p\n", This, resource);
7248 EnterCriticalSection(&resourceStoreCriticalSection);
7250 /* add a new texture to the frot of the linked list */
7251 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
7252 resourceList->resource = resource;
7254 /* Get the old head */
7255 resourceList->next = This->resources;
7257 This->resources = resourceList;
7258 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
7261 LeaveCriticalSection(&resourceStoreCriticalSection);
7266 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7267 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7268 ResourceList* resourceList = NULL;
7269 ResourceList* previousResourceList = NULL;
7271 TRACE("(%p) : resource %p\n", This, resource);
7274 EnterCriticalSection(&resourceStoreCriticalSection);
7276 resourceList = This->resources;
7278 while (resourceList != NULL) {
7279 if(resourceList->resource == resource) break;
7280 previousResourceList = resourceList;
7281 resourceList = resourceList->next;
7284 if (resourceList == NULL) {
7285 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
7287 LeaveCriticalSection(&resourceStoreCriticalSection);
7291 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
7293 /* make sure we don't leave a hole in the list */
7294 if (previousResourceList != NULL) {
7295 previousResourceList->next = resourceList->next;
7297 This->resources = resourceList->next;
7301 LeaveCriticalSection(&resourceStoreCriticalSection);
7307 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
7308 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7311 TRACE("(%p) : resource %p\n", This, resource);
7312 switch(IWineD3DResource_GetType(resource)){
7313 case WINED3DRTYPE_SURFACE:
7314 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
7316 case WINED3DRTYPE_TEXTURE:
7317 case WINED3DRTYPE_CUBETEXTURE:
7318 case WINED3DRTYPE_VOLUMETEXTURE:
7319 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
7320 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7321 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7322 This->stateBlock->textures[counter] = NULL;
7324 if (This->updateStateBlock != This->stateBlock ){
7325 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7326 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7327 This->updateStateBlock->textures[counter] = NULL;
7332 case WINED3DRTYPE_VOLUME:
7333 /* TODO: nothing really? */
7335 case WINED3DRTYPE_VERTEXBUFFER:
7336 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
7339 TRACE("Cleaning up stream pointers\n");
7341 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
7342 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
7343 FINDOUT: should changes.streamSource[StreamNumber] be set ?
7345 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7346 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
7347 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
7348 This->updateStateBlock->streamSource[streamNumber] = 0;
7349 /* Set changed flag? */
7352 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) */
7353 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
7354 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
7355 This->stateBlock->streamSource[streamNumber] = 0;
7358 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
7359 else { /* This shouldn't happen */
7360 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
7367 case WINED3DRTYPE_INDEXBUFFER:
7368 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
7369 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7370 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7371 This->updateStateBlock->pIndexData = NULL;
7374 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
7375 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7376 This->stateBlock->pIndexData = NULL;
7382 FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
7387 /* Remove the resoruce from the resourceStore */
7388 IWineD3DDeviceImpl_RemoveResource(iface, resource);
7390 TRACE("Resource released\n");
7394 /**********************************************************
7395 * IWineD3DDevice VTbl follows
7396 **********************************************************/
7398 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
7400 /*** IUnknown methods ***/
7401 IWineD3DDeviceImpl_QueryInterface,
7402 IWineD3DDeviceImpl_AddRef,
7403 IWineD3DDeviceImpl_Release,
7404 /*** IWineD3DDevice methods ***/
7405 IWineD3DDeviceImpl_GetParent,
7406 /*** Creation methods**/
7407 IWineD3DDeviceImpl_CreateVertexBuffer,
7408 IWineD3DDeviceImpl_CreateIndexBuffer,
7409 IWineD3DDeviceImpl_CreateStateBlock,
7410 IWineD3DDeviceImpl_CreateSurface,
7411 IWineD3DDeviceImpl_CreateTexture,
7412 IWineD3DDeviceImpl_CreateVolumeTexture,
7413 IWineD3DDeviceImpl_CreateVolume,
7414 IWineD3DDeviceImpl_CreateCubeTexture,
7415 IWineD3DDeviceImpl_CreateQuery,
7416 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
7417 IWineD3DDeviceImpl_CreateVertexDeclaration,
7418 IWineD3DDeviceImpl_CreateVertexShader,
7419 IWineD3DDeviceImpl_CreatePixelShader,
7420 IWineD3DDeviceImpl_CreatePalette,
7421 /*** Odd functions **/
7422 IWineD3DDeviceImpl_Init3D,
7423 IWineD3DDeviceImpl_Uninit3D,
7424 IWineD3DDeviceImpl_EnumDisplayModes,
7425 IWineD3DDeviceImpl_EvictManagedResources,
7426 IWineD3DDeviceImpl_GetAvailableTextureMem,
7427 IWineD3DDeviceImpl_GetBackBuffer,
7428 IWineD3DDeviceImpl_GetCreationParameters,
7429 IWineD3DDeviceImpl_GetDeviceCaps,
7430 IWineD3DDeviceImpl_GetDirect3D,
7431 IWineD3DDeviceImpl_GetDisplayMode,
7432 IWineD3DDeviceImpl_SetDisplayMode,
7433 IWineD3DDeviceImpl_GetHWND,
7434 IWineD3DDeviceImpl_SetHWND,
7435 IWineD3DDeviceImpl_GetNumberOfSwapChains,
7436 IWineD3DDeviceImpl_GetRasterStatus,
7437 IWineD3DDeviceImpl_GetSwapChain,
7438 IWineD3DDeviceImpl_Reset,
7439 IWineD3DDeviceImpl_SetDialogBoxMode,
7440 IWineD3DDeviceImpl_SetCursorProperties,
7441 IWineD3DDeviceImpl_SetCursorPosition,
7442 IWineD3DDeviceImpl_ShowCursor,
7443 IWineD3DDeviceImpl_TestCooperativeLevel,
7444 IWineD3DDeviceImpl_EnumZBufferFormats,
7445 IWineD3DDeviceImpl_EnumTextureFormats,
7446 /*** Getters and setters **/
7447 IWineD3DDeviceImpl_SetClipPlane,
7448 IWineD3DDeviceImpl_GetClipPlane,
7449 IWineD3DDeviceImpl_SetClipStatus,
7450 IWineD3DDeviceImpl_GetClipStatus,
7451 IWineD3DDeviceImpl_SetCurrentTexturePalette,
7452 IWineD3DDeviceImpl_GetCurrentTexturePalette,
7453 IWineD3DDeviceImpl_SetDepthStencilSurface,
7454 IWineD3DDeviceImpl_GetDepthStencilSurface,
7455 IWineD3DDeviceImpl_SetFVF,
7456 IWineD3DDeviceImpl_GetFVF,
7457 IWineD3DDeviceImpl_SetGammaRamp,
7458 IWineD3DDeviceImpl_GetGammaRamp,
7459 IWineD3DDeviceImpl_SetIndices,
7460 IWineD3DDeviceImpl_GetIndices,
7461 IWineD3DDeviceImpl_SetLight,
7462 IWineD3DDeviceImpl_GetLight,
7463 IWineD3DDeviceImpl_SetLightEnable,
7464 IWineD3DDeviceImpl_GetLightEnable,
7465 IWineD3DDeviceImpl_SetMaterial,
7466 IWineD3DDeviceImpl_GetMaterial,
7467 IWineD3DDeviceImpl_SetNPatchMode,
7468 IWineD3DDeviceImpl_GetNPatchMode,
7469 IWineD3DDeviceImpl_SetPaletteEntries,
7470 IWineD3DDeviceImpl_GetPaletteEntries,
7471 IWineD3DDeviceImpl_SetPixelShader,
7472 IWineD3DDeviceImpl_GetPixelShader,
7473 IWineD3DDeviceImpl_SetPixelShaderConstant,
7474 IWineD3DDeviceImpl_GetPixelShaderConstant,
7475 IWineD3DDeviceImpl_SetPixelShaderConstantB,
7476 IWineD3DDeviceImpl_GetPixelShaderConstantB,
7477 IWineD3DDeviceImpl_SetPixelShaderConstantI,
7478 IWineD3DDeviceImpl_GetPixelShaderConstantI,
7479 IWineD3DDeviceImpl_SetPixelShaderConstantF,
7480 IWineD3DDeviceImpl_GetPixelShaderConstantF,
7481 IWineD3DDeviceImpl_SetPixelShaderConstantN,
7482 IWineD3DDeviceImpl_SetRenderState,
7483 IWineD3DDeviceImpl_GetRenderState,
7484 IWineD3DDeviceImpl_SetRenderTarget,
7485 IWineD3DDeviceImpl_GetRenderTarget,
7486 IWineD3DDeviceImpl_SetFrontBackBuffers,
7487 IWineD3DDeviceImpl_SetSamplerState,
7488 IWineD3DDeviceImpl_GetSamplerState,
7489 IWineD3DDeviceImpl_SetScissorRect,
7490 IWineD3DDeviceImpl_GetScissorRect,
7491 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
7492 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
7493 IWineD3DDeviceImpl_SetStreamSource,
7494 IWineD3DDeviceImpl_GetStreamSource,
7495 IWineD3DDeviceImpl_SetStreamSourceFreq,
7496 IWineD3DDeviceImpl_GetStreamSourceFreq,
7497 IWineD3DDeviceImpl_SetTexture,
7498 IWineD3DDeviceImpl_GetTexture,
7499 IWineD3DDeviceImpl_SetTextureStageState,
7500 IWineD3DDeviceImpl_GetTextureStageState,
7501 IWineD3DDeviceImpl_SetTransform,
7502 IWineD3DDeviceImpl_GetTransform,
7503 IWineD3DDeviceImpl_SetVertexDeclaration,
7504 IWineD3DDeviceImpl_GetVertexDeclaration,
7505 IWineD3DDeviceImpl_SetVertexShader,
7506 IWineD3DDeviceImpl_GetVertexShader,
7507 IWineD3DDeviceImpl_SetVertexShaderConstant,
7508 IWineD3DDeviceImpl_GetVertexShaderConstant,
7509 IWineD3DDeviceImpl_SetVertexShaderConstantB,
7510 IWineD3DDeviceImpl_GetVertexShaderConstantB,
7511 IWineD3DDeviceImpl_SetVertexShaderConstantI,
7512 IWineD3DDeviceImpl_GetVertexShaderConstantI,
7513 IWineD3DDeviceImpl_SetVertexShaderConstantF,
7514 IWineD3DDeviceImpl_GetVertexShaderConstantF,
7515 IWineD3DDeviceImpl_SetVertexShaderConstantN,
7516 IWineD3DDeviceImpl_SetViewport,
7517 IWineD3DDeviceImpl_GetViewport,
7518 IWineD3DDeviceImpl_MultiplyTransform,
7519 IWineD3DDeviceImpl_ValidateDevice,
7520 IWineD3DDeviceImpl_ProcessVertices,
7521 /*** State block ***/
7522 IWineD3DDeviceImpl_BeginStateBlock,
7523 IWineD3DDeviceImpl_EndStateBlock,
7524 /*** Scene management ***/
7525 IWineD3DDeviceImpl_BeginScene,
7526 IWineD3DDeviceImpl_EndScene,
7527 IWineD3DDeviceImpl_Present,
7528 IWineD3DDeviceImpl_Clear,
7530 IWineD3DDeviceImpl_DrawPrimitive,
7531 IWineD3DDeviceImpl_DrawIndexedPrimitive,
7532 IWineD3DDeviceImpl_DrawPrimitiveUP,
7533 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
7534 IWineD3DDeviceImpl_DrawPrimitiveStrided,
7535 IWineD3DDeviceImpl_DrawRectPatch,
7536 IWineD3DDeviceImpl_DrawTriPatch,
7537 IWineD3DDeviceImpl_DeletePatch,
7538 IWineD3DDeviceImpl_ColorFill,
7539 IWineD3DDeviceImpl_UpdateTexture,
7540 IWineD3DDeviceImpl_UpdateSurface,
7541 IWineD3DDeviceImpl_CopyRects,
7542 IWineD3DDeviceImpl_StretchRect,
7543 IWineD3DDeviceImpl_GetRenderTargetData,
7544 IWineD3DDeviceImpl_GetFrontBufferData,
7545 /*** Internal use IWineD3DDevice methods ***/
7546 IWineD3DDeviceImpl_SetupTextureStates,
7547 /*** object tracking ***/
7548 IWineD3DDeviceImpl_ResourceReleased
7552 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
7553 WINED3DRS_ALPHABLENDENABLE ,
7554 WINED3DRS_ALPHAFUNC ,
7555 WINED3DRS_ALPHAREF ,
7556 WINED3DRS_ALPHATESTENABLE ,
7558 WINED3DRS_COLORWRITEENABLE ,
7559 WINED3DRS_DESTBLEND ,
7560 WINED3DRS_DITHERENABLE ,
7561 WINED3DRS_FILLMODE ,
7562 WINED3DRS_FOGDENSITY ,
7564 WINED3DRS_FOGSTART ,
7565 WINED3DRS_LASTPIXEL ,
7566 WINED3DRS_SHADEMODE ,
7567 WINED3DRS_SRCBLEND ,
7568 WINED3DRS_STENCILENABLE ,
7569 WINED3DRS_STENCILFAIL ,
7570 WINED3DRS_STENCILFUNC ,
7571 WINED3DRS_STENCILMASK ,
7572 WINED3DRS_STENCILPASS ,
7573 WINED3DRS_STENCILREF ,
7574 WINED3DRS_STENCILWRITEMASK ,
7575 WINED3DRS_STENCILZFAIL ,
7576 WINED3DRS_TEXTUREFACTOR ,
7587 WINED3DRS_ZWRITEENABLE
7590 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
7591 WINED3DTSS_ADDRESSW ,
7592 WINED3DTSS_ALPHAARG0 ,
7593 WINED3DTSS_ALPHAARG1 ,
7594 WINED3DTSS_ALPHAARG2 ,
7595 WINED3DTSS_ALPHAOP ,
7596 WINED3DTSS_BUMPENVLOFFSET ,
7597 WINED3DTSS_BUMPENVLSCALE ,
7598 WINED3DTSS_BUMPENVMAT00 ,
7599 WINED3DTSS_BUMPENVMAT01 ,
7600 WINED3DTSS_BUMPENVMAT10 ,
7601 WINED3DTSS_BUMPENVMAT11 ,
7602 WINED3DTSS_COLORARG0 ,
7603 WINED3DTSS_COLORARG1 ,
7604 WINED3DTSS_COLORARG2 ,
7605 WINED3DTSS_COLOROP ,
7606 WINED3DTSS_RESULTARG ,
7607 WINED3DTSS_TEXCOORDINDEX ,
7608 WINED3DTSS_TEXTURETRANSFORMFLAGS
7611 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
7612 WINED3DSAMP_ADDRESSU ,
7613 WINED3DSAMP_ADDRESSV ,
7614 WINED3DSAMP_ADDRESSW ,
7615 WINED3DSAMP_BORDERCOLOR ,
7616 WINED3DSAMP_MAGFILTER ,
7617 WINED3DSAMP_MINFILTER ,
7618 WINED3DSAMP_MIPFILTER ,
7619 WINED3DSAMP_MIPMAPLODBIAS ,
7620 WINED3DSAMP_MAXMIPLEVEL ,
7621 WINED3DSAMP_MAXANISOTROPY ,
7622 WINED3DSAMP_SRGBTEXTURE ,
7623 WINED3DSAMP_ELEMENTINDEX
7626 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
7628 WINED3DRS_AMBIENTMATERIALSOURCE ,
7629 WINED3DRS_CLIPPING ,
7630 WINED3DRS_CLIPPLANEENABLE ,
7631 WINED3DRS_COLORVERTEX ,
7632 WINED3DRS_DIFFUSEMATERIALSOURCE ,
7633 WINED3DRS_EMISSIVEMATERIALSOURCE ,
7634 WINED3DRS_FOGDENSITY ,
7636 WINED3DRS_FOGSTART ,
7637 WINED3DRS_FOGTABLEMODE ,
7638 WINED3DRS_FOGVERTEXMODE ,
7639 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
7640 WINED3DRS_LIGHTING ,
7641 WINED3DRS_LOCALVIEWER ,
7642 WINED3DRS_MULTISAMPLEANTIALIAS ,
7643 WINED3DRS_MULTISAMPLEMASK ,
7644 WINED3DRS_NORMALIZENORMALS ,
7645 WINED3DRS_PATCHEDGESTYLE ,
7646 WINED3DRS_POINTSCALE_A ,
7647 WINED3DRS_POINTSCALE_B ,
7648 WINED3DRS_POINTSCALE_C ,
7649 WINED3DRS_POINTSCALEENABLE ,
7650 WINED3DRS_POINTSIZE ,
7651 WINED3DRS_POINTSIZE_MAX ,
7652 WINED3DRS_POINTSIZE_MIN ,
7653 WINED3DRS_POINTSPRITEENABLE ,
7654 WINED3DRS_RANGEFOGENABLE ,
7655 WINED3DRS_SPECULARMATERIALSOURCE ,
7656 WINED3DRS_TWEENFACTOR ,
7657 WINED3DRS_VERTEXBLEND
7660 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
7661 WINED3DTSS_TEXCOORDINDEX ,
7662 WINED3DTSS_TEXTURETRANSFORMFLAGS
7665 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
7666 WINED3DSAMP_DMAPOFFSET